From 7cf43fd7de56253c029cfdfd70249b4ed8fbc1e4 Mon Sep 17 00:00:00 2001 From: Mark Date: Mon, 30 Oct 2017 18:39:55 -0400 Subject: [PATCH 0001/1002] ROE Addon --- addons/roe/ReadMe.md | 26 ++++ addons/roe/roe.lua | 281 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 307 insertions(+) create mode 100644 addons/roe/ReadMe.md create mode 100644 addons/roe/roe.lua diff --git a/addons/roe/ReadMe.md b/addons/roe/ReadMe.md new file mode 100644 index 0000000000..59d872f075 --- /dev/null +++ b/addons/roe/ReadMe.md @@ -0,0 +1,26 @@ +**Author:** Cair
+**Version:** 1.0
+**Date:** Oct. 30, 2017
+ +### ROE ### + +This addon lets you save your currently set objectives to profiles that can be loaded. It can also be configured to remove quests for you. By default, ROE will remove quests that are not in a profile only if their progress is zero. You can customize this to your liking. + + + +#### Commands: #### +1. help - Displays this help menu. +2. save : saves the currently set ROE to the named profile +3. set : attempts to set the ROE objectives in the profile + - Objectives may be canceled automatically based on settings. + - The default setting is to only cancel ROE that have 0 progress if space is needed +4. unset : removes currently set objectives + - By default, this will only remove objectives + - Handles 1:1 replacement, similar to .DAT swapping. +5. settings : toggles the specified setting + * settings: + * clear : removes objectives if space is needed (default true) + * clearprogress : remove objectives even if they have non-zero progress (default false) + * clearall : clears every objective before setting new ones (default false) +6. blacklist [add|remove] : blacklists a quest from ever being removes + - I do not currently have a mapping of quest IDs to names \ No newline at end of file diff --git a/addons/roe/roe.lua b/addons/roe/roe.lua new file mode 100644 index 0000000000..d37e38a5e5 --- /dev/null +++ b/addons/roe/roe.lua @@ -0,0 +1,281 @@ +-- Copyright © 2017, Cair +-- 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 ROE 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 Cair 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 = {} +_addon.name = 'ROE' +_addon.version = '1.0' +_addon.author = "Cair" +_addon.commands = {'roe'} + +packets = require('packets') +config = require('config') +require('logger') + + +local defaults = T{ + profiles = T{ + default = S{}, + }, + blacklist = S{}, + clear = true, + clearprogress = false, + clearall = false, +} + +settings = config.load(defaults) + +_roe = T{ + active = T{}, + complete = T{} +} + + +local function cancel_roe(id) + id = tonumber(id) + + if not id then return end + + if settings.blacklist[id] then return end + + local p = packets.new('outgoing', 0x10d, {['RoE Quest'] = id }) + packets.inject(p) +end + +local function accept_roe(id) + id = tonumber(id) + + if not id or _roe.complete[id] or _roe.active[id] then return end + + local p = packets.new('outgoing', 0x10c, {['RoE Quest'] = id }) + packets.inject(p) +end + +local function eval(...) + assert(loadstring(table.concat({...}, ' ')))() +end + +local function save(name) + if not type(name) == "string" then + error('`save` : specify a profile name') + return + end + + name = name:lower() + + settings.profiles[name] = S(_roe.active:keyset()) + settings:save('global') + notice('saved %d objectives to the profile %s':format(_roe.active:length(), name)) +end + + +local function list() + notice('You have saved the following profiles: ') + notice(settings.profiles:keyset()) +end + +local function set(name) + if not type(name) == "string" then + error('`set` : specify a profile name') + return + end + + name = name:lower() + + if not settings.profiles[name] then + error('`set` : the profile \'%s\' does not exist':format(name)) + return + end + + if type(settings.profiles[name]) == "string" then + settings.profiles[name] = S(settings.profiles[name]:split(','):map(tonumber)) + end + + + + local needed_quests = settings.profiles[name]:diff(_roe.active:keyset()) + local available_slots = 30 - _roe.active:length() + local to_remove = S{} + + if settings.clearall then + to_remove:update(_roe.active:keyset()) + elseif settings.clear then + for id,progress in pairs(_roe.active) do + if (needed_quests:length() - to_remove:length()) <= available_slots then + break + end + if (progress == 0 or settings.clearprogress) and not settings.blacklist[id] then + to_remove:add(id) + end + end + end + + + if (needed_quests:length() - to_remove:length()) > available_slots then + error('you do not have enough available quest slots') + return + end + + for id in to_remove:it() do + cancel_roe(id) + coroutine.sleep(.5) + end + + for id in needed_quests:it() do + accept_roe(id) + coroutine.sleep(.5) + end + + notice('loaded the profile \'%s\'':format(name)) + +end + +local function unset() + for id,progress in pairs(_roe.active:copy()) do + if progress == 0 or settings.clearprogress then + cancel_roe(id) + coroutine.sleep(.5) + end + end +end + +local true_strings = S{'true','t','y','yes','on'} +local false_strings = S{'false','f','n','off'} +local bool_strings = true_strings:union(false_strings) + +local function handle_setting(setting,val) + setting = setting and setting:lower() or setting + val = val and val:lower() or val + + if not setting or not settings:containskey(setting) then + error('specified setting (%s) does not exist':format(setting or '')) + elseif type(settings[setting]) == "boolean" then + if not val or not bool_strings:contains(val) then + settings[setting] = not settings[setting] + elseif true_strings:contains(val) then + settings[setting] = true + else + settings[setting] = false + end + + notice('%s setting is now %s':format(setting, tostring(settings[setting]))) + end + +end + +local function blacklist(add_remove,id) + add_remove = add_remove and add_remove:lower() + id = id and tonumber(id) + + + if add_remove and id then + if add_remove == 'add' then + settings.blacklist:add(id) + notice('roe quest %d added to the blacklist':format(id)) + elseif add_remove == 'remove' then + settings.blacklist:remove(id) + notice('roe quest %d removed from the blacklist':format(id)) + else + error('`blacklist` specify \'add\' or \'remove\'') + end + else + error('`blacklist` requires two args, [add|remove] ') + end + +end + + +local function help() + notice([[ROE - Command List: +1. help - Displays this help menu. +2. save : saves the currently set ROE to the named profile +3. set : attempts to set the ROE objectives in the profile + - Objectives may be canceled automatically based on settings. + - The default setting is to only cancel ROE that have 0 progress if space is needed +4. unset : removes currently set objectives + - By default, this will only remove objectives + - Handles 1:1 replacement, similar to .DAT swapping. +5. settings : toggles the specified setting + * settings: + * clear : removes objectives if space is needed (default true) + * clearprogress : remove objectives even if they have non-zero progress (default false) + * clearall : clears every objective before setting new ones (default false) +6. blacklist [add|remove] : blacklists a quest from ever being removes + - I do not currently have a mapping of quest IDs to names]]) +end + +local cmd_handlers = { + eval = eval, + save = save, + list = list, + set = set, + unset = unset, + setting = handle_setting, + blacklist = blacklist, + help = help, +} + + +local function inc_chunk_handler(id,data) + if id == 0x111 then + _roe.active:clear() + for i = 1,30 do + local offset = 5 + ((i - 1) * 4) + local id,progress = data:unpack('b12b20', offset) + if id > 0 then + _roe.active[id] = progress + end + end + elseif id == 0x112 then + local complete = T{data:unpack('b1':rep(1024),4)}:key_map( + function(k) + return (k + 1024*data:unpack('H', 133) - 1) + end):map( + function(v) + return (v == 1 and true) or false + end) + _roe.complete:update(complete) + end +end + +local function addon_command_handler(command,...) + local cmd = command and command:lower() or "help" + if cmd_handlers[cmd] then + cmd_handlers[cmd](...) + else + error('unknown command `%s`':format(cmd or '')) + end + +end + +local function load_handler() + local last_roe = windower.packets.last_incoming(0x111) + if last_roe then inc_chunk_handler(0x111,last_roe) end +end + +windower.register_event('incoming chunk', inc_chunk_handler) +windower.register_event('addon command', addon_command_handler) +windower.register_event('load', load_handler) \ No newline at end of file From 0a696ffc04dcd412c8cd018c74c1a70ae8379b7f Mon Sep 17 00:00:00 2001 From: Mark Date: Mon, 30 Oct 2017 18:46:05 -0400 Subject: [PATCH 0002/1002] Update addons.xml --- addons/addons.xml | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/addons/addons.xml b/addons/addons.xml index 577dbb5838..13716b00a6 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -180,10 +180,10 @@ DressUp - Cairthenn + Cair Emulates BlinkMeNot functionality. Allows for customization of gear display for you or anyone else. https://github.com/cairface/Lua/issues - http://www.bluegartr.com/members/34070-Cairthenn + https://discord.gg/b275nMv DynamisHelper @@ -214,7 +214,7 @@ FastCS - Cairthenn + Cair Dramatically speeds up cutscenes by disabling the frame rate cap. Requires the config plugin. https://github.com/cairface/Lua/issues https://discord.gg/b275nMv @@ -262,10 +262,10 @@ InfoReplacer - Cairthenn + Cair Replaces outgoing text prefixed by % with respective game information. https://github.com/cairface/Lua/issues - http://www.bluegartr.com/members/34070-Cairthenn + https://discord.gg/b275nMv Itemizer @@ -445,6 +445,13 @@ https://discord.gg/b275nMv https://github.com/trv6/Lua/issues + + ROE + Cair + Let's you save your Records of Eminence objectives to profiles for easily swapping out objectives. + https://github.com/cairface/Lua/issues + https://discord.gg/b275nMv + RollTracker Balloon From 3c6d142f8ae6aef93785a633cefcc6c0fba27e79 Mon Sep 17 00:00:00 2001 From: Mark Date: Mon, 30 Oct 2017 18:48:02 -0400 Subject: [PATCH 0003/1002] Add files via upload From 0178e6a6b40626efca289a4d8b7c9406c66917af Mon Sep 17 00:00:00 2001 From: Mark Date: Mon, 30 Oct 2017 18:53:14 -0400 Subject: [PATCH 0004/1002] Update ReadMe.md --- addons/roe/ReadMe.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/addons/roe/ReadMe.md b/addons/roe/ReadMe.md index 59d872f075..849e860c61 100644 --- a/addons/roe/ReadMe.md +++ b/addons/roe/ReadMe.md @@ -15,12 +15,11 @@ This addon lets you save your currently set objectives to profiles that can be l - Objectives may be canceled automatically based on settings. - The default setting is to only cancel ROE that have 0 progress if space is needed 4. unset : removes currently set objectives - - By default, this will only remove objectives - - Handles 1:1 replacement, similar to .DAT swapping. + - By default, this will only remove objectives without progress made 5. settings : toggles the specified setting * settings: * clear : removes objectives if space is needed (default true) * clearprogress : remove objectives even if they have non-zero progress (default false) * clearall : clears every objective before setting new ones (default false) 6. blacklist [add|remove] : blacklists a quest from ever being removes - - I do not currently have a mapping of quest IDs to names \ No newline at end of file + - I do not currently have a mapping of quest IDs to names From 2148d50d105d9c5eaa0b959fdf8214796181113e Mon Sep 17 00:00:00 2001 From: Mark Date: Mon, 30 Oct 2017 18:53:36 -0400 Subject: [PATCH 0005/1002] Update roe.lua --- addons/roe/roe.lua | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/addons/roe/roe.lua b/addons/roe/roe.lua index d37e38a5e5..76ab6882cf 100644 --- a/addons/roe/roe.lua +++ b/addons/roe/roe.lua @@ -216,8 +216,7 @@ local function help() - Objectives may be canceled automatically based on settings. - The default setting is to only cancel ROE that have 0 progress if space is needed 4. unset : removes currently set objectives - - By default, this will only remove objectives - - Handles 1:1 replacement, similar to .DAT swapping. + - By default, this will only remove objectives without progress made 5. settings : toggles the specified setting * settings: * clear : removes objectives if space is needed (default true) @@ -278,4 +277,4 @@ end windower.register_event('incoming chunk', inc_chunk_handler) windower.register_event('addon command', addon_command_handler) -windower.register_event('load', load_handler) \ No newline at end of file +windower.register_event('load', load_handler) From 373befcad1509696a9c239c5c1c6ab61c60c7754 Mon Sep 17 00:00:00 2001 From: Mark Date: Mon, 30 Oct 2017 19:02:51 -0400 Subject: [PATCH 0006/1002] Update ReadMe.md --- addons/roe/ReadMe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/roe/ReadMe.md b/addons/roe/ReadMe.md index 849e860c61..00d2df95b1 100644 --- a/addons/roe/ReadMe.md +++ b/addons/roe/ReadMe.md @@ -21,5 +21,5 @@ This addon lets you save your currently set objectives to profiles that can be l * clear : removes objectives if space is needed (default true) * clearprogress : remove objectives even if they have non-zero progress (default false) * clearall : clears every objective before setting new ones (default false) -6. blacklist [add|remove] : blacklists a quest from ever being removes +6. blacklist [add|remove] : blacklists a quest from ever being removed - I do not currently have a mapping of quest IDs to names From 94dc08222447f468cf1db308e2a64a38f53503e5 Mon Sep 17 00:00:00 2001 From: Mark Date: Mon, 30 Oct 2017 19:03:11 -0400 Subject: [PATCH 0007/1002] Update roe.lua --- addons/roe/roe.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/roe/roe.lua b/addons/roe/roe.lua index 76ab6882cf..576f995d29 100644 --- a/addons/roe/roe.lua +++ b/addons/roe/roe.lua @@ -222,7 +222,7 @@ local function help() * clear : removes objectives if space is needed (default true) * clearprogress : remove objectives even if they have non-zero progress (default false) * clearall : clears every objective before setting new ones (default false) -6. blacklist [add|remove] : blacklists a quest from ever being removes +6. blacklist [add|remove] : blacklists a quest from ever being removed - I do not currently have a mapping of quest IDs to names]]) end From ac6af95344b39035e1f12732f6f7166ca252a0ee Mon Sep 17 00:00:00 2001 From: Mark Date: Tue, 31 Oct 2017 14:11:45 -0400 Subject: [PATCH 0008/1002] Update roe.lua --- addons/roe/roe.lua | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/addons/roe/roe.lua b/addons/roe/roe.lua index 576f995d29..2c6ef0c9c5 100644 --- a/addons/roe/roe.lua +++ b/addons/roe/roe.lua @@ -51,6 +51,7 @@ settings = config.load(defaults) _roe = T{ active = T{}, complete = T{} + max_count = 30, } @@ -117,7 +118,7 @@ local function set(name) local needed_quests = settings.profiles[name]:diff(_roe.active:keyset()) - local available_slots = 30 - _roe.active:length() + local available_slots = _roe.max_count - _roe.active:length() local to_remove = S{} if settings.clearall then @@ -163,7 +164,7 @@ local function unset() end local true_strings = S{'true','t','y','yes','on'} -local false_strings = S{'false','f','n','off'} +local false_strings = S{'false','f','n','no','off'} local bool_strings = true_strings:union(false_strings) local function handle_setting(setting,val) @@ -241,7 +242,7 @@ local cmd_handlers = { local function inc_chunk_handler(id,data) if id == 0x111 then _roe.active:clear() - for i = 1,30 do + for i = 1, _roe.max_count do local offset = 5 + ((i - 1) * 4) local id,progress = data:unpack('b12b20', offset) if id > 0 then @@ -254,7 +255,7 @@ local function inc_chunk_handler(id,data) return (k + 1024*data:unpack('H', 133) - 1) end):map( function(v) - return (v == 1 and true) or false + return (v == 1) end) _roe.complete:update(complete) end From 6d90880e4c59b05f346a2531eae1c16f8d2b42f6 Mon Sep 17 00:00:00 2001 From: Mark Date: Tue, 31 Oct 2017 14:12:20 -0400 Subject: [PATCH 0009/1002] Update roe.lua --- addons/roe/roe.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/roe/roe.lua b/addons/roe/roe.lua index 2c6ef0c9c5..02f64b103b 100644 --- a/addons/roe/roe.lua +++ b/addons/roe/roe.lua @@ -50,7 +50,7 @@ settings = config.load(defaults) _roe = T{ active = T{}, - complete = T{} + complete = T{}, max_count = 30, } From 23b413ae4c2d6bd3ea71a5dcdc747e413aefd4b8 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 3 Nov 2017 18:05:06 -0700 Subject: [PATCH 0010/1002] Fix bug in gearswap filter_pretarget function that can conflate job ability and weapon skill IDs --- addons/GearSwap/helper_functions.lua | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/addons/GearSwap/helper_functions.lua b/addons/GearSwap/helper_functions.lua index e7084c5c54..62233df0d9 100644 --- a/addons/GearSwap/helper_functions.lua +++ b/addons/GearSwap/helper_functions.lua @@ -641,11 +641,15 @@ function filter_pretarget(action) elseif category == 3 then local available_spells = windower.ffxi.get_spells() bool,err = check_spell(available_spells,action) - elseif category == 7 or category == 9 then - local available = windower.ffxi.get_abilities() - available = S(available.job_abilities):union(S(available.weapon_skills)) + elseif category == 7 then + local available = windower.ffxi.get_abilities().weapon_skills if not available[action.id] then - bool,err = false,"Unable to excute command. You do not have access to that ability." + bool,err = false,"Unable to execute command. You do not have access to that weapon skill." + end + elseif category == 9 then + local available = windower.ffxi.get_abilities().job_abilities + if not available[action.id] then + bool,err = false,"Unable to execute command. You do not have access to that job ability." end elseif category == 25 and (not player.main_job_id == 23 or not windower.ffxi.get_mjob_data().species or not res.monstrosity[windower.ffxi.get_mjob_data().species] or not res.monstrosity[windower.ffxi.get_mjob_data().species].tp_moves[action.id] or From b540ac2e65b16ed418d04d7b2c7ab1d4f3137d31 Mon Sep 17 00:00:00 2001 From: Casey Campbell Date: Fri, 3 Nov 2017 18:59:23 -0700 Subject: [PATCH 0011/1002] Change tabs to spaces --- addons/GearSwap/helper_functions.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/GearSwap/helper_functions.lua b/addons/GearSwap/helper_functions.lua index 62233df0d9..835dc7c49a 100644 --- a/addons/GearSwap/helper_functions.lua +++ b/addons/GearSwap/helper_functions.lua @@ -642,11 +642,11 @@ function filter_pretarget(action) local available_spells = windower.ffxi.get_spells() bool,err = check_spell(available_spells,action) elseif category == 7 then - local available = windower.ffxi.get_abilities().weapon_skills + local available = windower.ffxi.get_abilities().weapon_skills if not available[action.id] then bool,err = false,"Unable to execute command. You do not have access to that weapon skill." end - elseif category == 9 then + elseif category == 9 then local available = windower.ffxi.get_abilities().job_abilities if not available[action.id] then bool,err = false,"Unable to execute command. You do not have access to that job ability." From dca0949600a402bb835b5251c9a0a73d52b89a24 Mon Sep 17 00:00:00 2001 From: Casey Campbell Date: Fri, 3 Nov 2017 21:10:46 -0700 Subject: [PATCH 0012/1002] Fix filter_pretarget function to have proper table checking syntax, instead of always returning nil --- addons/GearSwap/helper_functions.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/GearSwap/helper_functions.lua b/addons/GearSwap/helper_functions.lua index 835dc7c49a..35ebf103d8 100644 --- a/addons/GearSwap/helper_functions.lua +++ b/addons/GearSwap/helper_functions.lua @@ -643,12 +643,12 @@ function filter_pretarget(action) bool,err = check_spell(available_spells,action) elseif category == 7 then local available = windower.ffxi.get_abilities().weapon_skills - if not available[action.id] then + if not table.contains(available,action.id) then bool,err = false,"Unable to execute command. You do not have access to that weapon skill." end elseif category == 9 then local available = windower.ffxi.get_abilities().job_abilities - if not available[action.id] then + if not table.contains(available,action.id) then bool,err = false,"Unable to execute command. You do not have access to that job ability." end elseif category == 25 and (not player.main_job_id == 23 or not windower.ffxi.get_mjob_data().species or From ad4dae2762c69589925dd7a95b2b4d840041d197 Mon Sep 17 00:00:00 2001 From: Mark Date: Sun, 5 Nov 2017 09:35:49 -0500 Subject: [PATCH 0013/1002] ROE: Add the option to unset a profile --- addons/roe/ReadMe.md | 5 +- addons/roe/roe.lua | 578 ++++++++++++++++++++++--------------------- 2 files changed, 300 insertions(+), 283 deletions(-) diff --git a/addons/roe/ReadMe.md b/addons/roe/ReadMe.md index 00d2df95b1..1cbd1410bb 100644 --- a/addons/roe/ReadMe.md +++ b/addons/roe/ReadMe.md @@ -14,8 +14,9 @@ This addon lets you save your currently set objectives to profiles that can be l 3. set : attempts to set the ROE objectives in the profile - Objectives may be canceled automatically based on settings. - The default setting is to only cancel ROE that have 0 progress if space is needed -4. unset : removes currently set objectives - - By default, this will only remove objectives without progress made +4. unset : removes currently set objectives + - if a profile name is specified, every objective in that profile will be removed + - if a profile name is not specificed, all objectives will be removed (based on your settings) 5. settings : toggles the specified setting * settings: * clear : removes objectives if space is needed (default true) diff --git a/addons/roe/roe.lua b/addons/roe/roe.lua index 02f64b103b..a2fc4f9297 100644 --- a/addons/roe/roe.lua +++ b/addons/roe/roe.lua @@ -1,281 +1,297 @@ --- Copyright © 2017, Cair --- 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 ROE 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 Cair 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 = {} -_addon.name = 'ROE' -_addon.version = '1.0' -_addon.author = "Cair" -_addon.commands = {'roe'} - -packets = require('packets') -config = require('config') -require('logger') - - -local defaults = T{ - profiles = T{ - default = S{}, - }, - blacklist = S{}, - clear = true, - clearprogress = false, - clearall = false, -} - -settings = config.load(defaults) - -_roe = T{ - active = T{}, - complete = T{}, - max_count = 30, -} - - -local function cancel_roe(id) - id = tonumber(id) - - if not id then return end - - if settings.blacklist[id] then return end - - local p = packets.new('outgoing', 0x10d, {['RoE Quest'] = id }) - packets.inject(p) -end - -local function accept_roe(id) - id = tonumber(id) - - if not id or _roe.complete[id] or _roe.active[id] then return end - - local p = packets.new('outgoing', 0x10c, {['RoE Quest'] = id }) - packets.inject(p) -end - -local function eval(...) - assert(loadstring(table.concat({...}, ' ')))() -end - -local function save(name) - if not type(name) == "string" then - error('`save` : specify a profile name') - return - end - - name = name:lower() - - settings.profiles[name] = S(_roe.active:keyset()) - settings:save('global') - notice('saved %d objectives to the profile %s':format(_roe.active:length(), name)) -end - - -local function list() - notice('You have saved the following profiles: ') - notice(settings.profiles:keyset()) -end - -local function set(name) - if not type(name) == "string" then - error('`set` : specify a profile name') - return - end - - name = name:lower() - - if not settings.profiles[name] then - error('`set` : the profile \'%s\' does not exist':format(name)) - return - end - - if type(settings.profiles[name]) == "string" then - settings.profiles[name] = S(settings.profiles[name]:split(','):map(tonumber)) - end - - - - local needed_quests = settings.profiles[name]:diff(_roe.active:keyset()) - local available_slots = _roe.max_count - _roe.active:length() - local to_remove = S{} - - if settings.clearall then - to_remove:update(_roe.active:keyset()) - elseif settings.clear then - for id,progress in pairs(_roe.active) do - if (needed_quests:length() - to_remove:length()) <= available_slots then - break - end - if (progress == 0 or settings.clearprogress) and not settings.blacklist[id] then - to_remove:add(id) - end - end - end - - - if (needed_quests:length() - to_remove:length()) > available_slots then - error('you do not have enough available quest slots') - return - end - - for id in to_remove:it() do - cancel_roe(id) - coroutine.sleep(.5) - end - - for id in needed_quests:it() do - accept_roe(id) - coroutine.sleep(.5) - end - - notice('loaded the profile \'%s\'':format(name)) - -end - -local function unset() - for id,progress in pairs(_roe.active:copy()) do - if progress == 0 or settings.clearprogress then - cancel_roe(id) - coroutine.sleep(.5) - end - end -end - -local true_strings = S{'true','t','y','yes','on'} -local false_strings = S{'false','f','n','no','off'} -local bool_strings = true_strings:union(false_strings) - -local function handle_setting(setting,val) - setting = setting and setting:lower() or setting - val = val and val:lower() or val - - if not setting or not settings:containskey(setting) then - error('specified setting (%s) does not exist':format(setting or '')) - elseif type(settings[setting]) == "boolean" then - if not val or not bool_strings:contains(val) then - settings[setting] = not settings[setting] - elseif true_strings:contains(val) then - settings[setting] = true - else - settings[setting] = false - end - - notice('%s setting is now %s':format(setting, tostring(settings[setting]))) - end - -end - -local function blacklist(add_remove,id) - add_remove = add_remove and add_remove:lower() - id = id and tonumber(id) - - - if add_remove and id then - if add_remove == 'add' then - settings.blacklist:add(id) - notice('roe quest %d added to the blacklist':format(id)) - elseif add_remove == 'remove' then - settings.blacklist:remove(id) - notice('roe quest %d removed from the blacklist':format(id)) - else - error('`blacklist` specify \'add\' or \'remove\'') - end - else - error('`blacklist` requires two args, [add|remove] ') - end - -end - - -local function help() - notice([[ROE - Command List: -1. help - Displays this help menu. -2. save : saves the currently set ROE to the named profile -3. set : attempts to set the ROE objectives in the profile - - Objectives may be canceled automatically based on settings. - - The default setting is to only cancel ROE that have 0 progress if space is needed -4. unset : removes currently set objectives - - By default, this will only remove objectives without progress made -5. settings : toggles the specified setting - * settings: - * clear : removes objectives if space is needed (default true) - * clearprogress : remove objectives even if they have non-zero progress (default false) - * clearall : clears every objective before setting new ones (default false) -6. blacklist [add|remove] : blacklists a quest from ever being removed - - I do not currently have a mapping of quest IDs to names]]) -end - -local cmd_handlers = { - eval = eval, - save = save, - list = list, - set = set, - unset = unset, - setting = handle_setting, - blacklist = blacklist, - help = help, -} - - -local function inc_chunk_handler(id,data) - if id == 0x111 then - _roe.active:clear() - for i = 1, _roe.max_count do - local offset = 5 + ((i - 1) * 4) - local id,progress = data:unpack('b12b20', offset) - if id > 0 then - _roe.active[id] = progress - end - end - elseif id == 0x112 then - local complete = T{data:unpack('b1':rep(1024),4)}:key_map( - function(k) - return (k + 1024*data:unpack('H', 133) - 1) - end):map( - function(v) - return (v == 1) - end) - _roe.complete:update(complete) - end -end - -local function addon_command_handler(command,...) - local cmd = command and command:lower() or "help" - if cmd_handlers[cmd] then - cmd_handlers[cmd](...) - else - error('unknown command `%s`':format(cmd or '')) - end - -end - -local function load_handler() - local last_roe = windower.packets.last_incoming(0x111) - if last_roe then inc_chunk_handler(0x111,last_roe) end -end - -windower.register_event('incoming chunk', inc_chunk_handler) -windower.register_event('addon command', addon_command_handler) -windower.register_event('load', load_handler) +-- Copyright © 2017, Cair +-- 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 ROE 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 Cair 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 = {} +_addon.name = 'ROE' +_addon.version = '1.0' +_addon.author = "Cair" +_addon.commands = {'roe'} + +packets = require('packets') +config = require('config') +require('logger') + + +local defaults = T{ + profiles = T{ + default = S{}, + }, + blacklist = S{}, + clear = true, + clearprogress = false, + clearall = false, +} + +settings = config.load(defaults) + +_roe = T{ + active = T{}, + complete = T{}, + max_count = 30, +} + + +local function cancel_roe(id) + id = tonumber(id) + + if not id then return end + + if settings.blacklist[id] or not _roe.active[id] then return end + + local p = packets.new('outgoing', 0x10d, {['RoE Quest'] = id }) + packets.inject(p) +end + +local function accept_roe(id) + id = tonumber(id) + + if not id or _roe.complete[id] or _roe.active[id] then return end + + local p = packets.new('outgoing', 0x10c, {['RoE Quest'] = id }) + packets.inject(p) +end + +local function eval(...) + assert(loadstring(table.concat({...}, ' ')))() +end + +local function save(name) + if not type(name) == "string" then + error('`save` : specify a profile name') + return + end + + name = name:lower() + + settings.profiles[name] = S(_roe.active:keyset()) + settings:save('global') + notice('saved %d objectives to the profile %s':format(_roe.active:length(), name)) +end + + +local function list() + notice('You have saved the following profiles: ') + notice(settings.profiles:keyset()) +end + +local function set(name) + if not type(name) == "string" then + error('`set` : specify a profile name') + return + end + + name = name:lower() + + if not settings.profiles[name] then + error('`set` : the profile \'%s\' does not exist':format(name)) + return + end + + local needed_quests = settings.profiles[name]:diff(_roe.active:keyset()) + local available_slots = _roe.max_count - _roe.active:length() + local to_remove = S{} + + if settings.clearall then + to_remove:update(_roe.active:keyset()) + elseif settings.clear then + for id,progress in pairs(_roe.active) do + if (needed_quests:length() - to_remove:length()) <= available_slots then + break + end + if (progress == 0 or settings.clearprogress) and not settings.blacklist[id] then + to_remove:add(id) + end + end + end + + + if (needed_quests:length() - to_remove:length()) > available_slots then + error('you do not have enough available quest slots') + return + end + + for id in to_remove:it() do + cancel_roe(id) + coroutine.sleep(.5) + end + + for id in needed_quests:it() do + accept_roe(id) + coroutine.sleep(.5) + end + + notice('loaded the profile \'%s\'':format(name)) + +end + +local function unset(name) + + name = name and name:lower() + + if name and settings.profiles[name] then + for id in _roe.active:keyset():intersection(settings.profiles[name]):it() do + cancel_roe(id) + coroutine.sleep(.5) + end + notice('unset the profile \'%s\'':format(name)) + elseif name then + error('`unset` : the profile \'%s\' does not exist':format(name)) + elseif not name then + notice('clearing ROE objectives.') + for id,progress in pairs(_roe.active:copy()) do + if progress == 0 or settings.clearprogress then + cancel_roe(id) + coroutine.sleep(.5) + end + end + end + +end + +local true_strings = S{'true','t','y','yes','on'} +local false_strings = S{'false','f','n','no','off'} +local bool_strings = true_strings:union(false_strings) + +local function handle_setting(setting,val) + setting = setting and setting:lower() or setting + val = val and val:lower() or val + + if not setting or not settings:containskey(setting) then + error('specified setting (%s) does not exist':format(setting or '')) + elseif type(settings[setting]) == "boolean" then + if not val or not bool_strings:contains(val) then + settings[setting] = not settings[setting] + elseif true_strings:contains(val) then + settings[setting] = true + else + settings[setting] = false + end + + notice('%s setting is now %s':format(setting, tostring(settings[setting]))) + end + +end + +local function blacklist(add_remove,id) + add_remove = add_remove and add_remove:lower() + id = id and tonumber(id) + + + if add_remove and id then + if add_remove == 'add' then + settings.blacklist:add(id) + notice('roe quest %d added to the blacklist':format(id)) + elseif add_remove == 'remove' then + settings.blacklist:remove(id) + notice('roe quest %d removed from the blacklist':format(id)) + else + error('`blacklist` specify \'add\' or \'remove\'') + end + else + error('`blacklist` requires two args, [add|remove] ') + end + +end + + +local function help() + notice([[ROE - Command List: +1. help - Displays this help menu. +2. save : saves the currently set ROE to the named profile +3. set : attempts to set the ROE objectives in the profile + - Objectives may be canceled automatically based on settings. + - The default setting is to only cancel ROE that have 0 progress if space is needed +4. unset : removes currently set objectives + - By default, this will only remove objectives without progress made +5. settings : toggles the specified setting + * settings: + * clear : removes objectives if space is needed (default true) + * clearprogress : remove objectives even if they have non-zero progress (default false) + * clearall : clears every objective before setting new ones (default false) +6. blacklist [add|remove] : blacklists a quest from ever being removed + - I do not currently have a mapping of quest IDs to names]]) +end + +local cmd_handlers = { + eval = eval, + save = save, + list = list, + set = set, + unset = unset, + setting = handle_setting, + blacklist = blacklist, + help = help, +} + + +local function inc_chunk_handler(id,data) + if id == 0x111 then + _roe.active:clear() + for i = 1, _roe.max_count do + local offset = 5 + ((i - 1) * 4) + local id,progress = data:unpack('b12b20', offset) + if id > 0 then + _roe.active[id] = progress + end + end + elseif id == 0x112 then + local complete = T{data:unpack('b1':rep(1024),4)}:key_map( + function(k) + return (k + 1024*data:unpack('H', 133) - 1) + end):map( + function(v) + return (v == 1) + end) + _roe.complete:update(complete) + end +end + +local function addon_command_handler(command,...) + local cmd = command and command:lower() or "help" + if cmd_handlers[cmd] then + cmd_handlers[cmd](...) + else + error('unknown command `%s`':format(cmd or '')) + end + +end + +local function load_handler() + for k,v in pairs(settings.profiles) do + if type(v) == "string" then + settings.profiles[k] = S(v:split(','):map(tonumber)) + end + end + + local last_roe = windower.packets.last_incoming(0x111) + if last_roe then inc_chunk_handler(0x111,last_roe) end + +end + +windower.register_event('incoming chunk', inc_chunk_handler) +windower.register_event('addon command', addon_command_handler) +windower.register_event('load', load_handler) From 065a9184fbc24069afea0e9f20b1718375d87eee Mon Sep 17 00:00:00 2001 From: Mark Date: Mon, 6 Nov 2017 13:18:03 -0500 Subject: [PATCH 0014/1002] Update addons.xml --- addons/addons.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/addons.xml b/addons/addons.xml index 13716b00a6..eaeb705ac0 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -447,8 +447,8 @@ ROE - Cair - Let's you save your Records of Eminence objectives to profiles for easily swapping out objectives. + Cair + Lets you save your Records of Eminence objectives to profiles for easily swapping out objectives. https://github.com/cairface/Lua/issues https://discord.gg/b275nMv From 5e7362ac3b088fef0d674b912d0cafd0ed86ea56 Mon Sep 17 00:00:00 2001 From: Mark Date: Tue, 7 Nov 2017 04:22:28 -0500 Subject: [PATCH 0015/1002] DressUp: Get PC names from packet or memory --- addons/DressUp/DressUp.lua | 128 +++++++++++++++++++++---------------- 1 file changed, 72 insertions(+), 56 deletions(-) diff --git a/addons/DressUp/DressUp.lua b/addons/DressUp/DressUp.lua index 5bc08530ae..a7d062097e 100644 --- a/addons/DressUp/DressUp.lua +++ b/addons/DressUp/DressUp.lua @@ -1,4 +1,4 @@ --- Copyright © 2013-2015, Cairthenn +-- Copyright © 2013-2017, Cairthenn -- All rights reserved. -- Redistribution and use in source and binary forms, with or without @@ -25,20 +25,17 @@ -- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'DressUp' -_addon.author = 'Cairthenn' -_addon.version = '1.1' +_addon.author = 'Cair' +_addon.version = '1.2' _addon.commands = {'DressUp','du'} ---Libs -require('luau') -packets = require('packets') - ---DressUp files - +packets = require('packets') +require('luau') require('helper_functions') require('static_variables') + models = {} require('head') require('body') @@ -47,12 +44,22 @@ require('legs') require('feet') settings = config.load(defaults) +info = T{ + names = T{}, + self = T{}, + party = S{} +} + +model_names = S{"Face","Race","Head","Body","Hands","Legs","Feet","Main","Sub","Ranged"} local initialize = function() local player = windower.ffxi.get_player() - _char = player.name:lower() - if not settings[_char] then - settings[_char] = {} + info.self.name = player.name:lower() + info.self.id = player.id + info.self.index = player.index + + if not settings[info.self.name] then + settings[info.self.name] = {} end print_blink_settings("global") @@ -60,7 +67,7 @@ local initialize = function() notice('Loaded profile: ' .. player.main_job) end - update_model(player.index) + update_model(info.self.index) end windower.register_event('load', function() @@ -72,17 +79,16 @@ end) windower.register_event('login', initialize) windower.register_event('logout', function() - _char = nil + info.self:clear() end) windower.register_event('job change',function(job) if load_profile(res.jobs[job].name) then - update_model(windower.ffxi.get_player().index) - notice('Loaded profile: ' .. job) + update_model(info.self.index) + notice('Loaded profile: ' .. res.jobs[job].name) end end) -model_names = S{"Face","Race","Head","Body","Hands","Legs","Feet","Main","Sub","Ranged"} local modify_gear = function(packet, name, freeze, models) local modified = false @@ -109,65 +115,75 @@ local modify_gear = function(packet, name, freeze, models) end windower.register_event('incoming chunk',function (id, _, data) + if id ~= 0x00A and id ~= 0x00D and id ~= 0x051 then return end local packet = packets.parse('incoming', data) - local player = windower.ffxi.get_player() local modified -- Processing based on packet type if id == 0x00A then - if not _char then - return - end - modified,packet = modify_gear(packet, _char) + info.self.id = packet['Player'] + info.self.index = packet['Player Index'] + info.self.name = packet['Player Name']:lower() + modified,packet = modify_gear(packet, info.self.name) return modified and packets.build(packet) end - - -- Check whether the character is loaded into memory yet. - local character = windower.ffxi.get_mob_by_index(packet.Index or player and player.index or -1) -- Target of 0x00D or yourself for 0x051 - local blink_type, models, name = 'others' + + local char_id = packet.Player or info.self.id + local char_index = packet.Index or info.self.index + local character = windower.ffxi.get_mob_by_index(char_index) + local blink_type, name = 'others' + local models + if character and character.models and table.length(character.models) == 9 and (id == 0x051 or (id == 0x00D and character.id == packet.Player) ) then - models = {Race=character.race, - Face = character.models[1], - Head=character.models[2]+0x1000, - Body=character.models[3]+0x2000, - Hands=character.models[4]+0x3000, - Legs=character.models[5]+0x4000, - Feet=character.models[6]+0x5000, - Main=character.models[7]+0x6000, - Sub=character.models[8]+0x7000, - Ranged=character.models[9]+0x8000} - else - return + models = T{ + Race = character.race, + Face = character.models[1], + Head = character.models[2]+0x1000, + Body = character.models[3]+0x2000, + Hands = character.models[4]+0x3000, + Legs = character.models[5]+0x4000, + Feet = character.models[6]+0x5000, + Main = character.models[7]+0x6000, + Sub = character.models[8]+0x7000, + Ranged = character.models[9]+0x8000}) end - - if character then - if player.follow_index == character.index then - blink_type = "follow" - elseif character.in_alliance then - blink_type = "party" - else - blink_type = "others" - end - if character.name == player.name then - name = _char - blink_type = "self" - elseif settings[character.name:lower()] then - name = character.name:lower() + if not info.names[char_id] then + if packet['Update Name'] then + info.names[char_id] = packet['Character Name']:lower() + elseif character then + info.names[char_id] = character.name:lower() else - name = "others" + return end + end + + local player = windower.ffxi.get_player() + + if player.follow_index == char_index then + blink_type = "follow" + elseif character and character.in_alliance then + blink_type = "party" + else + blink_type = "others" + end + + if info.names[char_id] == info.self.name then + name = info.self.name + blink_type = "self" + elseif settings[info.names[char_id]] then + name = info.names[char_id] else name = "others" end -- Model ID 0xFFFF in ranged slot signifies a monster. This prevents undesired results. - modified,packet = modify_gear(packet, name or _char, blink_logic(blink_type, character, player), models) + modified,packet = modify_gear(packet, name, blink_logic(blink_type, char_index, player), models) return packet['Ranged'] ~= 0xFFFF and modified and packets.build(packet) end) @@ -224,7 +240,7 @@ windower.register_event('addon command', function (command,...) if command == "player" then command = args:remove(1) elseif command == "self" then - command = _char + command = info.self.name end if not settings[command] then @@ -453,7 +469,7 @@ windower.register_event('addon command', function (command,...) return end end - if settings.autoupdate and ((command == _char) or (_clear == _char)) then + if settings.autoupdate and ((command == info.self.name) or (_clear == info.self.name)) then update_model(windower.ffxi.get_player().index) end From 35bd309dd97f9d54c5644cf4c2266a787952f4e7 Mon Sep 17 00:00:00 2001 From: Mark Date: Tue, 7 Nov 2017 04:35:27 -0500 Subject: [PATCH 0016/1002] DU: Missed file :( --- addons/DressUp/helper_functions.lua | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/addons/DressUp/helper_functions.lua b/addons/DressUp/helper_functions.lua index 866283454b..162d605a05 100644 --- a/addons/DressUp/helper_functions.lua +++ b/addons/DressUp/helper_functions.lua @@ -71,7 +71,7 @@ function save_profile(name) notice('Saved your current settings to the profile: ' .. name) end -function blink_logic(blink_type,character,player) +function blink_logic(blink_type,character_index,player) if settings.blinking["all"]["always"] then return true elseif settings.blinking[blink_type]["always"] then @@ -83,10 +83,12 @@ function blink_logic(blink_type,character,player) elseif settings.blinking[blink_type]["combat"] and player.in_combat then return true end - - if settings.blinking["all"]["target"] and player.target_index == character.index then + + log(settings.blinking["all"]["target"], player.target_index, character_index) + + if settings.blinking["all"]["target"] and player.target_index == character_index then return true - elseif settings.blinking[blink_type]["target"] and player.target_index == character.index then + elseif settings.blinking[blink_type]["target"] and player.target_index == character_index then return true end From 1550df0b435794481334509ff045a76192f74eef Mon Sep 17 00:00:00 2001 From: Mark Date: Tue, 7 Nov 2017 05:03:05 -0500 Subject: [PATCH 0017/1002] DU: remove mysterious debug message -don't know how that happened -don't commit things when half asleep --- addons/DressUp/helper_functions.lua | 2 -- 1 file changed, 2 deletions(-) diff --git a/addons/DressUp/helper_functions.lua b/addons/DressUp/helper_functions.lua index 162d605a05..7d84543285 100644 --- a/addons/DressUp/helper_functions.lua +++ b/addons/DressUp/helper_functions.lua @@ -83,8 +83,6 @@ function blink_logic(blink_type,character_index,player) elseif settings.blinking[blink_type]["combat"] and player.in_combat then return true end - - log(settings.blinking["all"]["target"], player.target_index, character_index) if settings.blinking["all"]["target"] and player.target_index == character_index then return true From e7709c2ddc3f9ad982622bd76e97a680e4ae6fc3 Mon Sep 17 00:00:00 2001 From: Mark Date: Tue, 7 Nov 2017 13:46:37 -0500 Subject: [PATCH 0018/1002] Syntax error --- addons/DressUp/DressUp.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/DressUp/DressUp.lua b/addons/DressUp/DressUp.lua index a7d062097e..4d87477b24 100644 --- a/addons/DressUp/DressUp.lua +++ b/addons/DressUp/DressUp.lua @@ -150,7 +150,7 @@ windower.register_event('incoming chunk',function (id, _, data) Feet = character.models[6]+0x5000, Main = character.models[7]+0x6000, Sub = character.models[8]+0x7000, - Ranged = character.models[9]+0x8000}) + Ranged = character.models[9]+0x8000} end if not info.names[char_id] then From c5b2416603cf57489bf37a2717a5e1aa602ff38b Mon Sep 17 00:00:00 2001 From: Mark Date: Tue, 7 Nov 2017 21:52:19 -0500 Subject: [PATCH 0019/1002] DU: Properly clear self settings --- addons/DressUp/DressUp.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/DressUp/DressUp.lua b/addons/DressUp/DressUp.lua index 4d87477b24..5d6b96a2de 100644 --- a/addons/DressUp/DressUp.lua +++ b/addons/DressUp/DressUp.lua @@ -360,7 +360,7 @@ windower.register_event('addon command', function (command,...) if _clear == "player" then _clear = args:remove(1) elseif _clear == "self" then - _clear = _char + _clear = info.self.name end local _selection = S{"head","body","hands","legs","feet","main","sub","ranged","race","face"}:contains(args[1]) and args:remove(1) From 4221c3bd41c19fa168cfa3dc63182e7d1d98bf87 Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 9 Nov 2017 12:10:49 -0500 Subject: [PATCH 0020/1002] DU: Login runtime error fix --- addons/DressUp/DressUp.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/DressUp/DressUp.lua b/addons/DressUp/DressUp.lua index 5d6b96a2de..9025b12ce4 100644 --- a/addons/DressUp/DressUp.lua +++ b/addons/DressUp/DressUp.lua @@ -134,7 +134,7 @@ windower.register_event('incoming chunk',function (id, _, data) local char_id = packet.Player or info.self.id local char_index = packet.Index or info.self.index - local character = windower.ffxi.get_mob_by_index(char_index) + local character = windower.ffxi.get_mob_by_index(char_index or -1) local blink_type, name = 'others' local models From 3f5df4eff969a59fbabdbcba0e8b1051f8161e7f Mon Sep 17 00:00:00 2001 From: funkworkz Date: Fri, 10 Nov 2017 13:32:46 -0600 Subject: [PATCH 0021/1002] Update setbgm.lua Updated name for #84, added #86, #87, #88 and #89 --- addons/setbgm/setbgm.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/setbgm/setbgm.lua b/addons/setbgm/setbgm.lua index 1a246e9213..6e94b9ebb9 100644 --- a/addons/setbgm/setbgm.lua +++ b/addons/setbgm/setbgm.lua @@ -54,7 +54,7 @@ songs = { [50]='Feast of the Ladies', [51]='Abyssea - Scarlet Skies, Shadowed Plains', [52]='Melodies Errant', [53]='Shinryu', [54]='Everlasting Bonds', [55]='Provenance Watcher', [56]='Where it All Begins', [57]='Steel Sings, Blades Dance', [58]='A New Direction', [59]='The Pioneers', [60]='Into Lands Primeval - Ulbuka', [61]="Water's Umbral Knell", [62]='Keepers of the Wild', [63]='The Sacred City of Adoulin', [64]='Breaking Ground', [65]='Hades', [66]='Arciela', [67]='Mog Resort', [68]='Worlds Away', [69]="Distant Worlds (Nanaa Mihgo's version)", [70]='Monstrosity', [71]="The Pioneers (Nanaa Mihgo's version)", [72]='The Serpentine Labyrinth', [73]='The Divine', [74]='Clouds Over Ulbuka', [75]='The Price', [76]='Forever Today', [77]='Distant Worlds (Instrumental)', [78]='Forever Today (Instrumental)', [79]='Iroha', - [80]='The Boundless Black', [81]='Isle of the Gods', [82]='Wail of the Void', [83]="Rhapsodies of Vana'diel", [84]="Unknown", [85]="Ambuscade", + [80]='The Boundless Black', [81]='Isle of the Gods', [82]='Wail of the Void', [83]="Rhapsodies of Vana'diel", [84]="Mount", [85]="Ambuscade", [86]="FFRK Shadow Lord", [87]="Omen", [88]="Dynamis Divergence", [89]="Unknown", [101]='Battle Theme', [102]='Battle in the Dungeon #2', [103]='Battle Theme #2', [104]='A Road Once Traveled', [105]='Mhaura', [106]='Voyager', [107]="The Kingdom of San d'Oria", [108]="Vana'diel March", [109]='Ronfaure', [110]='The Grand Duchy of Jeuno', [111]='Blackout', [112]='Selbina', [113]='Sarutabaruta', [114]='Batallia Downs', [115]='Battle in the Dungeon', [116]='Gustaberg', [117]="Ru'Lude Gardens", [118]='Rolanberry Fields', [119]='Awakening', [120]="Vana'diel March #2", [121]='Shadow Lord', [122]='One Last Time', [123]='Hopelessness', [124]='Recollection', [125]='Tough Battle', [126]='Mog House', [127]='Anxiety', [128]='Airship', [129]='Hook, Line and Sinker', From 99637803405cded0090b34ac52aecb18b743532b Mon Sep 17 00:00:00 2001 From: Mark Date: Fri, 10 Nov 2017 18:29:15 -0500 Subject: [PATCH 0022/1002] Fix runtime error building outgoing packet 0x4e --- addons/libs/packets/fields.lua | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index ee0d18f51d..51272fc188 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -577,14 +577,10 @@ func.outgoing[0x04E][0x10] = L{ } -- Auction Interaction -fields.outgoing[0x04E] = function() - local self = func.outgoing[0x04E] - local fields = self.base - - return function(data, type) - return self.base + (self[type or data:byte(5)] or L{}) - end -end() +fields.outgoing[0x04E] = function(data, type) + type = type or data and data:byte(5) + return func.outgoing[0x04E].base + (func.outgoing[0x04E][type] or L{}) +end -- Equip fields.outgoing[0x050] = L{ From c9bf49e309c854c854d3b82a115c91a2c5b814b0 Mon Sep 17 00:00:00 2001 From: Mark Date: Sat, 11 Nov 2017 19:13:31 -0500 Subject: [PATCH 0023/1002] Add missing guild list fields --- addons/libs/packets/fields.lua | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 51272fc188..48143e6f91 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -3068,6 +3068,10 @@ types.guild_entry = L{ -- Guild Inv List fields.incoming[0x083] = L{ {ref=types.guild_entry, label='Item', count='*'}, -- 04 + {ctype='unsigned char', label='Item Count'}, + {ctype='bit[4]', label='Order'}, + {ctype='bit[4]', label='_unknown'}, + {ctype='unsigned short', label='_padding'} } -- Guild Sell Response @@ -3081,6 +3085,10 @@ fields.incoming[0x084] = L{ -- Guild Sale List fields.incoming[0x085] = L{ {ref=types.guild_entry, label='Item', count='*'}, -- 04 + {ctype='unsigned char', label='Item Count'}, + {ctype='bit[4]', label='Order'}, + {ctype='bit[4]', label='_unknown'}, + {ctype='unsigned short', label='_padding'} } -- Guild Open -- Sent to update guild status or open the guild menu. From 1583d06cd19f68383112018600199fe6cadcaac2 Mon Sep 17 00:00:00 2001 From: Mark Date: Sat, 11 Nov 2017 19:21:15 -0500 Subject: [PATCH 0024/1002] Add item counts to guild packets --- addons/libs/packets/fields.lua | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 48143e6f91..e3b72f72ec 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -3067,11 +3067,11 @@ types.guild_entry = L{ } -- Guild Inv List fields.incoming[0x083] = L{ - {ref=types.guild_entry, label='Item', count='*'}, -- 04 - {ctype='unsigned char', label='Item Count'}, - {ctype='bit[4]', label='Order'}, - {ctype='bit[4]', label='_unknown'}, - {ctype='unsigned short', label='_padding'} + {ref=types.guild_entry, label='Item', count='30'}, -- 04 + {ctype='unsigned char', label='Item Count'}, -- F4 + {ctype='bit[4]', label='Order'}, -- F5 + {ctype='bit[4]', label='_unknown'}, + {ctype='unsigned short', label='_padding'} -- F6 } -- Guild Sell Response @@ -3084,11 +3084,11 @@ fields.incoming[0x084] = L{ -- Guild Sale List fields.incoming[0x085] = L{ - {ref=types.guild_entry, label='Item', count='*'}, -- 04 - {ctype='unsigned char', label='Item Count'}, - {ctype='bit[4]', label='Order'}, - {ctype='bit[4]', label='_unknown'}, - {ctype='unsigned short', label='_padding'} + {ref=types.guild_entry, label='Item', count='30'}, -- 04 + {ctype='unsigned char', label='Item Count'}, -- F4 + {ctype='bit[4]', label='Order'}, -- F5 + {ctype='bit[4]', label='_unknown'}, + {ctype='unsigned short', label='_padding'} -- F6 } -- Guild Open -- Sent to update guild status or open the guild menu. From af4472056b9913b930cd9dae2a3cea7bdff484c8 Mon Sep 17 00:00:00 2001 From: Mark Date: Wed, 22 Nov 2017 15:03:18 -0500 Subject: [PATCH 0025/1002] DU: Allow changing of model ids that can be 0 * Model IDs were set to 0 in incoming chunk 0x0D if `Update Models` was false * Fixes #1600 --- addons/DressUp/DressUp.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/addons/DressUp/DressUp.lua b/addons/DressUp/DressUp.lua index 9025b12ce4..cf3d4225a8 100644 --- a/addons/DressUp/DressUp.lua +++ b/addons/DressUp/DressUp.lua @@ -26,7 +26,7 @@ _addon.name = 'DressUp' _addon.author = 'Cair' -_addon.version = '1.2' +_addon.version = '1.21' _addon.commands = {'DressUp','du'} @@ -94,7 +94,7 @@ local modify_gear = function(packet, name, freeze, models) local modified = false for k, v in pairs(packet) do - if model_names:contains(k) and v ~= 0 then + if model_names[k] then if rawget(settings, name) and settings[name][k:lower()] then -- Settings for individuals packet[k] = settings[name][k:lower()] @@ -132,6 +132,10 @@ windower.register_event('incoming chunk',function (id, _, data) return modified and packets.build(packet) end + if id == 0x0D and not p['Update Model'] then + return + end + local char_id = packet.Player or info.self.id local char_index = packet.Index or info.self.index local character = windower.ffxi.get_mob_by_index(char_index or -1) From 4257c88464b6487ac1e63607cdefb9bc4346255c Mon Sep 17 00:00:00 2001 From: Mark Date: Wed, 22 Nov 2017 15:42:43 -0500 Subject: [PATCH 0026/1002] DU: Typo --- addons/DressUp/DressUp.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/DressUp/DressUp.lua b/addons/DressUp/DressUp.lua index cf3d4225a8..85ea1e48e6 100644 --- a/addons/DressUp/DressUp.lua +++ b/addons/DressUp/DressUp.lua @@ -132,7 +132,7 @@ windower.register_event('incoming chunk',function (id, _, data) return modified and packets.build(packet) end - if id == 0x0D and not p['Update Model'] then + if id == 0x0D and not packet['Update Model'] then return end From 7a6f5ebd80d843ff4be21c0bfefbd31ec121baf6 Mon Sep 17 00:00:00 2001 From: zetaepyon Date: Wed, 22 Nov 2017 19:32:45 -0600 Subject: [PATCH 0027/1002] BoxDestroyer: Update messages for Nov update Update the messages for the boxdestroyer addon --- addons/boxdestroyer/messages.lua | 116 +++++++++++++++---------------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/addons/boxdestroyer/messages.lua b/addons/boxdestroyer/messages.lua index 235863866c..51c4c1e906 100644 --- a/addons/boxdestroyer/messages.lua +++ b/addons/boxdestroyer/messages.lua @@ -1,61 +1,61 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination" for the associated zone IDs - [100] = 8054, - [101] = 7503, - [102] = 7905, - [103] = 8080, - [104] = 8645, - [105] = 7696, - [106] = 8070, - [107] = 7531, - [108] = 7600, - [109] = 8463, - [110] = 7587, - [111] = 8564, - [112] = 8166, - [113] = 7926, - [114] = 7765, - [115] = 7861, - [116] = 7557, - [117] = 7564, - [118] = 8106, - [119] = 8343, - [120] = 7503, - [121] = 8083, - [122] = 7432, - [123] = 7866, - [124] = 7817, - [125] = 7627, - [126] = 8050, - [127] = 7349, - [128] = 7504, - [130] = 7567, - [153] = 11393, - [158] = 7379, - [159] = 8442, - [160] = 7406, - [166] = 10576, - [167] = 10590, - [169] = 7536, - [172] = 7410, - [173] = 10515, - [174] = 11392, - [176] = 7601, - [177] = 11216, - [178] = 11397, - [190] = 8250, - [191] = 8370, - [192] = 7406, - [193] = 8382, - [194] = 8262, - [195] = 7593, - [196] = 8302, - [197] = 7347, - [198] = 8268, - [200] = 7524, - [204] = 7512, - [205] = 11479, - [208] = 8281, - [212] = 10636, - [213] = 10445, + [100] = 8055, + [101] = 7504, + [102] = 7906, + [103] = 8081, + [104] = 8646, + [105] = 7697, + [106] = 8071, + [107] = 7532, + [108] = 7601, + [109] = 8464, + [110] = 7588, + [111] = 8565, + [112] = 8167, + [113] = 7927, + [114] = 7766, + [115] = 7862, + [116] = 7558, + [117] = 7565, + [118] = 8107, + [119] = 8344, + [120] = 7504, + [121] = 8084, + [122] = 7433, + [123] = 7867, + [124] = 7818, + [125] = 7628, + [126] = 8051, + [127] = 7350, + [128] = 7505, + [130] = 7568, + [153] = 11394, + [158] = 7380, + [159] = 8443, + [160] = 7407, + [166] = 10577, + [167] = 10591, + [169] = 7537, + [172] = 7411, + [173] = 10516, + [174] = 11393, + [176] = 7602, + [177] = 11217, + [178] = 11398, + [190] = 8251, + [191] = 8371, + [192] = 7407, + [193] = 8383, + [194] = 8263, + [195] = 7594, + [196] = 8303, + [197] = 7348, + [198] = 8269, + [200] = 7525, + [204] = 7513, + [205] = 11480, + [208] = 8282, + [212] = 10637, + [213] = 10446, } offsets = {greater_less=1, failure=2, success=4, second_even_odd=5, first_even_odd=6, range=7, less=8, greater=9, equal=10, second_multiple=11, first_multiple=12} From 4d6b28bb8c1078087a2f969af2fe61e5a92d7b5b Mon Sep 17 00:00:00 2001 From: Mark Date: Fri, 24 Nov 2017 03:05:29 -0500 Subject: [PATCH 0028/1002] Packets/fields: Update incoming 0x34 --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index e3b72f72ec..baaa1f7520 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1908,7 +1908,7 @@ fields.incoming[0x034] = L{ {ctype='unsigned short', label='NPC Index', fn=index}, -- 28 {ctype='unsigned short', label='Zone', fn=zone}, -- 2A {ctype='unsigned short', label='Menu ID'}, -- 2C Seems to select between menus within a zone - {ctype='unsigned short', label='_unknown1', const=0x08}, -- 2E 08 00 for me, but FFing did nothing + {ctype='unsigned short', label='_unknown1',} -- 2E Ususually 8, but often not for newer menus {ctype='unsigned short', label='_dupeZone', fn=zone}, -- 30 {ctype='data[2]', label='_junk1'}, -- 31 Always 00s for me } From 512582870fb7ea502a43beb3de04ea1a194ba56b Mon Sep 17 00:00:00 2001 From: Mark Date: Fri, 24 Nov 2017 03:36:02 -0500 Subject: [PATCH 0029/1002] Update fields.lua --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index baaa1f7520..b5185aab31 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1908,7 +1908,7 @@ fields.incoming[0x034] = L{ {ctype='unsigned short', label='NPC Index', fn=index}, -- 28 {ctype='unsigned short', label='Zone', fn=zone}, -- 2A {ctype='unsigned short', label='Menu ID'}, -- 2C Seems to select between menus within a zone - {ctype='unsigned short', label='_unknown1',} -- 2E Ususually 8, but often not for newer menus + {ctype='unsigned short', label='_unknown1'}, -- 2E Ususually 8, but often not for newer menus {ctype='unsigned short', label='_dupeZone', fn=zone}, -- 30 {ctype='data[2]', label='_junk1'}, -- 31 Always 00s for me } From 7ef812d6fb26e9754f5ad422a542f3336815a4ee Mon Sep 17 00:00:00 2001 From: Mark Date: Fri, 1 Dec 2017 17:30:26 -0500 Subject: [PATCH 0030/1002] Extdata: Fix crafting shield parsing The stage four 'units' is probably incorrect too, but I don't have a shield to test it --- addons/libs/extdata.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/extdata.lua b/addons/libs/extdata.lua index 863cabba59..a392074fc4 100644 --- a/addons/libs/extdata.lua +++ b/addons/libs/extdata.lua @@ -1589,8 +1589,8 @@ function decode.Augmented(str) if flag_2%16/8 >= 1 then -- Crafting shields rettab.objective = str:byte(6) - local units = {30,40,50,100} - rettab.stage = math.min(1,math.max(4,str:byte(0x9))) + local units = {30,50,100,100} + rettab.stage = math.max(1,math.min(4,str:byte(0x9))) rettab.completion = str:unpack('H',7)/units[rettab.stage] elseif flag_2%64/32 >=1 then rettab.augment_system = 2 From 4bc552b9a9c0a1979f6db0b52ca8453344b2aa9c Mon Sep 17 00:00:00 2001 From: Mark Date: Sat, 2 Dec 2017 18:13:17 -0500 Subject: [PATCH 0031/1002] Fix #1604 --- addons/craft/craft.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/addons/craft/craft.lua b/addons/craft/craft.lua index 050ee2e228..6546486b4a 100644 --- a/addons/craft/craft.lua +++ b/addons/craft/craft.lua @@ -131,7 +131,7 @@ craft - Command List: * put "Dragon Mask" safe2 - Moves all Dragon Masks to Mog Safe 2 (if available). 5. delay - Sets the delay between crafting attempts - (default 24) + (default 24, minimum 20) * delay 30 - Sets the delay between crafting to 30 seconds.]] @@ -505,6 +505,7 @@ local function check_queue() consume_food() end local fn, arg = unpack(queue:pop()) + log(fn,arg) local msg = fn(arg) if msg then error(msg) @@ -549,7 +550,8 @@ local function handle_delay(seconds) if n == nil then return "Invalid delay %s":format(seconds) else - notice("Setting delay to %s":format(seconds)) + n = math.max(20, n) + notice("Setting delay to %d":format(n)) delay = n end end From b8722d2ca063bbcf6edebea17a3e214ecf0ec604 Mon Sep 17 00:00:00 2001 From: Mark Date: Fri, 8 Dec 2017 20:29:17 -0500 Subject: [PATCH 0032/1002] Craft: remove debug statement --- addons/craft/craft.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/craft/craft.lua b/addons/craft/craft.lua index 6546486b4a..ef4e0ce9ae 100644 --- a/addons/craft/craft.lua +++ b/addons/craft/craft.lua @@ -505,7 +505,6 @@ local function check_queue() consume_food() end local fn, arg = unpack(queue:pop()) - log(fn,arg) local msg = fn(arg) if msg then error(msg) From 86d2da31039ff83b8630db6f7641c45e14ccc379 Mon Sep 17 00:00:00 2001 From: Mark Date: Sun, 10 Dec 2017 14:44:27 -0500 Subject: [PATCH 0033/1002] Craft: Lower minimum delay slightly for shields --- addons/craft/craft.lua | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/addons/craft/craft.lua b/addons/craft/craft.lua index ef4e0ce9ae..3081a64f9e 100644 --- a/addons/craft/craft.lua +++ b/addons/craft/craft.lua @@ -131,7 +131,7 @@ craft - Command List: * put "Dragon Mask" safe2 - Moves all Dragon Masks to Mog Safe 2 (if available). 5. delay - Sets the delay between crafting attempts - (default 24, minimum 20) + (default 24, minimum 17) * delay 30 - Sets the delay between crafting to 30 seconds.]] @@ -320,6 +320,7 @@ local function consume_item(item) end local function fetch_ingredient(ingredient) + local id, name if exceptions[ingredient] then id = exceptions[ingredient] @@ -403,7 +404,12 @@ local function hash(crystal, item, count) end local function build_recipe(item) + if windower.ffxi.get_player().status ~= 0 then + return "You can't craft at the moment" + end + local recipe = fetch_recipe(item) + if recipe then inventory = windower.ffxi.get_items() appropriated = {} @@ -549,7 +555,7 @@ local function handle_delay(seconds) if n == nil then return "Invalid delay %s":format(seconds) else - n = math.max(20, n) + n = math.max(17, n) notice("Setting delay to %d":format(n)) delay = n end From 7dc05fa95be6ae093ec942a87d92bda20f595b2c Mon Sep 17 00:00:00 2001 From: Mark Date: Sun, 17 Dec 2017 07:29:28 -0500 Subject: [PATCH 0034/1002] Box destroyer: update messages --- addons/boxdestroyer/messages.lua | 116 +++++++++++++++---------------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/addons/boxdestroyer/messages.lua b/addons/boxdestroyer/messages.lua index 51c4c1e906..968133f33f 100644 --- a/addons/boxdestroyer/messages.lua +++ b/addons/boxdestroyer/messages.lua @@ -1,61 +1,61 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination" for the associated zone IDs - [100] = 8055, - [101] = 7504, - [102] = 7906, - [103] = 8081, - [104] = 8646, - [105] = 7697, - [106] = 8071, - [107] = 7532, - [108] = 7601, - [109] = 8464, - [110] = 7588, - [111] = 8565, - [112] = 8167, - [113] = 7927, - [114] = 7766, - [115] = 7862, - [116] = 7558, - [117] = 7565, - [118] = 8107, - [119] = 8344, - [120] = 7504, - [121] = 8084, - [122] = 7433, - [123] = 7867, - [124] = 7818, - [125] = 7628, - [126] = 8051, - [127] = 7350, - [128] = 7505, - [130] = 7568, - [153] = 11394, - [158] = 7380, - [159] = 8443, - [160] = 7407, - [166] = 10577, - [167] = 10591, - [169] = 7537, - [172] = 7411, - [173] = 10516, - [174] = 11393, - [176] = 7602, - [177] = 11217, - [178] = 11398, - [190] = 8251, - [191] = 8371, - [192] = 7407, - [193] = 8383, - [194] = 8263, - [195] = 7594, - [196] = 8303, - [197] = 7348, - [198] = 8269, - [200] = 7525, - [204] = 7513, - [205] = 11480, - [208] = 8282, - [212] = 10637, - [213] = 10446, + [100] = 8057, + [101] = 7503, + [102] = 7908, + [103] = 8083, + [104] = 8648, + [105] = 7699, + [106] = 8073, + [107] = 7534, + [108] = 7603, + [109] = 8466, + [110] = 7590, + [111] = 8567, + [112] = 8169, + [113] = 7926, + [114] = 7768, + [115] = 7864, + [116] = 7560, + [117] = 7567, + [118] = 8109, + [119] = 8346, + [120] = 7506, + [121] = 8086, + [122] = 7432, + [123] = 7869, + [124] = 7820, + [125] = 7630, + [126] = 8053, + [127] = 7349, + [128] = 7504, + [130] = 7567, + [153] = 11393, + [158] = 7379, + [159] = 8442, + [160] = 7406, + [166] = 10576, + [167] = 10590, + [169] = 7536, + [172] = 7410, + [173] = 10515, + [174] = 11392, + [176] = 7601, + [177] = 11216, + [178] = 11397, + [190] = 8250, + [191] = 8370, + [192] = 7406, + [193] = 8382, + [194] = 8262, + [195] = 7593, + [196] = 8302, + [197] = 7347, + [198] = 8268, + [200] = 7524, + [204] = 7512, + [205] = 11479, + [208] = 8281, + [212] = 10636, + [213] = 10445, } offsets = {greater_less=1, failure=2, success=4, second_even_odd=5, first_even_odd=6, range=7, less=8, greater=9, equal=10, second_multiple=11, first_multiple=12} From 3e6d2bd66d963c660134223bbc80a34e9c1f2273 Mon Sep 17 00:00:00 2001 From: Mark Date: Sun, 17 Dec 2017 07:30:07 -0500 Subject: [PATCH 0035/1002] Gearswap: Inject action closer to midcast equip --- addons/GearSwap/flow.lua | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/addons/GearSwap/flow.lua b/addons/GearSwap/flow.lua index 033e16adf9..45a0387e7c 100644 --- a/addons/GearSwap/flow.lua +++ b/addons/GearSwap/flow.lua @@ -184,6 +184,11 @@ function equip_sets(swap_type,ts,...) chunk_table:append(minichunk) end end + + if swap_type == 'midcast' and command_registry[ts] and command_registry[ts].proposed_packet and not _settings.demo_mode then + windower.packets.inject_outgoing(command_registry[ts].proposed_packet:byte(1),command_registry[ts].proposed_packet) + end + if chunk_table.n >= 3 then local big_chunk = string.char(0x51,0x24,0,0,chunk_table.n,0,0,0) for i=1,chunk_table.n do @@ -424,9 +429,6 @@ end ---- none ----------------------------------------------------------------------------------- function send_action(ts) - if command_registry[ts].proposed_packet then - if not _settings.demo_mode then windower.packets.inject_outgoing(command_registry[ts].proposed_packet:byte(1),command_registry[ts].proposed_packet) end - command_registry[ts].midaction = true - equip_sets('midcast',ts,command_registry[ts].spell) - end + command_registry[ts].midaction = true + equip_sets('midcast',ts,command_registry[ts].spell) end \ No newline at end of file From eab165c9521ce2a59d47f71eea86a6f8fd34012c Mon Sep 17 00:00:00 2001 From: Mark Date: Wed, 3 Jan 2018 22:56:20 -0500 Subject: [PATCH 0036/1002] Fields: Update outgoing job point increase --- addons/libs/packets/fields.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index b5185aab31..d2af2c0e5f 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -899,9 +899,9 @@ fields.outgoing[0x0BE] = L{ } -- Job Point Increase --- This chunk was sent on three consecutive outgoing packets the only time I've used it fields.outgoing[0x0BF] = L{ - {ctype='unsigned short', label='Job Point'}, -- 04 + {ctype='bit[5]', label='Type'}, -- 04 + {ctype='bit[11]', label='Job', fn=job}, -- 04 {ctype='unsigned short', label='_junk1', const=0x0000}, -- 06 No values seen so far } From 226e9e2841c3ba40736de35092b6f33fac2c26bf Mon Sep 17 00:00:00 2001 From: azamorapl Date: Mon, 15 Jan 2018 19:25:22 -0500 Subject: [PATCH 0037/1002] Add giltracker addon --- addons/giltracker/README.md | 26 +++++ addons/giltracker/gil.png | Bin 0 -> 1399 bytes addons/giltracker/giltracker.lua | 182 +++++++++++++++++++++++++++++++ 3 files changed, 208 insertions(+) create mode 100644 addons/giltracker/README.md create mode 100644 addons/giltracker/gil.png create mode 100644 addons/giltracker/giltracker.lua diff --git a/addons/giltracker/README.md b/addons/giltracker/README.md new file mode 100644 index 0000000000..683a8eb1ac --- /dev/null +++ b/addons/giltracker/README.md @@ -0,0 +1,26 @@ +# giltracker +This addon displays the current gil, similar to the FFXIV Gil HUD widget. + +![Imgur](https://i.imgur.com/vZ8NkDr.png) + +## How to install: +1. Download the repository [here](https://github.com/azamorapl/Lua/archive/personal.zip) +2. Extract the **_giltracker_** folder to your **_Windower4/addons_** folder + +## How to enable it in-game: +1. Login to your character in FFXI +2. Press insert to access the windower console +3. Type ``` lua l giltracker ``` + +## How to have windower load it automatically: +1. Go to your windower folder +2. Open the file **_Windower4/scripts/init.txt_** +3. Add the following line to the end of the file ``` lua l giltracker ``` + +## How to edit the settings +1. Login to your character in FFXI +2. Edit the addon settings file: **_Windower4\addons\giltracker\data\settings.xml_** +3. Save the file +4. Press Insert in FFXI to access the windower console +5. Type ``` lua r giltracker ``` to reload the addon +6. Press Insert in FFXI again to close the windower console diff --git a/addons/giltracker/gil.png b/addons/giltracker/gil.png new file mode 100644 index 0000000000000000000000000000000000000000..df56142f25f24bd769c89fffc7afdf941795467e GIT binary patch literal 1399 zcmV--1&I2IP)WFU8GbZ8()Nlj2>E@cM*00i4fL_t(Y$90umOj~6b z$A9P0mbR3%mO^NO78tm8g#v>xWNvdybeqn_Wbr~56TcGUh1Vt~-g@Ju-k4~-*lu)F zlSSt=!rZ1p28&-?zK=lMU+c^{#-{{>`O zM$YFE%S2>Zh5{hK^u$N5k-dZ3a&hSu=UBp4Wuamd##P!K=>q3`)qYAp9hhYFv*Zs(IP zx&Zk3a+sOv7y#aOGgFiCCuGqXDzI5a0LB7YzPvKeTW^0L?8u_XdVh4N@bNo#&b{UY z;Iog$@g1=OaQd8Gg~>Zv2tJ6bYpXGto;EFwjxs7tPNEc`ARz8;IQ^WNGyN9T%s|l~qqJryPM(lP2 z)4@3FQikAzIN@ks^?V_k2cXk!;?lQYA=K8^7LIiq`0#>-+v7>9O=>W__ihuRnN9V5 zEtY0&DWMp4=>WJjyn)rC!_{CU97$rf*5Prb7#K4P8USyzP6f2Km;jg!B~)OQRj)oP zbQ!8^idnTv~5e9c|U>x0U4_&PE+$ zBS~UXhM1JWWKs;eT}gsr10GkZAOa=O*-%2AkC)OsT1v1O-NYYQDJj99u1GjtI@NOk zSA)Wdt}1IHq%r70tIaDl+g58xoQv6=ey8(nSyIi{ALWTKqd@rqpzX)mUby1a&;yr0ktt$Z%&QSrVNJ zZ)?#jcgTxoIy}mKG7(JesT7&TXrAy=ajnr|;G6Fyo;EZ9gQH5~21hrk4sJiO>CsZ2 zI(r!tQ(2B2HmDKoAFYi#{2{2bWe7$LXwqp&XSAH`wQ%#UgvFs;X|Y(2<9$Y2oE5Y< z;lD_VP-Kf60}80GON$iCallnheVv{*cO^FlRxnr&V74Whe{59hd@_{eWUr;fi^XV$ zjy5Ah<8kH|Q(Szt7J!Ef3FabshR3rsH#^x3kjfckLEU#v$v5E9`X`ia|g=0(1KQ;<#Lfzg@VKS8D=3NP^ zwfOh>1I6smEvBfk=~!Ns0l0Wx{{+~3(8Rr2^WJJH00r&^)|d*V(dcy4)Ec?^`zEu| zJe3uKIybhq$!SDHLm77_^VBwI5sWsbR+?}+O}J_jTpuwA!AJq!Gu_2fbToGhqk$E^ z{z3T@j~=d661$dDJ&8oOskfKm4`x}DWcb>om4qp$yT)&FYcl1PwZtd+p0IpoV zROs(C(cUa#t Date: Mon, 15 Jan 2018 19:26:26 -0500 Subject: [PATCH 0038/1002] Add invtracker addon --- addons/invtracker/README.md | 31 +++ addons/invtracker/invtracker.lua | 460 +++++++++++++++++++++++++++++++ addons/invtracker/slot.png | Bin 0 -> 167 bytes 3 files changed, 491 insertions(+) create mode 100644 addons/invtracker/README.md create mode 100644 addons/invtracker/invtracker.lua create mode 100644 addons/invtracker/slot.png diff --git a/addons/invtracker/README.md b/addons/invtracker/README.md new file mode 100644 index 0000000000..fbf8cd9f7a --- /dev/null +++ b/addons/invtracker/README.md @@ -0,0 +1,31 @@ +# invtracker +This addon displays a grid detailing empty and filled inventory slots, similar to the FFXIV Inventory Grid HUD widget. + +![Imgur](https://i.imgur.com/PgiMxRZ.png) + +## How to install: +1. Download the repository [here](https://github.com/azamorapl/Lua/archive/personal.zip) +2. Extract the **_invtracker_** folder to your **_Windower4/addons_** folder + +## How to enable it in-game: +1. Login to your character in FFXI +2. Press insert to access the windower console +3. Type ``` lua l invtracker ``` + +## How to have windower load it automatically: +1. Go to your windower folder +2. Open the file **_Windower4/scripts/init.txt_** +3. Add the following line to the end of the file ``` lua l invtracker ``` + +## How to edit the settings +1. Login to your character in FFXI +2. Edit the addon settings file: **_Windower4\addons\invtracker\data\settings.xml_** +3. Save the file +4. Press Insert in FFXI to access the windower console +5. Type ``` lua r invtracker ``` to reload the addon +6. Press Insert in FFXI again to close the windower console + +## Issues: +1. Since there is no way to know many items determine a full stack, all regular items are painted blue. Instead, bazaar equipped items are painted orange, linkshell and equipped items are painted green, and temporary items are painted red. +2. There is no way to get the inventory sort order, so all items in the grid will be ordered by status and item count. +3. You may need to log out from you character and enter again in order to have the addon display properly if loaded manually. diff --git a/addons/invtracker/invtracker.lua b/addons/invtracker/invtracker.lua new file mode 100644 index 0000000000..6df103b29c --- /dev/null +++ b/addons/invtracker/invtracker.lua @@ -0,0 +1,460 @@ +--[[ BSD License Disclaimer + Copyright © 2017, sylandro + 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 invtracker 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 sylandro 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.name = 'invtracker' +_addon.author = 'sylandro' +_addon.version = '1.0.0' +_addon.language = 'English' + +config = require('config') +images = require('images') +texts = require('texts') + +hideKey = 70 +is_hidden_by_cutscene = false +is_hidden_by_key = false + +defaults = {} +defaults.HideKey = 70 +defaults.SlotImage = {} +defaults.SlotImage.spacing = 4 +defaults.SlotImage.blockSpacing = 4 +defaults.SlotImage.visible = true +defaults.SlotImage.pos = {} +defaults.SlotImage.pos.x = -360 +defaults.SlotImage.pos.y = -50 +defaults.SlotImage.equipment = {} +defaults.SlotImage.equipment.visible = true +defaults.SlotImage.equipment.maxColumns = 4 +defaults.SlotImage.inventory = {} +defaults.SlotImage.inventory.visible = true +defaults.SlotImage.inventory.maxColumns = 5 +defaults.SlotImage.mogSafe = {} +defaults.SlotImage.mogSafe.visible = false +defaults.SlotImage.mogSafe.maxColumns = 5 +defaults.SlotImage.mogStorage = {} +defaults.SlotImage.mogStorage.visible = false +defaults.SlotImage.mogStorage.maxColumns = 5 +defaults.SlotImage.mogLocker = {} +defaults.SlotImage.mogLocker.visible = false +defaults.SlotImage.mogLocker.maxColumns = 5 +defaults.SlotImage.mogSatchel = {} +defaults.SlotImage.mogSatchel.visible = true +defaults.SlotImage.mogSatchel.maxColumns = 5 +defaults.SlotImage.mogSack = {} +defaults.SlotImage.mogSack.visible = true +defaults.SlotImage.mogSack.maxColumns = 5 +defaults.SlotImage.mogCase = {} +defaults.SlotImage.mogCase.visible = true +defaults.SlotImage.mogCase.maxColumns = 5 +defaults.SlotImage.mogWardrobe = {} +defaults.SlotImage.mogWardrobe.visible = false +defaults.SlotImage.mogWardrobe.maxColumns = 5 +defaults.SlotImage.tempInventory = {} +defaults.SlotImage.tempInventory.visible = true +defaults.SlotImage.tempInventory.maxColumns = 1 +defaults.SlotImage.status = {} +defaults.SlotImage.status.default = {} +defaults.SlotImage.status.default.color = {} +defaults.SlotImage.status.default.color.alpha = 255 +defaults.SlotImage.status.default.color.red = 0 +defaults.SlotImage.status.default.color.green = 170 +defaults.SlotImage.status.default.color.blue = 170 +defaults.SlotImage.status.default.background = {} +defaults.SlotImage.status.default.background.color = {} +defaults.SlotImage.status.default.background.color.alpha = 200 +defaults.SlotImage.status.default.background.color.red = 0 +defaults.SlotImage.status.default.background.color.green = 60 +defaults.SlotImage.status.default.background.color.blue = 60 +defaults.SlotImage.status.equipment = {} +defaults.SlotImage.status.equipment.color = {} +defaults.SlotImage.status.equipment.color.alpha = 255 +defaults.SlotImage.status.equipment.color.red = 253 +defaults.SlotImage.status.equipment.color.green = 252 +defaults.SlotImage.status.equipment.color.blue = 250 +defaults.SlotImage.status.equipment.background = {} +defaults.SlotImage.status.equipment.background.color = {} +defaults.SlotImage.status.equipment.background.color.alpha = 200 +defaults.SlotImage.status.equipment.background.color.red = 50 +defaults.SlotImage.status.equipment.background.color.green = 50 +defaults.SlotImage.status.equipment.background.color.blue = 50 +defaults.SlotImage.status.equipped = {} +defaults.SlotImage.status.equipped.color = {} +defaults.SlotImage.status.equipped.color.alpha = 255 +defaults.SlotImage.status.equipped.color.red = 150 +defaults.SlotImage.status.equipped.color.green = 255 +defaults.SlotImage.status.equipped.color.blue = 150 +defaults.SlotImage.status.equipped.background = {} +defaults.SlotImage.status.equipped.background.color = {} +defaults.SlotImage.status.equipped.background.color.alpha = 200 +defaults.SlotImage.status.equipped.background.color.red = 0 +defaults.SlotImage.status.equipped.background.color.green = 100 +defaults.SlotImage.status.equipped.background.color.blue = 0 +defaults.SlotImage.status.linkshell_equipped = {} +defaults.SlotImage.status.linkshell_equipped.color = {} +defaults.SlotImage.status.linkshell_equipped.color.alpha = 255 +defaults.SlotImage.status.linkshell_equipped.color.red = 150 +defaults.SlotImage.status.linkshell_equipped.color.green = 255 +defaults.SlotImage.status.linkshell_equipped.color.blue = 150 +defaults.SlotImage.status.linkshell_equipped.background = {} +defaults.SlotImage.status.linkshell_equipped.background.color = {} +defaults.SlotImage.status.linkshell_equipped.background.color.alpha = 200 +defaults.SlotImage.status.linkshell_equipped.background.color.red = 0 +defaults.SlotImage.status.linkshell_equipped.background.color.green = 100 +defaults.SlotImage.status.linkshell_equipped.background.color.blue = 0 +defaults.SlotImage.status.bazaar = {} +defaults.SlotImage.status.bazaar.color = {} +defaults.SlotImage.status.bazaar.color.alpha = 255 +defaults.SlotImage.status.bazaar.color.red = 225 +defaults.SlotImage.status.bazaar.color.green = 160 +defaults.SlotImage.status.bazaar.color.blue = 30 +defaults.SlotImage.status.bazaar.background = {} +defaults.SlotImage.status.bazaar.background.color = {} +defaults.SlotImage.status.bazaar.background.color.alpha = 200 +defaults.SlotImage.status.bazaar.background.color.red = 100 +defaults.SlotImage.status.bazaar.background.color.green = 100 +defaults.SlotImage.status.bazaar.background.color.blue = 0 +defaults.SlotImage.status.tempItem = {} +defaults.SlotImage.status.tempItem.color = {} +defaults.SlotImage.status.tempItem.color.alpha = 255 +defaults.SlotImage.status.tempItem.color.red = 255 +defaults.SlotImage.status.tempItem.color.green = 30 +defaults.SlotImage.status.tempItem.color.blue = 30 +defaults.SlotImage.status.tempItem.background = {} +defaults.SlotImage.status.tempItem.background.color = {} +defaults.SlotImage.status.tempItem.background.color.alpha = 200 +defaults.SlotImage.status.tempItem.background.color.red = 100 +defaults.SlotImage.status.tempItem.background.color.green = 0 +defaults.SlotImage.status.tempItem.background.color.blue = 0 +defaults.SlotImage.status.empty = {} +defaults.SlotImage.status.empty.color = {} +defaults.SlotImage.status.empty.color.alpha = 150 +defaults.SlotImage.status.empty.color.red = 0 +defaults.SlotImage.status.empty.color.green = 0 +defaults.SlotImage.status.empty.color.blue = 0 +defaults.SlotImage.status.empty.background = {} +defaults.SlotImage.status.empty.background.color = {} +defaults.SlotImage.status.empty.background.color.alpha = 150 +defaults.SlotImage.status.empty.background.color.red = 0 +defaults.SlotImage.status.empty.background.color.green = 0 +defaults.SlotImage.status.empty.background.color.blue = 0 + +local settings = config.load(defaults) +config.save(settings) + +settings.SlotImage.equipment.index = 1 +settings.SlotImage.inventory.index = 2 +settings.SlotImage.mogSafe.index = 3 +settings.SlotImage.mogStorage.index = 4 +settings.SlotImage.mogLocker.index = 5 +settings.SlotImage.mogSatchel.index = 6 +settings.SlotImage.mogSack.index = 7 +settings.SlotImage.mogCase.index = 8 +settings.SlotImage.mogWardrobe.index = 9 +settings.SlotImage.tempInventory.index = 10 +settings.SlotImage.box = {} +settings.SlotImage.box.texture = {} +settings.SlotImage.box.texture.path = windower.addon_path..'slot.png' +settings.SlotImage.box.texture.fit = true +settings.SlotImage.box.size = {} +settings.SlotImage.box.size.height = 2 +settings.SlotImage.box.size.width = 2 +settings.SlotImage.box.repeatable = {} +settings.SlotImage.box.repeatable.x = 1 +settings.SlotImage.box.repeatable.y = 1 +settings.SlotImage.background = {} +settings.SlotImage.background.texture = {} +settings.SlotImage.background.texture.path = windower.addon_path..'slot.png' +settings.SlotImage.background.texture.fit = true +settings.SlotImage.background.size = {} +settings.SlotImage.background.size.height = 3 +settings.SlotImage.background.size.width = 3 +settings.SlotImage.background.repeatable = {} +settings.SlotImage.background.repeatable.x = 1 +settings.SlotImage.background.repeatable.y = 1 + +local yRes = windower.get_windower_settings().ui_y_res +local xRes = windower.get_windower_settings().ui_x_res +local xBase = settings.SlotImage.pos.x +local yBase = settings.SlotImage.pos.y +local current_block = 0 +local current_slot = 1 +local current_row = 1 +local current_column = 1 +local last_column = 1 +local items = {} +local slot_images = {} +local update_time = 0 + +windower.register_event('load',function() + if windower.ffxi.get_info().logged_in then + initialize() + end +end) + +windower.register_event('login', function() + initialize() + update_time = os.time() +end) + +windower.register_event('logout', function(...) + hide() + clear() +end) + +windower.register_event('incoming chunk',function(id,org,modi,is_injected,is_blocked) + if (os.time() - update_time > 30 and id == 0x50 or id == 0xE0 or id == 0x1D) then + update() + end +end) + +windower.register_event('add item', function(...) + if (os.time() - update_time > 30) then + update() + end +end) + +windower.register_event('remove item', function(...) + if (os.time() - update_time > 30) then + update() + end +end) + +function initialize() + hideKey = settings.HideKey + update() + show() +end + +function update() + current_block = 0 + last_column = 1 + items = windower.ffxi.get_items() + update_equipment() + update_items() +end + +function update_equipment() + if (settings.SlotImage.equipment.visible) then + initialize_block() + print_equipment(items.equipment.back) + print_equipment(items.equipment.waist) + print_equipment(items.equipment.legs) + print_equipment(items.equipment.feet) + print_equipment(items.equipment.body) + print_equipment(items.equipment.hands) + print_equipment(items.equipment.left_ring) + print_equipment(items.equipment.right_ring) + print_equipment(items.equipment.head) + print_equipment(items.equipment.neck) + print_equipment(items.equipment.left_ear) + print_equipment(items.equipment.right_ear) + print_equipment(items.equipment.main) + print_equipment(items.equipment.sub) + print_equipment(items.equipment.range) + print_equipment(items.equipment.ammo) + end +end + +function update_items() + update_bag(settings.SlotImage.inventory,items.inventory,items.max_inventory,items.enabled_inventory) + update_bag(settings.SlotImage.mogSafe,items.safe,items.max_safe,items.enabled_safe) + update_bag(settings.SlotImage.mogSafe,items.safe2,items.max_safe2,items.enabled_safe2) + update_bag(settings.SlotImage.mogStorage,items.storage,items.max_storage,items.enabled_storage) + update_bag(settings.SlotImage.mogLocker,items.locker,items.max_locker,items.enabled_locker) + update_bag(settings.SlotImage.mogSatchel,items.satchel,items.max_satchel,items.enabled_satchel) + update_bag(settings.SlotImage.mogSack,items.sack,items.max_sack,items.enabled_sack) + update_bag(settings.SlotImage.mogCase,items.case,items.max_case,items.enabled_case) + update_bag(settings.SlotImage.mogWardrobe,items.wardrobe,items.max_wardrobe,items.enabled_wardrobe) + update_bag(settings.SlotImage.mogWardrobe,items.wardrobe2,items.max_wardrobe2,items.enabled_wardrobe2) + update_bag(settings.SlotImage.mogWardrobe,items.wardrobe3,items.max_wardrobe3,items.enabled_wardrobe3) + update_bag(settings.SlotImage.mogWardrobe,items.wardrobe4,items.max_wardrobe4,items.enabled_wardrobe4) + update_temp_bag(settings.SlotImage.tempInventory,items.treasure,#items.treasure,items.enabled_treasure) + --update_temp_bag(settings.SlotImage.tempInventory,items.temporary,items.max_temporary,items.enabled_temporary) +end + +function update_bag(config, bag, max, enabled) + if (config.visible and enabled) then + initialize_block() + print_bag(config, bag, max) + end +end + +function update_temp_bag(config, bag, max) + if (config.visible and bag.enabled) then + initialize_block() + for key=1,max,1 do + print_item(config,-1,max) + end + end +end + +function initialize_block() + current_block = current_block + 1 + if slot_images[current_block] == nil then + slot_images[current_block] = {} + end + current_slot = 1 + current_row = 1 + current_column = 1 +end + +function print_equipment(status) + if (status > 0) then + print_slot(settings.SlotImage.status.equipment,settings.SlotImage.equipment.maxColumns,16) + else + print_slot(settings.SlotImage.status.empty,settings.SlotImage.equipment.maxColumns,16) + end +end + +function print_bag(config, bag, max) + table.sort(bag, function(a,b) + if (a.status ~= b.status) then + return a.status > b.status + end + return a.count > b.count + end) + for key=1,max,1 do + if (bag[key].count > 0) then + print_item(config,bag[key].status,max) + else + print_slot(settings.SlotImage.status.empty,config.maxColumns,max) + end + end +end + +function print_item(config, status, last_index) + if (status == -1) then + print_slot(settings.SlotImage.status.tempItem,config.maxColumns,last_index) + elseif (status == 0) then + print_slot(settings.SlotImage.status.default,config.maxColumns,last_index) + elseif (status == 5) then + print_slot(settings.SlotImage.status.equipped,config.maxColumns,last_index) + elseif (status == 19) then + print_slot(settings.SlotImage.status.linkshell_equipped,config.maxColumns,last_index) + elseif (status == 25) then + print_slot(settings.SlotImage.status.bazaar,config.maxColumns,last_index) + else + print_slot(settings.SlotImage.status.empty,config.maxColumns,last_index) + end +end + +function print_slot(status, max_columns, last_index) + update_coordinates() + if slot_images[current_block][current_slot] == nil then + slot_images[current_block][current_slot] = {} + end + print_slot_background(status.background.color) + print_slot_box(status.color) + update_indexes(max_columns,last_index) +end + +function print_slot_background(slot_color, max_columns, last_index) + if slot_images[current_block][current_slot].background == nil then + slot_images[current_block][current_slot].background = images.new(settings.SlotImage.background) + slot_images[current_block][current_slot].background:pos(current_x,current_y) + end + slot_images[current_block][current_slot].background:width(settings.SlotImage.background.size.width) + slot_images[current_block][current_slot].background:height(settings.SlotImage.background.size.height) + slot_images[current_block][current_slot].background:alpha(slot_color.alpha) + slot_images[current_block][current_slot].background:color(slot_color.red,slot_color.green,slot_color.blue) +end + +function print_slot_box(slot_color, max_columns, last_index) + if slot_images[current_block][current_slot].box == nil then + slot_images[current_block][current_slot].box = images.new(settings.SlotImage.box) + slot_images[current_block][current_slot].box:pos(current_x,current_y) + end + slot_images[current_block][current_slot].box:width(settings.SlotImage.box.size.width) + slot_images[current_block][current_slot].box:height(settings.SlotImage.box.size.height) + slot_images[current_block][current_slot].box:color(slot_color.red,slot_color.green,slot_color.blue) + slot_images[current_block][current_slot].box:alpha(slot_color.alpha) +end + +function update_coordinates() + current_x = xRes + xBase + + ((current_column - 1) * settings.SlotImage.spacing) + + ((current_block - 1) * settings.SlotImage.blockSpacing) + + ((last_column - 1) * settings.SlotImage.spacing) + current_y = yRes + yBase - ((current_row - 1) * settings.SlotImage.spacing) +end + +function update_indexes(max_columns, last_index) + if (current_slot % max_columns) == 0 then + if (current_slot == last_index) then + last_column = last_column + current_column + end + current_column = 1 + current_row = current_row + 1 + else + current_column = current_column + 1 + end + current_slot = current_slot + 1 +end + +function show() + for key,block in ipairs(slot_images) do + for key,slot in ipairs(block) do + slot.background:show() + slot.box:show() + end + end +end + +function hide() + for key,block in ipairs(slot_images) do + for key,slot in ipairs(block) do + slot.background:hide() + slot.box:hide() + end + end +end + +function clear() + slot_images = {} +end + +windower.register_event('status change', function(new_status_id) + if (new_status_id == 4) and (is_hidden_by_key == false) then + is_hidden_by_cutscene = true + hide() + elseif (new_status_id ~= 4) and (is_hidden_by_key == false) then + is_hidden_by_cutscene = false + show() + end +end) + +windower.register_event('keyboard', function(dik, flags, blocked) + if (dik == hideKey) and (flags == true) and (is_hidden_by_key == true) and (is_hidden_by_cutscene == false) then + is_hidden_by_key = false + show() + elseif (dik == hideKey) and (flags == true) and (is_hidden_by_key == false) and (is_hidden_by_cutscene == false) then + is_hidden_by_key = true + hide() + end +end) diff --git a/addons/invtracker/slot.png b/addons/invtracker/slot.png new file mode 100644 index 0000000000000000000000000000000000000000..f2d13ec092c590241eb5597ac5b4ffb1df8ef0ff GIT binary patch literal 167 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1|;Q0k8}blwj^(N7l!{JxM1({$v_d#0*}aI z1_o|n5N2eUHAey{$X?><>&pI+M_hoP^Y?`3yMaQonIRD+&iT2ysd*(pE(3#eQEFmI zYKlU6W=V#EyQgnJie4%^P@LP-#W95Adh!o`76#7W%zu;Bj`oApd%F6$taD0e0ss@M BDYO6p literal 0 HcmV?d00001 From 9f198d3665b7543cf766f5be605e8cb7fa171fd5 Mon Sep 17 00:00:00 2001 From: azamorapl Date: Mon, 15 Jan 2018 19:29:32 -0500 Subject: [PATCH 0039/1002] Update readme --- addons/invtracker/README.md | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/addons/invtracker/README.md b/addons/invtracker/README.md index fbf8cd9f7a..0262ca6d66 100644 --- a/addons/invtracker/README.md +++ b/addons/invtracker/README.md @@ -3,20 +3,6 @@ This addon displays a grid detailing empty and filled inventory slots, similar t ![Imgur](https://i.imgur.com/PgiMxRZ.png) -## How to install: -1. Download the repository [here](https://github.com/azamorapl/Lua/archive/personal.zip) -2. Extract the **_invtracker_** folder to your **_Windower4/addons_** folder - -## How to enable it in-game: -1. Login to your character in FFXI -2. Press insert to access the windower console -3. Type ``` lua l invtracker ``` - -## How to have windower load it automatically: -1. Go to your windower folder -2. Open the file **_Windower4/scripts/init.txt_** -3. Add the following line to the end of the file ``` lua l invtracker ``` - ## How to edit the settings 1. Login to your character in FFXI 2. Edit the addon settings file: **_Windower4\addons\invtracker\data\settings.xml_** @@ -26,6 +12,6 @@ This addon displays a grid detailing empty and filled inventory slots, similar t 6. Press Insert in FFXI again to close the windower console ## Issues: -1. Since there is no way to know many items determine a full stack, all regular items are painted blue. Instead, bazaar equipped items are painted orange, linkshell and equipped items are painted green, and temporary items are painted red. +1. You may need to log out from you character and enter again in order to have the addon display properly if loaded manually. 2. There is no way to get the inventory sort order, so all items in the grid will be ordered by status and item count. -3. You may need to log out from you character and enter again in order to have the addon display properly if loaded manually. +3. Since there is no way to know many items determine a full stack, all regular items are painted blue. Instead, bazaar equipped items are painted orange, linkshell and equipped items are painted green, and temporary items are painted red. From e1d14c76d50bff89f5ab40a3b96e9595979fbed4 Mon Sep 17 00:00:00 2001 From: azamorapl Date: Mon, 15 Jan 2018 19:31:24 -0500 Subject: [PATCH 0040/1002] Update readme --- addons/giltracker/README.md | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/addons/giltracker/README.md b/addons/giltracker/README.md index 683a8eb1ac..2c6e98dfc4 100644 --- a/addons/giltracker/README.md +++ b/addons/giltracker/README.md @@ -3,20 +3,6 @@ This addon displays the current gil, similar to the FFXIV Gil HUD widget. ![Imgur](https://i.imgur.com/vZ8NkDr.png) -## How to install: -1. Download the repository [here](https://github.com/azamorapl/Lua/archive/personal.zip) -2. Extract the **_giltracker_** folder to your **_Windower4/addons_** folder - -## How to enable it in-game: -1. Login to your character in FFXI -2. Press insert to access the windower console -3. Type ``` lua l giltracker ``` - -## How to have windower load it automatically: -1. Go to your windower folder -2. Open the file **_Windower4/scripts/init.txt_** -3. Add the following line to the end of the file ``` lua l giltracker ``` - ## How to edit the settings 1. Login to your character in FFXI 2. Edit the addon settings file: **_Windower4\addons\giltracker\data\settings.xml_** From f3612333bf50ca0f6b4e99cda4a95a1a9bc9d68a Mon Sep 17 00:00:00 2001 From: azamorapl Date: Wed, 17 Jan 2018 00:30:52 -0500 Subject: [PATCH 0041/1002] Small code cleanup --- addons/giltracker/giltracker.lua | 202 ++++++++++++++++++------------- 1 file changed, 116 insertions(+), 86 deletions(-) diff --git a/addons/giltracker/giltracker.lua b/addons/giltracker/giltracker.lua index a58e6d6bcb..0976527ef3 100644 --- a/addons/giltracker/giltracker.lua +++ b/addons/giltracker/giltracker.lua @@ -35,66 +35,74 @@ config = require('config') images = require('images') texts = require('texts') -hideKey = 70 +local GIL_ITEM_ID = 0xFFFF +local CUTSCENE_STATUS_ID = 4 +local SCROLL_LOCK_KEY = 70 + +hideKey = SCROLL_LOCK_KEY is_hidden_by_cutscene = false is_hidden_by_key = false defaults = {} -defaults.HideKey = 70 -defaults.GilText = {} -defaults.GilText.bg = {} -defaults.GilText.bg.alpha = 100 -defaults.GilText.bg.red = 0 -defaults.GilText.bg.green = 0 -defaults.GilText.bg.blue = 0 -defaults.GilText.bg.visible = false -defaults.GilText.text = {} -defaults.GilText.text.font = 'sans-serif' -defaults.GilText.text.fonts = {'Arial','Trebuchet MS'} -defaults.GilText.text.size = 9 -defaults.GilText.flags = {} -defaults.GilText.flags.italic = true -defaults.GilText.flags.bold = false -defaults.GilText.flags.right = true -defaults.GilText.flags.bottom = true -defaults.GilText.pos = {} -defaults.GilText.pos.x = -285 -defaults.GilText.pos.y = -35 -defaults.GilText.text.alpha = 255 -defaults.GilText.text.red = 253 -defaults.GilText.text.green = 252 -defaults.GilText.text.blue = 250 -defaults.GilText.text.stroke = {} -defaults.GilText.text.stroke.alpha = 200 -defaults.GilText.text.stroke.red = 50 -defaults.GilText.text.stroke.green = 50 -defaults.GilText.text.stroke.blue = 50 -defaults.GilText.text.stroke.width = 2 -defaults.GilText.text.visible = true -defaults.GilImage = {} -defaults.GilImage.color = {} -defaults.GilImage.color.alpha = 255 -defaults.GilImage.color.red = 255 -defaults.GilImage.color.green = 255 -defaults.GilImage.color.blue = 255 -defaults.GilImage.visible = true +defaults.hideKey = SCROLL_LOCK_KEY +defaults.gilText = {} +defaults.gilText.bg = {} +defaults.gilText.bg.alpha = 100 +defaults.gilText.bg.red = 0 +defaults.gilText.bg.green = 0 +defaults.gilText.bg.blue = 0 +defaults.gilText.bg.visible = false +defaults.gilText.text = {} +defaults.gilText.text.font = 'sans-serif' +defaults.gilText.text.fonts = {'Arial','Trebuchet MS'} +defaults.gilText.text.size = 9 +defaults.gilText.flags = {} +defaults.gilText.flags.italic = true +defaults.gilText.flags.bold = false +defaults.gilText.flags.right = true +defaults.gilText.flags.bottom = true +defaults.gilText.pos = {} +defaults.gilText.pos.x = -285 +defaults.gilText.pos.y = -35 +defaults.gilText.text.alpha = 255 +defaults.gilText.text.red = 253 +defaults.gilText.text.green = 252 +defaults.gilText.text.blue = 250 +defaults.gilText.text.stroke = {} +defaults.gilText.text.stroke.alpha = 200 +defaults.gilText.text.stroke.red = 50 +defaults.gilText.text.stroke.green = 50 +defaults.gilText.text.stroke.blue = 50 +defaults.gilText.text.stroke.width = 2 +defaults.gilText.text.visible = true +defaults.gilImage = {} +defaults.gilImage.color = {} +defaults.gilImage.color.alpha = 255 +defaults.gilImage.color.red = 255 +defaults.gilImage.color.green = 255 +defaults.gilImage.color.blue = 255 +defaults.gilImage.visible = true local settings = config.load(defaults) config.save(settings) -settings.GilImage.texture = {} -settings.GilImage.texture.path = windower.addon_path..'gil.png' -settings.GilImage.texture.fit = true -settings.GilImage.size = {} -settings.GilImage.size.height = 23 -settings.GilImage.size.width = 23 -settings.GilImage.draggable = false -settings.GilImage.repeatable = {} -settings.GilImage.repeatable.x = 1 -settings.GilImage.repeatable.y = 1 - -gil_image = images.new(settings.GilImage) -gil_text = texts.new(settings.GilText) +settings.gilImage.texture = {} +settings.gilImage.texture.path = windower.addon_path..'gil.png' +settings.gilImage.texture.fit = true +settings.gilImage.size = {} +settings.gilImage.size.height = 23 +settings.gilImage.size.width = 23 +settings.gilImage.draggable = false +settings.gilImage.repeatable = {} +settings.gilImage.repeatable.x = 1 +settings.gilImage.repeatable.y = 1 + +gil_image = images.new(settings.gilImage) +gil_text = texts.new(settings.gilText) + +config.register(settings, function(settings) + hideKey = settings.hideKey +end) windower.register_event('load',function() if windower.ffxi.get_info().logged_in then @@ -111,33 +119,51 @@ windower.register_event('logout', function(...) end) windower.register_event('add item', function(...) - update_gil() + update_gil_if_item_id_matches(id) end) -windower.register_event('remove item', function(original, modified, original_mode, modified_mode, blocked) - if (string.match(original,"gil")) then - update_gil() - end +windower.register_event('remove item', function(bag, slot, id, count) + update_gil_if_item_id_matches(id) end) +windower.register_event('incoming text', function(original, ...) + update_gil_if_string_contains_gil(original) +end) -windower.register_event('incoming text', function(...) - update_gil() +windower.register_event('status change', function(new_status_id) + local is_cutscene_playing = is_cutscene(new_status_id) + toggle_display_if_cutscene(is_cutscene_playing) +end) + +windower.register_event('keyboard', function(dik, down, flags, blocked) + toggle_display_if_hide_key_is_pressed(dik, down) end) function initialize() - hideKey = settings.HideKey - local xRes = windower.get_windower_settings().ui_x_res - local yRes = windower.get_windower_settings().ui_y_res + local windower_settings = windower.get_windower_settings() + local xRes = windower_settings.ui_x_res + local yRes = windower_settings.ui_y_res update_gil() - gil_image:pos(xRes + settings.GilText.pos.x + 1 , - yRes + settings.GilText.pos.y - (settings.GilImage.size.height/6)) + gil_image:pos(xRes + settings.gilText.pos.x + 1, + yRes + settings.gilText.pos.y - (settings.gilImage.size.height/6)) show() end +function update_gil_if_item_id_matches(id) + if (id == GIL_ITEM_ID) then + update_gil() + end +end + +function update_gil_if_string_contains_gil(input_string) + if (string.match(input_string,"gil")) then + update_gil() + end +end + function update_gil() - local gil = windower.ffxi.get_items().gil - gil_text:text(''..comma_value(gil)) + local gil = windower.ffxi.get_items('gil') + gil_text:text(comma_value(gil)) end function show() @@ -151,32 +177,36 @@ function hide() end function comma_value(amount) - local formatted = amount - while true do - formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2') - if (k==0) then - break + local formatted = tostring(amount) + while true do + formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2') + if (k==0) then + break + end end - end - return formatted + return formatted end -windower.register_event('status change', function(new_status_id) - if (new_status_id == 4) and (is_hidden_by_key == false) then +function is_cutscene(status_id) + return status_id == CUTSCENE_STATUS_ID +end + +function toggle_display_if_cutscene(is_cutscene_playing) + if (is_cutscene_playing) and (not is_hidden_by_key) then is_hidden_by_cutscene = true hide() - elseif (new_status_id ~= 4) and (is_hidden_by_key == false) then + elseif (not is_cutscene_playing) and (not is_hidden_by_key) then is_hidden_by_cutscene = false show() end -end) +end -windower.register_event('keyboard', function(dik, flags, blocked) - if (dik == hideKey) and (flags == true) and (is_hidden_by_key == true) and (is_hidden_by_cutscene == false) then - is_hidden_by_key = false - show() - elseif (dik == hideKey) and (flags == true) and (is_hidden_by_key == false) and (is_hidden_by_cutscene == false) then - is_hidden_by_key = true - hide() - end -end) +function toggle_display_if_hide_key_is_pressed(key_pressed, key_down) + if (key_pressed == hideKey) and (key_down) and (is_hidden_by_key) and (not is_hidden_by_cutscene) then + is_hidden_by_key = false + show() + elseif (key_pressed == hideKey) and (key_down) and (not is_hidden_by_key) and (not is_hidden_by_cutscene) then + is_hidden_by_key = true + hide() + end +end From cc26cbdb15342bf867a61da4609dfa4cc5db5fbc Mon Sep 17 00:00:00 2001 From: azamorapl Date: Wed, 17 Jan 2018 00:31:34 -0500 Subject: [PATCH 0042/1002] Small code cleanup, add full stack functionality --- addons/invtracker/README.md | 1 - addons/invtracker/invtracker.lua | 541 +++++++++++++++++-------------- 2 files changed, 303 insertions(+), 239 deletions(-) diff --git a/addons/invtracker/README.md b/addons/invtracker/README.md index 0262ca6d66..03f3728302 100644 --- a/addons/invtracker/README.md +++ b/addons/invtracker/README.md @@ -14,4 +14,3 @@ This addon displays a grid detailing empty and filled inventory slots, similar t ## Issues: 1. You may need to log out from you character and enter again in order to have the addon display properly if loaded manually. 2. There is no way to get the inventory sort order, so all items in the grid will be ordered by status and item count. -3. Since there is no way to know many items determine a full stack, all regular items are painted blue. Instead, bazaar equipped items are painted orange, linkshell and equipped items are painted green, and temporary items are painted red. diff --git a/addons/invtracker/invtracker.lua b/addons/invtracker/invtracker.lua index 6df103b29c..b0911ec0fa 100644 --- a/addons/invtracker/invtracker.lua +++ b/addons/invtracker/invtracker.lua @@ -34,174 +34,200 @@ _addon.language = 'English' config = require('config') images = require('images') texts = require('texts') - -hideKey = 70 +res = require('resources') + +local CUTSCENE_STATUS_ID = 4 +local SCROLL_LOCK_KEY = 70 +local MIN_TIME_SINCE_STARTING = 30 +local MAX_EQUIPMENT_SIZE = 16 +local DEFAULT_ITEM_STATUS = 0 +local EQUIPPED_ITEM_STATUS = 5 +local LINKSHELL_EQUIPPED_ITEM_STATUS = 19 +local BAZAAR_ITEM_STATUS = 25 +local EQUIPMENT_CHANGED_PACKET = 0x50 +local SEARCH_MESSAGE_SET_PACKET = 0xE0 +local INVENTORY_FINISH_PACKET = 0x1D + +hideKey = SCROLL_LOCK_KEY is_hidden_by_cutscene = false is_hidden_by_key = false defaults = {} -defaults.HideKey = 70 -defaults.SlotImage = {} -defaults.SlotImage.spacing = 4 -defaults.SlotImage.blockSpacing = 4 -defaults.SlotImage.visible = true -defaults.SlotImage.pos = {} -defaults.SlotImage.pos.x = -360 -defaults.SlotImage.pos.y = -50 -defaults.SlotImage.equipment = {} -defaults.SlotImage.equipment.visible = true -defaults.SlotImage.equipment.maxColumns = 4 -defaults.SlotImage.inventory = {} -defaults.SlotImage.inventory.visible = true -defaults.SlotImage.inventory.maxColumns = 5 -defaults.SlotImage.mogSafe = {} -defaults.SlotImage.mogSafe.visible = false -defaults.SlotImage.mogSafe.maxColumns = 5 -defaults.SlotImage.mogStorage = {} -defaults.SlotImage.mogStorage.visible = false -defaults.SlotImage.mogStorage.maxColumns = 5 -defaults.SlotImage.mogLocker = {} -defaults.SlotImage.mogLocker.visible = false -defaults.SlotImage.mogLocker.maxColumns = 5 -defaults.SlotImage.mogSatchel = {} -defaults.SlotImage.mogSatchel.visible = true -defaults.SlotImage.mogSatchel.maxColumns = 5 -defaults.SlotImage.mogSack = {} -defaults.SlotImage.mogSack.visible = true -defaults.SlotImage.mogSack.maxColumns = 5 -defaults.SlotImage.mogCase = {} -defaults.SlotImage.mogCase.visible = true -defaults.SlotImage.mogCase.maxColumns = 5 -defaults.SlotImage.mogWardrobe = {} -defaults.SlotImage.mogWardrobe.visible = false -defaults.SlotImage.mogWardrobe.maxColumns = 5 -defaults.SlotImage.tempInventory = {} -defaults.SlotImage.tempInventory.visible = true -defaults.SlotImage.tempInventory.maxColumns = 1 -defaults.SlotImage.status = {} -defaults.SlotImage.status.default = {} -defaults.SlotImage.status.default.color = {} -defaults.SlotImage.status.default.color.alpha = 255 -defaults.SlotImage.status.default.color.red = 0 -defaults.SlotImage.status.default.color.green = 170 -defaults.SlotImage.status.default.color.blue = 170 -defaults.SlotImage.status.default.background = {} -defaults.SlotImage.status.default.background.color = {} -defaults.SlotImage.status.default.background.color.alpha = 200 -defaults.SlotImage.status.default.background.color.red = 0 -defaults.SlotImage.status.default.background.color.green = 60 -defaults.SlotImage.status.default.background.color.blue = 60 -defaults.SlotImage.status.equipment = {} -defaults.SlotImage.status.equipment.color = {} -defaults.SlotImage.status.equipment.color.alpha = 255 -defaults.SlotImage.status.equipment.color.red = 253 -defaults.SlotImage.status.equipment.color.green = 252 -defaults.SlotImage.status.equipment.color.blue = 250 -defaults.SlotImage.status.equipment.background = {} -defaults.SlotImage.status.equipment.background.color = {} -defaults.SlotImage.status.equipment.background.color.alpha = 200 -defaults.SlotImage.status.equipment.background.color.red = 50 -defaults.SlotImage.status.equipment.background.color.green = 50 -defaults.SlotImage.status.equipment.background.color.blue = 50 -defaults.SlotImage.status.equipped = {} -defaults.SlotImage.status.equipped.color = {} -defaults.SlotImage.status.equipped.color.alpha = 255 -defaults.SlotImage.status.equipped.color.red = 150 -defaults.SlotImage.status.equipped.color.green = 255 -defaults.SlotImage.status.equipped.color.blue = 150 -defaults.SlotImage.status.equipped.background = {} -defaults.SlotImage.status.equipped.background.color = {} -defaults.SlotImage.status.equipped.background.color.alpha = 200 -defaults.SlotImage.status.equipped.background.color.red = 0 -defaults.SlotImage.status.equipped.background.color.green = 100 -defaults.SlotImage.status.equipped.background.color.blue = 0 -defaults.SlotImage.status.linkshell_equipped = {} -defaults.SlotImage.status.linkshell_equipped.color = {} -defaults.SlotImage.status.linkshell_equipped.color.alpha = 255 -defaults.SlotImage.status.linkshell_equipped.color.red = 150 -defaults.SlotImage.status.linkshell_equipped.color.green = 255 -defaults.SlotImage.status.linkshell_equipped.color.blue = 150 -defaults.SlotImage.status.linkshell_equipped.background = {} -defaults.SlotImage.status.linkshell_equipped.background.color = {} -defaults.SlotImage.status.linkshell_equipped.background.color.alpha = 200 -defaults.SlotImage.status.linkshell_equipped.background.color.red = 0 -defaults.SlotImage.status.linkshell_equipped.background.color.green = 100 -defaults.SlotImage.status.linkshell_equipped.background.color.blue = 0 -defaults.SlotImage.status.bazaar = {} -defaults.SlotImage.status.bazaar.color = {} -defaults.SlotImage.status.bazaar.color.alpha = 255 -defaults.SlotImage.status.bazaar.color.red = 225 -defaults.SlotImage.status.bazaar.color.green = 160 -defaults.SlotImage.status.bazaar.color.blue = 30 -defaults.SlotImage.status.bazaar.background = {} -defaults.SlotImage.status.bazaar.background.color = {} -defaults.SlotImage.status.bazaar.background.color.alpha = 200 -defaults.SlotImage.status.bazaar.background.color.red = 100 -defaults.SlotImage.status.bazaar.background.color.green = 100 -defaults.SlotImage.status.bazaar.background.color.blue = 0 -defaults.SlotImage.status.tempItem = {} -defaults.SlotImage.status.tempItem.color = {} -defaults.SlotImage.status.tempItem.color.alpha = 255 -defaults.SlotImage.status.tempItem.color.red = 255 -defaults.SlotImage.status.tempItem.color.green = 30 -defaults.SlotImage.status.tempItem.color.blue = 30 -defaults.SlotImage.status.tempItem.background = {} -defaults.SlotImage.status.tempItem.background.color = {} -defaults.SlotImage.status.tempItem.background.color.alpha = 200 -defaults.SlotImage.status.tempItem.background.color.red = 100 -defaults.SlotImage.status.tempItem.background.color.green = 0 -defaults.SlotImage.status.tempItem.background.color.blue = 0 -defaults.SlotImage.status.empty = {} -defaults.SlotImage.status.empty.color = {} -defaults.SlotImage.status.empty.color.alpha = 150 -defaults.SlotImage.status.empty.color.red = 0 -defaults.SlotImage.status.empty.color.green = 0 -defaults.SlotImage.status.empty.color.blue = 0 -defaults.SlotImage.status.empty.background = {} -defaults.SlotImage.status.empty.background.color = {} -defaults.SlotImage.status.empty.background.color.alpha = 150 -defaults.SlotImage.status.empty.background.color.red = 0 -defaults.SlotImage.status.empty.background.color.green = 0 -defaults.SlotImage.status.empty.background.color.blue = 0 +defaults.HideKey = SCROLL_LOCK_KEY +defaults.slotImage = {} +defaults.slotImage.spacing = 4 +defaults.slotImage.blockSpacing = 4 +defaults.slotImage.visible = true +defaults.slotImage.pos = {} +defaults.slotImage.pos.x = -360 +defaults.slotImage.pos.y = -50 +defaults.slotImage.equipment = {} +defaults.slotImage.equipment.visible = true +defaults.slotImage.equipment.maxColumns = 4 +defaults.slotImage.inventory = {} +defaults.slotImage.inventory.visible = true +defaults.slotImage.inventory.maxColumns = 5 +defaults.slotImage.mogSafe = {} +defaults.slotImage.mogSafe.visible = false +defaults.slotImage.mogSafe.maxColumns = 5 +defaults.slotImage.mogStorage = {} +defaults.slotImage.mogStorage.visible = false +defaults.slotImage.mogStorage.maxColumns = 5 +defaults.slotImage.mogLocker = {} +defaults.slotImage.mogLocker.visible = false +defaults.slotImage.mogLocker.maxColumns = 5 +defaults.slotImage.mogSatchel = {} +defaults.slotImage.mogSatchel.visible = true +defaults.slotImage.mogSatchel.maxColumns = 5 +defaults.slotImage.mogSack = {} +defaults.slotImage.mogSack.visible = true +defaults.slotImage.mogSack.maxColumns = 5 +defaults.slotImage.mogCase = {} +defaults.slotImage.mogCase.visible = true +defaults.slotImage.mogCase.maxColumns = 5 +defaults.slotImage.mogWardrobe = {} +defaults.slotImage.mogWardrobe.visible = false +defaults.slotImage.mogWardrobe.maxColumns = 5 +defaults.slotImage.tempInventory = {} +defaults.slotImage.tempInventory.visible = true +defaults.slotImage.tempInventory.maxColumns = 1 +defaults.slotImage.status = {} +defaults.slotImage.status.default = {} +defaults.slotImage.status.default.color = {} +defaults.slotImage.status.default.color.alpha = 255 +defaults.slotImage.status.default.color.red = 0 +defaults.slotImage.status.default.color.green = 170 +defaults.slotImage.status.default.color.blue = 170 +defaults.slotImage.status.default.background = {} +defaults.slotImage.status.default.background.color = {} +defaults.slotImage.status.default.background.color.alpha = 200 +defaults.slotImage.status.default.background.color.red = 0 +defaults.slotImage.status.default.background.color.green = 60 +defaults.slotImage.status.default.background.color.blue = 60 +defaults.slotImage.status.fullStack = {} +defaults.slotImage.status.fullStack.color = {} +defaults.slotImage.status.fullStack.color.alpha = 255 +defaults.slotImage.status.fullStack.color.red = 245 +defaults.slotImage.status.fullStack.color.green = 40 +defaults.slotImage.status.fullStack.color.blue = 40 +defaults.slotImage.status.fullStack.background = {} +defaults.slotImage.status.fullStack.background.color = {} +defaults.slotImage.status.fullStack.background.color.alpha = 200 +defaults.slotImage.status.fullStack.background.color.red = 100 +defaults.slotImage.status.fullStack.background.color.green = 0 +defaults.slotImage.status.fullStack.background.color.blue = 0 +defaults.slotImage.status.equipment = {} +defaults.slotImage.status.equipment.color = {} +defaults.slotImage.status.equipment.color.alpha = 255 +defaults.slotImage.status.equipment.color.red = 253 +defaults.slotImage.status.equipment.color.green = 252 +defaults.slotImage.status.equipment.color.blue = 250 +defaults.slotImage.status.equipment.background = {} +defaults.slotImage.status.equipment.background.color = {} +defaults.slotImage.status.equipment.background.color.alpha = 200 +defaults.slotImage.status.equipment.background.color.red = 50 +defaults.slotImage.status.equipment.background.color.green = 50 +defaults.slotImage.status.equipment.background.color.blue = 50 +defaults.slotImage.status.equipped = {} +defaults.slotImage.status.equipped.color = {} +defaults.slotImage.status.equipped.color.alpha = 255 +defaults.slotImage.status.equipped.color.red = 150 +defaults.slotImage.status.equipped.color.green = 255 +defaults.slotImage.status.equipped.color.blue = 150 +defaults.slotImage.status.equipped.background = {} +defaults.slotImage.status.equipped.background.color = {} +defaults.slotImage.status.equipped.background.color.alpha = 200 +defaults.slotImage.status.equipped.background.color.red = 0 +defaults.slotImage.status.equipped.background.color.green = 100 +defaults.slotImage.status.equipped.background.color.blue = 0 +defaults.slotImage.status.linkshellEquipped = {} +defaults.slotImage.status.linkshellEquipped.color = {} +defaults.slotImage.status.linkshellEquipped.color.alpha = 255 +defaults.slotImage.status.linkshellEquipped.color.red = 150 +defaults.slotImage.status.linkshellEquipped.color.green = 255 +defaults.slotImage.status.linkshellEquipped.color.blue = 150 +defaults.slotImage.status.linkshellEquipped.background = {} +defaults.slotImage.status.linkshellEquipped.background.color = {} +defaults.slotImage.status.linkshellEquipped.background.color.alpha = 200 +defaults.slotImage.status.linkshellEquipped.background.color.red = 0 +defaults.slotImage.status.linkshellEquipped.background.color.green = 100 +defaults.slotImage.status.linkshellEquipped.background.color.blue = 0 +defaults.slotImage.status.bazaar = {} +defaults.slotImage.status.bazaar.color = {} +defaults.slotImage.status.bazaar.color.alpha = 255 +defaults.slotImage.status.bazaar.color.red = 225 +defaults.slotImage.status.bazaar.color.green = 160 +defaults.slotImage.status.bazaar.color.blue = 30 +defaults.slotImage.status.bazaar.background = {} +defaults.slotImage.status.bazaar.background.color = {} +defaults.slotImage.status.bazaar.background.color.alpha = 200 +defaults.slotImage.status.bazaar.background.color.red = 100 +defaults.slotImage.status.bazaar.background.color.green = 100 +defaults.slotImage.status.bazaar.background.color.blue = 0 +defaults.slotImage.status.tempItem = {} +defaults.slotImage.status.tempItem.color = {} +defaults.slotImage.status.tempItem.color.alpha = 255 +defaults.slotImage.status.tempItem.color.red = 255 +defaults.slotImage.status.tempItem.color.green = 30 +defaults.slotImage.status.tempItem.color.blue = 30 +defaults.slotImage.status.tempItem.background = {} +defaults.slotImage.status.tempItem.background.color = {} +defaults.slotImage.status.tempItem.background.color.alpha = 200 +defaults.slotImage.status.tempItem.background.color.red = 100 +defaults.slotImage.status.tempItem.background.color.green = 0 +defaults.slotImage.status.tempItem.background.color.blue = 0 +defaults.slotImage.status.empty = {} +defaults.slotImage.status.empty.color = {} +defaults.slotImage.status.empty.color.alpha = 150 +defaults.slotImage.status.empty.color.red = 0 +defaults.slotImage.status.empty.color.green = 0 +defaults.slotImage.status.empty.color.blue = 0 +defaults.slotImage.status.empty.background = {} +defaults.slotImage.status.empty.background.color = {} +defaults.slotImage.status.empty.background.color.alpha = 150 +defaults.slotImage.status.empty.background.color.red = 0 +defaults.slotImage.status.empty.background.color.green = 0 +defaults.slotImage.status.empty.background.color.blue = 0 local settings = config.load(defaults) config.save(settings) -settings.SlotImage.equipment.index = 1 -settings.SlotImage.inventory.index = 2 -settings.SlotImage.mogSafe.index = 3 -settings.SlotImage.mogStorage.index = 4 -settings.SlotImage.mogLocker.index = 5 -settings.SlotImage.mogSatchel.index = 6 -settings.SlotImage.mogSack.index = 7 -settings.SlotImage.mogCase.index = 8 -settings.SlotImage.mogWardrobe.index = 9 -settings.SlotImage.tempInventory.index = 10 -settings.SlotImage.box = {} -settings.SlotImage.box.texture = {} -settings.SlotImage.box.texture.path = windower.addon_path..'slot.png' -settings.SlotImage.box.texture.fit = true -settings.SlotImage.box.size = {} -settings.SlotImage.box.size.height = 2 -settings.SlotImage.box.size.width = 2 -settings.SlotImage.box.repeatable = {} -settings.SlotImage.box.repeatable.x = 1 -settings.SlotImage.box.repeatable.y = 1 -settings.SlotImage.background = {} -settings.SlotImage.background.texture = {} -settings.SlotImage.background.texture.path = windower.addon_path..'slot.png' -settings.SlotImage.background.texture.fit = true -settings.SlotImage.background.size = {} -settings.SlotImage.background.size.height = 3 -settings.SlotImage.background.size.width = 3 -settings.SlotImage.background.repeatable = {} -settings.SlotImage.background.repeatable.x = 1 -settings.SlotImage.background.repeatable.y = 1 - -local yRes = windower.get_windower_settings().ui_y_res -local xRes = windower.get_windower_settings().ui_x_res -local xBase = settings.SlotImage.pos.x -local yBase = settings.SlotImage.pos.y +settings.slotImage.equipment.index = 1 +settings.slotImage.inventory.index = 2 +settings.slotImage.mogSafe.index = 3 +settings.slotImage.mogStorage.index = 4 +settings.slotImage.mogLocker.index = 5 +settings.slotImage.mogSatchel.index = 6 +settings.slotImage.mogSack.index = 7 +settings.slotImage.mogCase.index = 8 +settings.slotImage.mogWardrobe.index = 9 +settings.slotImage.tempInventory.index = 10 +settings.slotImage.box = {} +settings.slotImage.box.texture = {} +settings.slotImage.box.texture.path = windower.addon_path..'slot.png' +settings.slotImage.box.texture.fit = true +settings.slotImage.box.size = {} +settings.slotImage.box.size.height = 2 +settings.slotImage.box.size.width = 2 +settings.slotImage.box.repeatable = {} +settings.slotImage.box.repeatable.x = 1 +settings.slotImage.box.repeatable.y = 1 +settings.slotImage.background = {} +settings.slotImage.background.texture = {} +settings.slotImage.background.texture.path = windower.addon_path..'slot.png' +settings.slotImage.background.texture.fit = true +settings.slotImage.background.size = {} +settings.slotImage.background.size.height = 3 +settings.slotImage.background.size.width = 3 +settings.slotImage.background.repeatable = {} +settings.slotImage.background.repeatable.x = 1 +settings.slotImage.background.repeatable.y = 1 + +local windower_settings = windower.get_windower_settings() +local yRes = windower_settings.ui_y_res +local xRes = windower_settings.ui_x_res +local xBase = settings.slotImage.pos.x +local yBase = settings.slotImage.pos.y local current_block = 0 local current_slot = 1 local current_row = 1 @@ -209,7 +235,11 @@ local current_column = 1 local last_column = 1 local items = {} local slot_images = {} -local update_time = 0 +local start_time = 0 + +config.register(settings, function(settings) + hideKey = settings.HideKey +end) windower.register_event('load',function() if windower.ffxi.get_info().logged_in then @@ -219,7 +249,7 @@ end) windower.register_event('login', function() initialize() - update_time = os.time() + start_time = os.time() end) windower.register_event('logout', function(...) @@ -228,25 +258,39 @@ windower.register_event('logout', function(...) end) windower.register_event('incoming chunk',function(id,org,modi,is_injected,is_blocked) - if (os.time() - update_time > 30 and id == 0x50 or id == 0xE0 or id == 0x1D) then - update() + if (min_time_has_elapsed() and id == EQUIPMENT_CHANGED_PACKET or id == SEARCH_MESSAGE_SET_PACKET or id == INVENTORY_FINISH_PACKET) then + update() end end) windower.register_event('add item', function(...) - if (os.time() - update_time > 30) then - update() - end + update_if_min_time_has_elapsed() end) windower.register_event('remove item', function(...) - if (os.time() - update_time > 30) then + update_if_min_time_has_elapsed() +end) + +windower.register_event('status change', function(new_status_id) + local is_cutscene_playing = is_cutscene(new_status_id) + toggle_display_if_cutscene(is_cutscene_playing) +end) + +windower.register_event('keyboard', function(dik, down, flags, blocked) + toggle_display_if_hide_key_is_pressed(dik, down) +end) + +function update_if_min_time_has_elapsed() + if (min_time_has_elapsed()) then update() end -end) +end + +function min_time_has_elapsed() + return os.time() - start_time > MIN_TIME_SINCE_STARTING +end function initialize() - hideKey = settings.HideKey update() show() end @@ -260,7 +304,7 @@ function update() end function update_equipment() - if (settings.SlotImage.equipment.visible) then + if (settings.slotImage.equipment.visible) then initialize_block() print_equipment(items.equipment.back) print_equipment(items.equipment.waist) @@ -282,20 +326,20 @@ function update_equipment() end function update_items() - update_bag(settings.SlotImage.inventory,items.inventory,items.max_inventory,items.enabled_inventory) - update_bag(settings.SlotImage.mogSafe,items.safe,items.max_safe,items.enabled_safe) - update_bag(settings.SlotImage.mogSafe,items.safe2,items.max_safe2,items.enabled_safe2) - update_bag(settings.SlotImage.mogStorage,items.storage,items.max_storage,items.enabled_storage) - update_bag(settings.SlotImage.mogLocker,items.locker,items.max_locker,items.enabled_locker) - update_bag(settings.SlotImage.mogSatchel,items.satchel,items.max_satchel,items.enabled_satchel) - update_bag(settings.SlotImage.mogSack,items.sack,items.max_sack,items.enabled_sack) - update_bag(settings.SlotImage.mogCase,items.case,items.max_case,items.enabled_case) - update_bag(settings.SlotImage.mogWardrobe,items.wardrobe,items.max_wardrobe,items.enabled_wardrobe) - update_bag(settings.SlotImage.mogWardrobe,items.wardrobe2,items.max_wardrobe2,items.enabled_wardrobe2) - update_bag(settings.SlotImage.mogWardrobe,items.wardrobe3,items.max_wardrobe3,items.enabled_wardrobe3) - update_bag(settings.SlotImage.mogWardrobe,items.wardrobe4,items.max_wardrobe4,items.enabled_wardrobe4) - update_temp_bag(settings.SlotImage.tempInventory,items.treasure,#items.treasure,items.enabled_treasure) - --update_temp_bag(settings.SlotImage.tempInventory,items.temporary,items.max_temporary,items.enabled_temporary) + update_bag(settings.slotImage.inventory,items.inventory,items.max_inventory,items.enabled_inventory) + update_bag(settings.slotImage.mogSafe,items.safe,items.max_safe,items.enabled_safe) + update_bag(settings.slotImage.mogSafe,items.safe2,items.max_safe2,items.enabled_safe2) + update_bag(settings.slotImage.mogStorage,items.storage,items.max_storage,items.enabled_storage) + update_bag(settings.slotImage.mogLocker,items.locker,items.max_locker,items.enabled_locker) + update_bag(settings.slotImage.mogSatchel,items.satchel,items.max_satchel,items.enabled_satchel) + update_bag(settings.slotImage.mogSack,items.sack,items.max_sack,items.enabled_sack) + update_bag(settings.slotImage.mogCase,items.case,items.max_case,items.enabled_case) + update_bag(settings.slotImage.mogWardrobe,items.wardrobe,items.max_wardrobe,items.enabled_wardrobe) + update_bag(settings.slotImage.mogWardrobe,items.wardrobe2,items.max_wardrobe2,items.enabled_wardrobe2) + update_bag(settings.slotImage.mogWardrobe,items.wardrobe3,items.max_wardrobe3,items.enabled_wardrobe3) + update_bag(settings.slotImage.mogWardrobe,items.wardrobe4,items.max_wardrobe4,items.enabled_wardrobe4) + update_temp_bag(settings.slotImage.tempInventory,items.treasure,#items.treasure) + update_temp_bag(settings.slotImage.tempInventory,items.temporary,items.max_temporary) end function update_bag(config, bag, max, enabled) @@ -309,7 +353,9 @@ function update_temp_bag(config, bag, max) if (config.visible and bag.enabled) then initialize_block() for key=1,max,1 do - print_item(config,-1,max) + if bag[key].count > 0 then + print_slot(settings.slotImage.status.tempItem,config.maxColumns,max) + end end end end @@ -326,41 +372,54 @@ end function print_equipment(status) if (status > 0) then - print_slot(settings.SlotImage.status.equipment,settings.SlotImage.equipment.maxColumns,16) + print_slot(settings.slotImage.status.equipment,settings.slotImage.equipment.maxColumns,MAX_EQUIPMENT_SIZE) else - print_slot(settings.SlotImage.status.empty,settings.SlotImage.equipment.maxColumns,16) + print_slot(settings.slotImage.status.empty,settings.slotImage.equipment.maxColumns,MAX_EQUIPMENT_SIZE) end end function print_bag(config, bag, max) + sort_table() + for key=1,max,1 do + if (bag[key].count > 0) then + print_item(config,bag[key],max) + else + print_slot(settings.slotImage.status.empty,config.maxColumns,max) + end + end +end + +function sort_table() table.sort(bag, function(a,b) if (a.status ~= b.status) then return a.status > b.status end + if (a.count > 0 and b.count > 0) then + full_stack_a = res.items[a.id].stack - a.count + full_stack_b = res.items[b.id].stack - b.count + if (full_stack_a ~= full_stack_b) then + return full_stack_a < full_stack_b + end + end return a.count > b.count end) - for key=1,max,1 do - if (bag[key].count > 0) then - print_item(config,bag[key].status,max) - else - print_slot(settings.SlotImage.status.empty,config.maxColumns,max) - end - end end -function print_item(config, status, last_index) - if (status == -1) then - print_slot(settings.SlotImage.status.tempItem,config.maxColumns,last_index) - elseif (status == 0) then - print_slot(settings.SlotImage.status.default,config.maxColumns,last_index) - elseif (status == 5) then - print_slot(settings.SlotImage.status.equipped,config.maxColumns,last_index) - elseif (status == 19) then - print_slot(settings.SlotImage.status.linkshell_equipped,config.maxColumns,last_index) - elseif (status == 25) then - print_slot(settings.SlotImage.status.bazaar,config.maxColumns,last_index) +function print_item(config, item, last_index) + if (item.status == DEFAULT_ITEM_STATUS) then + if (item.count == res.items[item.id].stack) then + print_slot(settings.slotImage.status.fullStack,config.maxColumns,last_index) + else + print_slot(settings.slotImage.status.default,config.maxColumns,last_index) + end + elseif (item.status == EQUIPPED_ITEM_STATUS) then + print_slot(settings.slotImage.status.equipped,config.maxColumns,last_index) + elseif (item.status == LINKSHELL_EQUIPPED_ITEM_STATUS) then + print_slot(settings.slotImage.status.linkshellEquipped,config.maxColumns,last_index) + elseif (item.status == BAZAAR_ITEM_STATUS) then + print_slot(settings.slotImage.status.bazaar,config.maxColumns,last_index) else - print_slot(settings.SlotImage.status.empty,config.maxColumns,last_index) + print_slot(settings.slotImage.status.empty,config.maxColumns,last_index) end end @@ -375,33 +434,35 @@ function print_slot(status, max_columns, last_index) end function print_slot_background(slot_color, max_columns, last_index) - if slot_images[current_block][current_slot].background == nil then - slot_images[current_block][current_slot].background = images.new(settings.SlotImage.background) - slot_images[current_block][current_slot].background:pos(current_x,current_y) + local slot_image = slot_images[current_block][current_slot] + if slot_image.background == nil then + slot_image.background = images.new(settings.slotImage.background) + slot_image.background:pos(current_x,current_y) end - slot_images[current_block][current_slot].background:width(settings.SlotImage.background.size.width) - slot_images[current_block][current_slot].background:height(settings.SlotImage.background.size.height) - slot_images[current_block][current_slot].background:alpha(slot_color.alpha) - slot_images[current_block][current_slot].background:color(slot_color.red,slot_color.green,slot_color.blue) + slot_image.background:width(settings.slotImage.background.size.width) + slot_image.background:height(settings.slotImage.background.size.height) + slot_image.background:alpha(slot_color.alpha) + slot_image.background:color(slot_color.red,slot_color.green,slot_color.blue) end function print_slot_box(slot_color, max_columns, last_index) - if slot_images[current_block][current_slot].box == nil then - slot_images[current_block][current_slot].box = images.new(settings.SlotImage.box) - slot_images[current_block][current_slot].box:pos(current_x,current_y) + local slot_image = slot_images[current_block][current_slot] + if slot_image.box == nil then + slot_image.box = images.new(settings.slotImage.box) + slot_image.box:pos(current_x,current_y) end - slot_images[current_block][current_slot].box:width(settings.SlotImage.box.size.width) - slot_images[current_block][current_slot].box:height(settings.SlotImage.box.size.height) - slot_images[current_block][current_slot].box:color(slot_color.red,slot_color.green,slot_color.blue) - slot_images[current_block][current_slot].box:alpha(slot_color.alpha) + slot_image.box:width(settings.slotImage.box.size.width) + slot_image.box:height(settings.slotImage.box.size.height) + slot_image.box:color(slot_color.red,slot_color.green,slot_color.blue) + slot_image.box:alpha(slot_color.alpha) end function update_coordinates() current_x = xRes + xBase + - ((current_column - 1) * settings.SlotImage.spacing) + - ((current_block - 1) * settings.SlotImage.blockSpacing) + - ((last_column - 1) * settings.SlotImage.spacing) - current_y = yRes + yBase - ((current_row - 1) * settings.SlotImage.spacing) + ((current_column - 1) * settings.slotImage.spacing) + + ((current_block - 1) * settings.slotImage.blockSpacing) + + ((last_column - 1) * settings.slotImage.spacing) + current_y = yRes + yBase - ((current_row - 1) * settings.slotImage.spacing) end function update_indexes(max_columns, last_index) @@ -439,22 +500,26 @@ function clear() slot_images = {} end -windower.register_event('status change', function(new_status_id) - if (new_status_id == 4) and (is_hidden_by_key == false) then +function is_cutscene(status_id) + return status_id == CUTSCENE_STATUS_ID +end + +function toggle_display_if_cutscene(is_cutscene_playing) + if (is_cutscene_playing) and (not is_hidden_by_key) then is_hidden_by_cutscene = true hide() - elseif (new_status_id ~= 4) and (is_hidden_by_key == false) then + elseif (not is_cutscene_playing) and (not is_hidden_by_key) then is_hidden_by_cutscene = false show() end -end) +end -windower.register_event('keyboard', function(dik, flags, blocked) - if (dik == hideKey) and (flags == true) and (is_hidden_by_key == true) and (is_hidden_by_cutscene == false) then - is_hidden_by_key = false - show() - elseif (dik == hideKey) and (flags == true) and (is_hidden_by_key == false) and (is_hidden_by_cutscene == false) then - is_hidden_by_key = true - hide() - end -end) +function toggle_display_if_hide_key_is_pressed(key_pressed, key_down) + if (key_pressed == hideKey) and (key_down) and (is_hidden_by_key) and (not is_hidden_by_cutscene) then + is_hidden_by_key = false + show() + elseif (key_pressed == hideKey) and (key_down) and (not is_hidden_by_key) and (not is_hidden_by_cutscene) then + is_hidden_by_key = true + hide() + end +end From 5cf4388b1ee80835318970f2b9f13ca5eb02d78a Mon Sep 17 00:00:00 2001 From: azamorapl Date: Wed, 17 Jan 2018 00:32:48 -0500 Subject: [PATCH 0043/1002] Update readme --- addons/invtracker/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/invtracker/README.md b/addons/invtracker/README.md index 03f3728302..bf95cac4ff 100644 --- a/addons/invtracker/README.md +++ b/addons/invtracker/README.md @@ -12,5 +12,5 @@ This addon displays a grid detailing empty and filled inventory slots, similar t 6. Press Insert in FFXI again to close the windower console ## Issues: -1. You may need to log out from you character and enter again in order to have the addon display properly if loaded manually. +1. You may need to change zones or log out from you character and enter again in order to have the addon display properly if loaded manually. 2. There is no way to get the inventory sort order, so all items in the grid will be ordered by status and item count. From 7c69d8cb2968a06743eb55a0bda9f1ac7c6c1a15 Mon Sep 17 00:00:00 2001 From: azamorapl Date: Wed, 17 Jan 2018 21:30:23 -0500 Subject: [PATCH 0044/1002] Fix method signature and gil not being updated during login --- addons/giltracker/giltracker.lua | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/addons/giltracker/giltracker.lua b/addons/giltracker/giltracker.lua index 0976527ef3..ab1c9564c8 100644 --- a/addons/giltracker/giltracker.lua +++ b/addons/giltracker/giltracker.lua @@ -38,6 +38,8 @@ texts = require('texts') local GIL_ITEM_ID = 0xFFFF local CUTSCENE_STATUS_ID = 4 local SCROLL_LOCK_KEY = 70 +local MAX_TIME_AFTER_STARTING = 180 +local STOP_DOWNLOADING_PACKET = 0x0041 hideKey = SCROLL_LOCK_KEY is_hidden_by_cutscene = false @@ -96,6 +98,7 @@ settings.gilImage.draggable = false settings.gilImage.repeatable = {} settings.gilImage.repeatable.x = 1 settings.gilImage.repeatable.y = 1 +local start_time = 0 gil_image = images.new(settings.gilImage) gil_text = texts.new(settings.gilText) @@ -112,20 +115,27 @@ end) windower.register_event('login', function() initialize() + start_time = os.time() end) windower.register_event('logout', function(...) hide() end) -windower.register_event('add item', function(...) +windower.register_event('add item', function(_bag, _slot, id, _count) update_gil_if_item_id_matches(id) end) -windower.register_event('remove item', function(bag, slot, id, count) +windower.register_event('remove item', function(_bag, _slot, id, _count) update_gil_if_item_id_matches(id) end) +windower.register_event('incoming chunk',function(id,_org,_modi,_is_injected,_is_blocked) + if (is_during_login_time() and id == STOP_DOWNLOADING_PACKET) then + update_gil() + end +end) + windower.register_event('incoming text', function(original, ...) update_gil_if_string_contains_gil(original) end) @@ -135,10 +145,14 @@ windower.register_event('status change', function(new_status_id) toggle_display_if_cutscene(is_cutscene_playing) end) -windower.register_event('keyboard', function(dik, down, flags, blocked) +windower.register_event('keyboard', function(dik, down, _flags, _blocked) toggle_display_if_hide_key_is_pressed(dik, down) end) +function is_during_login_time() + return os.time() - start_time < MAX_TIME_AFTER_STARTING +end + function initialize() local windower_settings = windower.get_windower_settings() local xRes = windower_settings.ui_x_res From 792420493df7f84fba9d9a35dd728a83ef971b82 Mon Sep 17 00:00:00 2001 From: azamorapl Date: Wed, 17 Jan 2018 21:45:03 -0500 Subject: [PATCH 0045/1002] Change packet from STOP_DOWNLOADING to INVENTORY_FINISH, works better --- addons/giltracker/giltracker.lua | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/addons/giltracker/giltracker.lua b/addons/giltracker/giltracker.lua index ab1c9564c8..4c2ad59ea6 100644 --- a/addons/giltracker/giltracker.lua +++ b/addons/giltracker/giltracker.lua @@ -38,8 +38,7 @@ texts = require('texts') local GIL_ITEM_ID = 0xFFFF local CUTSCENE_STATUS_ID = 4 local SCROLL_LOCK_KEY = 70 -local MAX_TIME_AFTER_STARTING = 180 -local STOP_DOWNLOADING_PACKET = 0x0041 +local INVENTORY_FINISH_PACKET = 0x1D hideKey = SCROLL_LOCK_KEY is_hidden_by_cutscene = false @@ -131,7 +130,7 @@ windower.register_event('remove item', function(_bag, _slot, id, _count) end) windower.register_event('incoming chunk',function(id,_org,_modi,_is_injected,_is_blocked) - if (is_during_login_time() and id == STOP_DOWNLOADING_PACKET) then + if (id == INVENTORY_FINISH_PACKET) then update_gil() end end) @@ -149,10 +148,6 @@ windower.register_event('keyboard', function(dik, down, _flags, _blocked) toggle_display_if_hide_key_is_pressed(dik, down) end) -function is_during_login_time() - return os.time() - start_time < MAX_TIME_AFTER_STARTING -end - function initialize() local windower_settings = windower.get_windower_settings() local xRes = windower_settings.ui_x_res From 0f004cc63fe22e3b995f60abf49e4e3e5b73dbb1 Mon Sep 17 00:00:00 2001 From: Ivaar <7287342+Ivaar@users.noreply.github.com> Date: Thu, 18 Jan 2018 05:41:35 -0800 Subject: [PATCH 0046/1002] Boxdestroyer: Fix zone id not updating --- addons/boxdestroyer/boxdestroyer.lua | 38 +++++++++++++++------------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/addons/boxdestroyer/boxdestroyer.lua b/addons/boxdestroyer/boxdestroyer.lua index 2c2fd90271..286b086b2e 100644 --- a/addons/boxdestroyer/boxdestroyer.lua +++ b/addons/boxdestroyer/boxdestroyer.lua @@ -1,22 +1,17 @@ --[[ Copyright (c) 2014, Seth VanHeulen All rights reserved. - Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. 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. - 3. Neither the name of the copyright holder 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 @@ -33,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- addon information _addon.name = 'boxdestroyer' -_addon.version = '1.0.1' +_addon.version = '1.0.2' _addon.command = 'boxdestroyer' _addon.author = 'Seth VanHeulen (Acacia@Odin)' @@ -62,6 +57,7 @@ default = { -- global variables box = {} +zone_id = windower.ffxi.get_info().zone -- filter helper functions @@ -119,11 +115,17 @@ function display(id, chances) windower.add_to_chat(207, 'best guess: %d (%d%%)':format(box[id][math.ceil(#box[id] / 2)], 1 / remaining * 100)) end +-- ID obtaining helper function +function get_id(zone_id,str) + return messages[zone_id] + offsets[str] +end + -- event callback functions function check_incoming_chunk(id, original, modified, injected, blocked) - local zone_id = windower.ffxi.get_info().zone - if messages[zone_id] then + if id == 0x0A then + zone_id = original:unpack('H', 49) + elseif messages[zone_id] then if id == 0x0B then box = {} elseif id == 0x2A then @@ -132,20 +134,20 @@ function check_incoming_chunk(id, original, modified, injected, blocked) local param1 = original:unpack('I', 13) local param2 = original:unpack('I', 17) local message_id = original:unpack('H', 27) % 0x8000 - if messages[zone_id].greater_less == message_id then + if get_id(zone_id,'greater_less') == message_id then box[box_id] = greater_less(box_id, param1 == 0, param0) - elseif messages[zone_id].second_even_odd == message_id then + elseif get_id(zone_id,'second_even_odd') == message_id then box[box_id] = even_odd(box_id, 1, param0) - elseif messages[zone_id].first_even_odd == message_id then + elseif get_id(zone_id,'first_even_odd') == message_id then box[box_id] = even_odd(box_id, 10, param0) - elseif messages[zone_id].range == message_id then + elseif get_id(zone_id,'range') == message_id then box[box_id] = greater_less(box_id, true, param0) box[box_id] = greater_less(box_id, false, param1) - elseif messages[zone_id].less == message_id then + elseif get_id(zone_id,'less') == message_id then box[box_id] = greater_less(box_id, false, param0) - elseif messages[zone_id].greater == message_id then + elseif get_id(zone_id,'greater') == message_id then box[box_id] = greater_less(box_id, true, param0) - elseif messages[zone_id].equal == message_id then + elseif get_id(zone_id,'equal') == message_id then local new = equal(box_id, true, param0) local duplicate = param0 * 10 + param0 for k,v in pairs(new) do @@ -156,19 +158,19 @@ function check_incoming_chunk(id, original, modified, injected, blocked) for _,v in pairs(equal(box_id, false, param0)) do table.insert(new, v) end table.sort(new) box[box_id] = new - elseif messages[zone_id].second_multiple == message_id then + elseif get_id(zone_id,'second_multiple') == message_id then local new = equal(box_id, false, param0) for _,v in pairs(equal(box_id, false, param1)) do table.insert(new, v) end for _,v in pairs(equal(box_id, false, param2)) do table.insert(new, v) end table.sort(new) box[box_id] = new - elseif messages[zone_id].first_multiple == message_id then + elseif get_id(zone_id,'first_multiple') == message_id then local new = equal(box_id, true, param0) for _,v in pairs(equal(box_id, true, param1)) do table.insert(new, v) end for _,v in pairs(equal(box_id, true, param2)) do table.insert(new, v) end table.sort(new) box[box_id] = new - elseif messages[zone_id].success == message_id or messages[zone_id].failure == message_id then + elseif get_id(zone_id,'success') == message_id or get_id(zone_id,'failure') == message_id then box[box_id] = nil end elseif id == 0x34 then From a3fc076eba5be3ef424fda643f1532a80e418385 Mon Sep 17 00:00:00 2001 From: Ivaar <7287342+Ivaar@users.noreply.github.com> Date: Thu, 18 Jan 2018 06:37:23 -0800 Subject: [PATCH 0047/1002] Boxdestroyer: Fix zone id not updating --- addons/boxdestroyer/boxdestroyer.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/boxdestroyer/boxdestroyer.lua b/addons/boxdestroyer/boxdestroyer.lua index d8ccbfc5b0..286b086b2e 100644 --- a/addons/boxdestroyer/boxdestroyer.lua +++ b/addons/boxdestroyer/boxdestroyer.lua @@ -123,10 +123,10 @@ end -- event callback functions function check_incoming_chunk(id, original, modified, injected, blocked) - if messages[zone_id] then - if id == 0x0A then - zone_id = original:unpack('H', 49) - elseif id == 0x0B then + if id == 0x0A then + zone_id = original:unpack('H', 49) + elseif messages[zone_id] then + if id == 0x0B then box = {} elseif id == 0x2A then local box_id = original:unpack('I', 5) From 06cacd98287745a13e45ec3af6b0b9f61644be99 Mon Sep 17 00:00:00 2001 From: azamorapl Date: Sun, 21 Jan 2018 23:57:07 -0500 Subject: [PATCH 0048/1002] Rework for update event optimization --- addons/giltracker/giltracker.lua | 90 +++++++++++++++++++------------- 1 file changed, 54 insertions(+), 36 deletions(-) diff --git a/addons/giltracker/giltracker.lua b/addons/giltracker/giltracker.lua index 4c2ad59ea6..3612a0e927 100644 --- a/addons/giltracker/giltracker.lua +++ b/addons/giltracker/giltracker.lua @@ -34,15 +34,20 @@ _addon.language = 'English' config = require('config') images = require('images') texts = require('texts') +packets = require('packets') -local GIL_ITEM_ID = 0xFFFF +local GIL_ITEM_ID = 65535 local CUTSCENE_STATUS_ID = 4 local SCROLL_LOCK_KEY = 70 local INVENTORY_FINISH_PACKET = 0x1D +local TREASURE_FIND_ITEM_PACKET = 0xD2 +local LOGIN_ZONE_PACKET = 0x0A +local ITEM_UPDATE_PACKET = 0x20 +local ITEM_MODIFY_PACKET = 0x1F -hideKey = SCROLL_LOCK_KEY -is_hidden_by_cutscene = false -is_hidden_by_key = false +local hideKey = SCROLL_LOCK_KEY +local is_hidden_by_cutscene = false +local is_hidden_by_key = false defaults = {} defaults.hideKey = SCROLL_LOCK_KEY @@ -97,13 +102,19 @@ settings.gilImage.draggable = false settings.gilImage.repeatable = {} settings.gilImage.repeatable.x = 1 settings.gilImage.repeatable.y = 1 -local start_time = 0 -gil_image = images.new(settings.gilImage) -gil_text = texts.new(settings.gilText) +local gil_image = images.new(settings.gilImage) +local gil_text = texts.new(settings.gilText) +local inventory_loaded = false +local ready = false config.register(settings, function(settings) hideKey = settings.hideKey + local windower_settings = windower.get_windower_settings() + local xRes = windower_settings.ui_x_res + local yRes = windower_settings.ui_y_res + gil_image:pos(xRes + settings.gilText.pos.x + 1, + yRes + settings.gilText.pos.y - (settings.gilImage.size.height/6)) end) windower.register_event('load',function() @@ -112,33 +123,37 @@ windower.register_event('load',function() end end) -windower.register_event('login', function() - initialize() - start_time = os.time() +windower.register_event('login',function() + gil_text:text('Loading...') end) windower.register_event('logout', function(...) + inventory_loaded = false hide() end) -windower.register_event('add item', function(_bag, _slot, id, _count) - update_gil_if_item_id_matches(id) +windower.register_event('add item', function(_bag,_index,id,...) + if (id == GIL_ITEM_ID) then ready = true end end) -windower.register_event('remove item', function(_bag, _slot, id, _count) - update_gil_if_item_id_matches(id) +windower.register_event('remove item', function(_bag,_index,id,...) + if (id == GIL_ITEM_ID) then ready = true end end) -windower.register_event('incoming chunk',function(id,_org,_modi,_is_injected,_is_blocked) - if (id == INVENTORY_FINISH_PACKET) then - update_gil() +windower.register_event('incoming chunk',function(id,org,_modi,_is_injected,_is_blocked) + if (id == LOGIN_ZONE_PACKET) then + inventory_loaded = false + elseif (id == TREASURE_FIND_ITEM_PACKET) then + ready_if_valid_treasure_packet(org) + elseif (id == ITEM_UPDATE_PACKET) then + update_if_valid_item_packet(org) + elseif (id == INVENTORY_FINISH_PACKET) then + refresh_gil() + elseif (id == ITEM_MODIFY_PACKET) then + update_if_valid_item_packet(org) end end) -windower.register_event('incoming text', function(original, ...) - update_gil_if_string_contains_gil(original) -end) - windower.register_event('status change', function(new_status_id) local is_cutscene_playing = is_cutscene(new_status_id) toggle_display_if_cutscene(is_cutscene_playing) @@ -148,28 +163,33 @@ windower.register_event('keyboard', function(dik, down, _flags, _blocked) toggle_display_if_hide_key_is_pressed(dik, down) end) -function initialize() - local windower_settings = windower.get_windower_settings() - local xRes = windower_settings.ui_x_res - local yRes = windower_settings.ui_y_res - update_gil() - gil_image:pos(xRes + settings.gilText.pos.x + 1, - yRes + settings.gilText.pos.y - (settings.gilImage.size.height/6)) - show() +function ready_if_valid_treasure_packet(packet_data) + local p = packets.parse('incoming',packet_data) + if (p.Count > 0) then ready = true end end -function update_gil_if_item_id_matches(id) - if (id == GIL_ITEM_ID) then +function update_if_valid_item_packet(packet_data) + local p = packets.parse('incoming',packet_data) + if (p.Item == GIL_ITEM_ID and p.Count >= 0) then update_gil() end end -function update_gil_if_string_contains_gil(input_string) - if (string.match(input_string,"gil")) then +function refresh_gil() + if (ready and inventory_loaded) then update_gil() + ready = false + elseif (not inventory_loaded) then + initialize() end end +function initialize() + inventory_loaded = true + update_gil() + if not is_hidden_by_key and not is_hidden_by_cutscene then show() end +end + function update_gil() local gil = windower.ffxi.get_items('gil') gil_text:text(comma_value(gil)) @@ -189,9 +209,7 @@ function comma_value(amount) local formatted = tostring(amount) while true do formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2') - if (k==0) then - break - end + if (k==0) then break end end return formatted end From 30d8ac7a3b630064745f67b92b26a64c58225105 Mon Sep 17 00:00:00 2001 From: azamorapl Date: Sun, 21 Jan 2018 23:58:16 -0500 Subject: [PATCH 0049/1002] Major rework for optimization --- addons/invtracker/README.md | 3 +- addons/invtracker/invtracker.lua | 376 ++++++++++++++++++++++--------- 2 files changed, 271 insertions(+), 108 deletions(-) diff --git a/addons/invtracker/README.md b/addons/invtracker/README.md index bf95cac4ff..4c327fa2d7 100644 --- a/addons/invtracker/README.md +++ b/addons/invtracker/README.md @@ -12,5 +12,4 @@ This addon displays a grid detailing empty and filled inventory slots, similar t 6. Press Insert in FFXI again to close the windower console ## Issues: -1. You may need to change zones or log out from you character and enter again in order to have the addon display properly if loaded manually. -2. There is no way to get the inventory sort order, so all items in the grid will be ordered by status and item count. +1. There is no way to get the inventory sort order, so all items in the grid will be ordered by status and item count. diff --git a/addons/invtracker/invtracker.lua b/addons/invtracker/invtracker.lua index b0911ec0fa..2ef1d57e9a 100644 --- a/addons/invtracker/invtracker.lua +++ b/addons/invtracker/invtracker.lua @@ -35,31 +35,40 @@ config = require('config') images = require('images') texts = require('texts') res = require('resources') +packets = require('packets') local CUTSCENE_STATUS_ID = 4 local SCROLL_LOCK_KEY = 70 -local MIN_TIME_SINCE_STARTING = 30 local MAX_EQUIPMENT_SIZE = 16 local DEFAULT_ITEM_STATUS = 0 local EQUIPPED_ITEM_STATUS = 5 local LINKSHELL_EQUIPPED_ITEM_STATUS = 19 local BAZAAR_ITEM_STATUS = 25 local EQUIPMENT_CHANGED_PACKET = 0x50 -local SEARCH_MESSAGE_SET_PACKET = 0xE0 +local BAZAAR_PRICE_PACKET = 0x10A +local EQUIPSET_CHANGED_PACKET = 0x051 local INVENTORY_FINISH_PACKET = 0x1D - -hideKey = SCROLL_LOCK_KEY -is_hidden_by_cutscene = false -is_hidden_by_key = false +local LOGIN_ZONE_PACKET = 0x0A +local TREASURE_FIND_ITEM_PACKET = 0xD2 +local TREASURE_LOT_ITEM_PACKET = 0xD3 +local EQUIP_LINKSHELL_PACKET = 0xC4 +local INVENTORY_SIZE_PACKET = 0x1C +local GIL_ITEM_ID = 65535 +local NO_ITEM_ID = 0 + +local hideKey = SCROLL_LOCK_KEY +local is_hidden_by_cutscene = false +local is_hidden_by_key = false defaults = {} defaults.HideKey = SCROLL_LOCK_KEY defaults.slotImage = {} +defaults.slotImage.sort = true defaults.slotImage.spacing = 4 defaults.slotImage.blockSpacing = 4 defaults.slotImage.visible = true defaults.slotImage.pos = {} -defaults.slotImage.pos.x = -360 +defaults.slotImage.pos.x = -365 defaults.slotImage.pos.y = -50 defaults.slotImage.equipment = {} defaults.slotImage.equipment.visible = true @@ -72,7 +81,7 @@ defaults.slotImage.mogSafe.visible = false defaults.slotImage.mogSafe.maxColumns = 5 defaults.slotImage.mogStorage = {} defaults.slotImage.mogStorage.visible = false -defaults.slotImage.mogStorage.maxColumns = 5 +defaults.slotImage.mogStorage.maxColumns = 4 defaults.slotImage.mogLocker = {} defaults.slotImage.mogLocker.visible = false defaults.slotImage.mogLocker.maxColumns = 5 @@ -89,8 +98,11 @@ defaults.slotImage.mogWardrobe = {} defaults.slotImage.mogWardrobe.visible = false defaults.slotImage.mogWardrobe.maxColumns = 5 defaults.slotImage.tempInventory = {} -defaults.slotImage.tempInventory.visible = true defaults.slotImage.tempInventory.maxColumns = 1 +defaults.slotImage.tempInventory.visible = true +defaults.slotImage.treasury = {} +defaults.slotImage.treasury.visible = true +defaults.slotImage.treasury.maxColumns = 1 defaults.slotImage.status = {} defaults.slotImage.status.default = {} defaults.slotImage.status.default.color = {} @@ -168,14 +180,14 @@ defaults.slotImage.status.tempItem = {} defaults.slotImage.status.tempItem.color = {} defaults.slotImage.status.tempItem.color.alpha = 255 defaults.slotImage.status.tempItem.color.red = 255 -defaults.slotImage.status.tempItem.color.green = 30 -defaults.slotImage.status.tempItem.color.blue = 30 +defaults.slotImage.status.tempItem.color.green = 130 +defaults.slotImage.status.tempItem.color.blue = 255 defaults.slotImage.status.tempItem.background = {} defaults.slotImage.status.tempItem.background.color = {} defaults.slotImage.status.tempItem.background.color.alpha = 200 defaults.slotImage.status.tempItem.background.color.red = 100 defaults.slotImage.status.tempItem.background.color.green = 0 -defaults.slotImage.status.tempItem.background.color.blue = 0 +defaults.slotImage.status.tempItem.background.color.blue = 100 defaults.slotImage.status.empty = {} defaults.slotImage.status.empty.color = {} defaults.slotImage.status.empty.color.alpha = 150 @@ -192,33 +204,23 @@ defaults.slotImage.status.empty.background.color.blue = 0 local settings = config.load(defaults) config.save(settings) -settings.slotImage.equipment.index = 1 -settings.slotImage.inventory.index = 2 -settings.slotImage.mogSafe.index = 3 -settings.slotImage.mogStorage.index = 4 -settings.slotImage.mogLocker.index = 5 -settings.slotImage.mogSatchel.index = 6 -settings.slotImage.mogSack.index = 7 -settings.slotImage.mogCase.index = 8 -settings.slotImage.mogWardrobe.index = 9 -settings.slotImage.tempInventory.index = 10 settings.slotImage.box = {} -settings.slotImage.box.texture = {} -settings.slotImage.box.texture.path = windower.addon_path..'slot.png' -settings.slotImage.box.texture.fit = true settings.slotImage.box.size = {} settings.slotImage.box.size.height = 2 settings.slotImage.box.size.width = 2 +settings.slotImage.box.texture = {} +settings.slotImage.box.texture.path = windower.addon_path..'slot.png' +settings.slotImage.box.texture.fit = false settings.slotImage.box.repeatable = {} settings.slotImage.box.repeatable.x = 1 settings.slotImage.box.repeatable.y = 1 settings.slotImage.background = {} -settings.slotImage.background.texture = {} -settings.slotImage.background.texture.path = windower.addon_path..'slot.png' -settings.slotImage.background.texture.fit = true settings.slotImage.background.size = {} settings.slotImage.background.size.height = 3 settings.slotImage.background.size.width = 3 +settings.slotImage.background.texture = {} +settings.slotImage.background.texture.path = windower.addon_path..'slot.png' +settings.slotImage.background.texture.fit = false settings.slotImage.background.repeatable = {} settings.slotImage.background.repeatable.x = 1 settings.slotImage.background.repeatable.y = 1 @@ -226,8 +228,6 @@ settings.slotImage.background.repeatable.y = 1 local windower_settings = windower.get_windower_settings() local yRes = windower_settings.ui_y_res local xRes = windower_settings.ui_x_res -local xBase = settings.slotImage.pos.x -local yBase = settings.slotImage.pos.y local current_block = 0 local current_slot = 1 local current_row = 1 @@ -235,10 +235,17 @@ local current_column = 1 local last_column = 1 local items = {} local slot_images = {} -local start_time = 0 +local inventory_loaded = false +local refresh_all = false +local refresh_items = false +local refresh_inventory = false +local refresh_linkshell = false +local last_treasure_count = 0 config.register(settings, function(settings) hideKey = settings.HideKey + xBase = settings.slotImage.pos.x + yBase = settings.slotImage.pos.y end) windower.register_event('load',function() @@ -247,28 +254,54 @@ windower.register_event('load',function() end end) -windower.register_event('login', function() - initialize() - start_time = os.time() +windower.register_event('login',function() + update_all() + hide() end) windower.register_event('logout', function(...) + inventory_loaded = false hide() clear() end) -windower.register_event('incoming chunk',function(id,org,modi,is_injected,is_blocked) - if (min_time_has_elapsed() and id == EQUIPMENT_CHANGED_PACKET or id == SEARCH_MESSAGE_SET_PACKET or id == INVENTORY_FINISH_PACKET) then - update() +windower.register_event('add item', function(_bag,_index,id,...) + if (id ~= GIL_ITEM_ID and id ~= NO_ITEM_ID) then refresh_items = true end +end) + +windower.register_event('remove item', function(_bag,_index,id,...) + if (id ~= GIL_ITEM_ID and id ~= NO_ITEM_ID) then refresh_items = true end +end) + +windower.register_event('linkshell change', function(new,old) + if (refresh_linkshell) then + refresh_inventory = true + refresh_linkshell = false end end) -windower.register_event('add item', function(...) - update_if_min_time_has_elapsed() +windower.register_event('incoming chunk',function(id,org,_modi,_is_injected,_is_blocked) + if (id == LOGIN_ZONE_PACKET) then + inventory_loaded = false + elseif (id == INVENTORY_FINISH_PACKET) then + update() + elseif (id == TREASURE_FIND_ITEM_PACKET) then + update_treasure_only() + elseif (id == TREASURE_LOT_ITEM_PACKET) then + update_treasure_only() + elseif (id == INVENTORY_SIZE_PACKET) then + update_if_different_size(org) + end end) -windower.register_event('remove item', function(...) - update_if_min_time_has_elapsed() +windower.register_event('outgoing chunk',function(id,org,_modi,_is_injected,_is_blocked) + if (id == EQUIPMENT_CHANGED_PACKET or id == EQUIPSET_CHANGED_PACKET) then + refresh_all = true + elseif (id == BAZAAR_PRICE_PACKET) then + refresh_inventory = true + elseif (id == EQUIP_LINKSHELL_PACKET) then + refresh_linkshell = true + end end) windower.register_event('status change', function(new_status_id) @@ -276,31 +309,113 @@ windower.register_event('status change', function(new_status_id) toggle_display_if_cutscene(is_cutscene_playing) end) -windower.register_event('keyboard', function(dik, down, flags, blocked) +windower.register_event('keyboard', function(dik, down, _flags, _blocked) toggle_display_if_hide_key_is_pressed(dik, down) end) -function update_if_min_time_has_elapsed() - if (min_time_has_elapsed()) then - update() +function update() + if (inventory_loaded) then + update_if_event() + else + initialize() end end -function min_time_has_elapsed() - return os.time() - start_time > MIN_TIME_SINCE_STARTING +function initialize() + inventory_loaded = true + update_all() + refresh_all = false + refresh_items = false + refresh_inventory = false + if not is_hidden_by_key and not is_hidden_by_cutscene then show() end end -function initialize() - update() - show() +function update_all() + setup_indexes() + update_equipment() + update_items() + update_treasure_bag(settings.slotImage.treasury,items.treasure) end -function update() +function update_if_event() + if (refresh_all) then + update_all() + refresh_all = false + refresh_items = false + refresh_inventory = false + elseif (refresh_items) then + update_items_only() + refresh_items = false + refresh_inventory = false + elseif (refresh_inventory) then + update_inventory_only() + refresh_inventory = false + end +end + +function update_inventory_only() + setup_indexes() + skip_block_if_enabled(settings.slotImage.equipment.visible, true,settings.slotImage.equipment.maxColumns,MAX_EQUIPMENT_SIZE) + update_bag(settings.slotImage.inventory,items.inventory,items.max_inventory,items.enabled_inventory) +end + +function update_items_only() + setup_indexes() + skip_block_if_enabled(settings.slotImage.equipment.visible, true,settings.slotImage.equipment.maxColumns,MAX_EQUIPMENT_SIZE) + update_items() +end + +function update_treasure_only() + local s = settings.slotImage + if (inventory_loaded and s.treasury.visible) then + setup_indexes() + skip_block_if_enabled(s.equipment.visible, true,s.equipment.maxColumns,MAX_EQUIPMENT_SIZE) + skip_block_if_enabled(s.inventory.visible,items.enabled_inventory,s.inventory.maxColumns,items.max_inventory) + skip_block_if_enabled(s.mogSafe.visible,items.safe.enabled,s.mogSafe.maxColumns,items.max_safe) + skip_block_if_enabled(s.mogSafe.visible,items.safe2.enabled,s.mogSafe.maxColumns,items.max_safe2) + skip_block_if_enabled(s.mogStorage.visible,items.storage.enabled,s.mogStorage.maxColumns,items.storage.max) + skip_block_if_enabled(s.mogLocker.visible,items.enabled_locker,s.mogLocker.maxColumns,items.max_locker) + skip_block_if_enabled(s.mogSatchel.visible,items.enabled_satchel,s.mogSatchel.maxColumns,items.max_satchel) + skip_block_if_enabled(s.mogSack.visible,items.enabled_sack,s.mogSack.maxColumns,items.max_sack) + skip_block_if_enabled(s.mogCase.visible,items.enabled_case,s.mogCase.maxColumns,items.max_case) + skip_block_if_enabled(s.mogWardrobe.visible,items.enabled_wardrobe,s.mogWardrobe.maxColumns,items.max_wardrobe) + skip_block_if_enabled(s.mogWardrobe.visible,items.enabled_wardrobe2,s.mogWardrobe.maxColumns,items.max_wardrobe2) + skip_block_if_enabled(s.mogWardrobe.visible,items.enabled_wardrobe3,s.mogWardrobe.maxColumns,items.max_wardrobe3) + skip_block_if_enabled(s.mogWardrobe.visible,items.enabled_wardrobe4,s.mogWardrobe.maxColumns,items.max_wardrobe4) + skip_block_if_enabled(s.tempInventory.visible,true,s.tempInventory.maxColumns,items.temporary.max) + update_treasure_bag(s.treasury,items.treasure) + end +end + +function update_if_different_size(packet_data) + if (inventory_loaded) then + local p = packets.parse('incoming',packet_data) + local s = settings.slotImage + if size_changed(s.inventory.visible,items.enabled_inventory,items.max_inventory,p['Inventory Size']) + or size_changed(s.mogSafe.visible,items.safe.enabled,items.max_safe,p['Safe Size']) + or size_changed(s.mogSafe.visible,items.safe2.enabled,items.max_safe2,p['Safe 2 Size']) + or size_changed(s.mogStorage.visible,items.storage.enabled,items.storage.max,p['Storage Size']) + or size_changed(s.mogLocker.visible,items.enabled_locker,items.max_locker,p['Locker Size']) + or size_changed(s.mogSatchel.visible,items.enabled_satchel,items.max_satchel,p['Satchel Size']) + or size_changed(s.mogSack.visible,items.enabled_sack,items.max_sack,p['Sack Size']) + or size_changed(s.mogCase.visible,items.enabled_case,items.max_case,p['Case Size']) + or size_changed(s.mogWardrobe.visible,items.enabled_wardrobe,items.max_wardrobe,p['Wardrobe Size']) + or size_changed(s.mogWardrobe.visible,items.enabled_wardrobe2,items.max_wardrobe2,p['Wardrobe 2 Size']) + or size_changed(s.mogWardrobe.visible,items.enabled_wardrobe3,items.max_wardrobe3,p['Wardrobe 3 Size']) + or size_changed(s.mogWardrobe.visible,items.enabled_wardrobe4,items.max_wardrobe4,p['Wardrobe 4 Size']) then + refresh_all = true + end + end +end + +function size_changed(visible, enabled, current_size, new_size) + return (visible and enabled and ((current_size+1) ~= new_size)) +end + +function setup_indexes() current_block = 0 last_column = 1 items = windower.ffxi.get_items() - update_equipment() - update_items() end function update_equipment() @@ -326,20 +441,37 @@ function update_equipment() end function update_items() - update_bag(settings.slotImage.inventory,items.inventory,items.max_inventory,items.enabled_inventory) - update_bag(settings.slotImage.mogSafe,items.safe,items.max_safe,items.enabled_safe) - update_bag(settings.slotImage.mogSafe,items.safe2,items.max_safe2,items.enabled_safe2) - update_bag(settings.slotImage.mogStorage,items.storage,items.max_storage,items.enabled_storage) - update_bag(settings.slotImage.mogLocker,items.locker,items.max_locker,items.enabled_locker) - update_bag(settings.slotImage.mogSatchel,items.satchel,items.max_satchel,items.enabled_satchel) - update_bag(settings.slotImage.mogSack,items.sack,items.max_sack,items.enabled_sack) - update_bag(settings.slotImage.mogCase,items.case,items.max_case,items.enabled_case) - update_bag(settings.slotImage.mogWardrobe,items.wardrobe,items.max_wardrobe,items.enabled_wardrobe) - update_bag(settings.slotImage.mogWardrobe,items.wardrobe2,items.max_wardrobe2,items.enabled_wardrobe2) - update_bag(settings.slotImage.mogWardrobe,items.wardrobe3,items.max_wardrobe3,items.enabled_wardrobe3) - update_bag(settings.slotImage.mogWardrobe,items.wardrobe4,items.max_wardrobe4,items.enabled_wardrobe4) - update_temp_bag(settings.slotImage.tempInventory,items.treasure,#items.treasure) - update_temp_bag(settings.slotImage.tempInventory,items.temporary,items.max_temporary) + local s = settings.slotImage + update_bag(s.inventory,items.inventory,items.max_inventory,items.enabled_inventory) + update_bag(s.mogSafe,items.safe,items.max_safe,items.safe.enabled) + update_bag(s.mogSafe,items.safe2,items.max_safe2,items.safe2.enabled) + update_bag(s.mogStorage,items.storage,items.storage.max,items.storage.enabled) + update_bag(s.mogLocker,items.locker,items.max_locker,items.enabled_locker) + update_bag(s.mogSatchel,items.satchel,items.max_satchel,items.enabled_satchel) + update_bag(s.mogSack,items.sack,items.max_sack,items.enabled_sack) + update_bag(s.mogCase,items.case,items.max_case,items.enabled_case) + update_bag(s.mogWardrobe,items.wardrobe,items.max_wardrobe,items.enabled_wardrobe) + update_bag(s.mogWardrobe,items.wardrobe2,items.max_wardrobe2,items.enabled_wardrobe2) + update_bag(s.mogWardrobe,items.wardrobe3,items.max_wardrobe3,items.enabled_wardrobe3) + update_bag(s.mogWardrobe,items.wardrobe4,items.max_wardrobe4,items.enabled_wardrobe4) + update_temp_bag(s.tempInventory,items.temporary) +end + +function update_treasure_bag(config,bag) + if (config.visible) then + local treasure_count = count_treasure() + if (treasure_count ~= last_treasure_count) then + initialize_block() + for k, _v in ipairs(slot_images[current_block]) do + slot_images[current_block][k].background:alpha(0) + slot_images[current_block][k].box:alpha(0) + end + for _k, _v in pairs(bag) do + print_slot(settings.slotImage.status.tempItem,config.maxColumns,80) + end + last_treasure_count = treasure_count + end + end end function update_bag(config, bag, max, enabled) @@ -349,14 +481,40 @@ function update_bag(config, bag, max, enabled) end end -function update_temp_bag(config, bag, max) - if (config.visible and bag.enabled) then +function update_temp_bag(config, bag) + if (config.visible) then initialize_block() - for key=1,max,1 do + local occupied_slots = 0 + for key=1,bag.max,1 do if bag[key].count > 0 then - print_slot(settings.slotImage.status.tempItem,config.maxColumns,max) + occupied_slots = occupied_slots + 1 end end + for k, _v in ipairs(slot_images[current_block]) do + slot_images[current_block][k].background:alpha(0) + slot_images[current_block][k].box:alpha(0) + end + for _k=1,occupied_slots,1 do + print_slot(settings.slotImage.status.tempItem,config.maxColumns,bag.max) + end + current_slot = bag.max + current_column = config.maxColumns + update_indexes(config.maxColumns,bag.max) + end +end + +function count_treasure() + local count = 0 + for _k, _v in pairs(items.treasure) do count = count + 1 end + return count +end + +function skip_block_if_enabled(visible,enabled,max_columns,last_index) + if visible and enabled then + initialize_block() + current_slot = last_index + current_column = max_columns + update_indexes(max_columns,last_index) end end @@ -379,47 +537,50 @@ function print_equipment(status) end function print_bag(config, bag, max) - sort_table() + sort_table(bag) for key=1,max,1 do - if (bag[key].count > 0) then - print_item(config,bag[key],max) - else - print_slot(settings.slotImage.status.empty,config.maxColumns,max) - end + if (bag[key].count > 0) then + print_item(config,bag[key],max) + else + print_slot(settings.slotImage.status.empty,config.maxColumns,max) + end end end -function sort_table() - table.sort(bag, function(a,b) - if (a.status ~= b.status) then - return a.status > b.status - end - if (a.count > 0 and b.count > 0) then - full_stack_a = res.items[a.id].stack - a.count - full_stack_b = res.items[b.id].stack - b.count - if (full_stack_a ~= full_stack_b) then - return full_stack_a < full_stack_b +function sort_table(bag) + if (settings.slotImage.sort) then + table.sort(bag, function(a,b) + if (a.status ~= b.status) then + return a.status > b.status end - end - return a.count > b.count - end) + if (a.count > 0 and b.count > 0) then + full_stack_a = res.items[a.id].stack - a.count + full_stack_b = res.items[b.id].stack - b.count + if (full_stack_a ~= full_stack_b) then + return full_stack_a < full_stack_b + end + end + return a.count > b.count + end) + end end function print_item(config, item, last_index) + local s = settings.slotImage if (item.status == DEFAULT_ITEM_STATUS) then if (item.count == res.items[item.id].stack) then - print_slot(settings.slotImage.status.fullStack,config.maxColumns,last_index) + print_slot(s.status.fullStack,config.maxColumns,last_index) else - print_slot(settings.slotImage.status.default,config.maxColumns,last_index) + print_slot(s.status.default,config.maxColumns,last_index) end elseif (item.status == EQUIPPED_ITEM_STATUS) then - print_slot(settings.slotImage.status.equipped,config.maxColumns,last_index) + print_slot(s.status.equipped,config.maxColumns,last_index) elseif (item.status == LINKSHELL_EQUIPPED_ITEM_STATUS) then - print_slot(settings.slotImage.status.linkshellEquipped,config.maxColumns,last_index) + print_slot(s.status.linkshellEquipped,config.maxColumns,last_index) elseif (item.status == BAZAAR_ITEM_STATUS) then - print_slot(settings.slotImage.status.bazaar,config.maxColumns,last_index) + print_slot(s.status.bazaar,config.maxColumns,last_index) else - print_slot(settings.slotImage.status.empty,config.maxColumns,last_index) + print_slot(s.status.empty,config.maxColumns,last_index) end end @@ -435,34 +596,37 @@ end function print_slot_background(slot_color, max_columns, last_index) local slot_image = slot_images[current_block][current_slot] + local s = settings.slotImage if slot_image.background == nil then - slot_image.background = images.new(settings.slotImage.background) + slot_image.background = images.new(s.background) slot_image.background:pos(current_x,current_y) end - slot_image.background:width(settings.slotImage.background.size.width) - slot_image.background:height(settings.slotImage.background.size.height) + slot_image.background:width(s.background.size.width) + slot_image.background:height(s.background.size.height) slot_image.background:alpha(slot_color.alpha) slot_image.background:color(slot_color.red,slot_color.green,slot_color.blue) end function print_slot_box(slot_color, max_columns, last_index) local slot_image = slot_images[current_block][current_slot] + local s = settings.slotImage if slot_image.box == nil then - slot_image.box = images.new(settings.slotImage.box) + slot_image.box = images.new(s.box) slot_image.box:pos(current_x,current_y) end - slot_image.box:width(settings.slotImage.box.size.width) - slot_image.box:height(settings.slotImage.box.size.height) + slot_image.box:width(s.box.size.width) + slot_image.box:height(s.box.size.height) slot_image.box:color(slot_color.red,slot_color.green,slot_color.blue) slot_image.box:alpha(slot_color.alpha) end function update_coordinates() + local s = settings.slotImage current_x = xRes + xBase + - ((current_column - 1) * settings.slotImage.spacing) + - ((current_block - 1) * settings.slotImage.blockSpacing) + - ((last_column - 1) * settings.slotImage.spacing) - current_y = yRes + yBase - ((current_row - 1) * settings.slotImage.spacing) + ((current_column - 1) * s.spacing) + + ((current_block - 1) * s.blockSpacing) + + ((last_column - 1) * s.spacing) + current_y = yRes + yBase - ((current_row - 1) * s.spacing) end function update_indexes(max_columns, last_index) From 7ae450e4aab4bd3d5fb7e0325a39114582ba074a Mon Sep 17 00:00:00 2001 From: Mark Date: Sat, 27 Jan 2018 13:50:46 -0500 Subject: [PATCH 0050/1002] Update zone (0x0a) fields --- addons/libs/packets/fields.lua | 42 ++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index d2af2c0e5f..28bad9066c 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1206,7 +1206,18 @@ types.job_level = L{ fields.incoming[0x00A] = L{ {ctype='unsigned int', label='Player', fn=id}, -- 04 {ctype='unsigned short', label='Player Index', fn=index}, -- 08 - {ctype='data[38]', label='_unknown1'}, -- 0A + {ctype='unsigned char', label='_padding'}, -- 0A + {ctype='unsigned char', label='Heading', fn=dir}, -- 0B -- 0B to + {ctype='float', label='X'}, -- 0C + {ctype='float', label='Z'}, -- 10 + {ctype='float', label='Y'}, -- 14 + {ctype='unsigned short', label='Run Count'}, -- 18 + {ctype='unsigned short', label='Target Index', fn=index}, -- 1A + {ctype='unsigned char', label='Movement Speed'}, -- 1C 32 represents 100% + {ctype='unsigned char', label='Animation Speed'}, -- 1D 32 represents 100% + {ctype='unsigned char', label='HP %', fn=percent}, -- 1E + {ctype='unsigned char', label='Status', fn=statuses}, -- 1F + {ctype='data[16]', label='_unknown1'}, -- 20 {ctype='unsigned short', label='Zone', fn=zone}, -- 30 {ctype='data[6]', label='_unknown2'}, -- 32 {ctype='unsigned int', label='Timestamp 1', fn=time}, -- 38 @@ -1223,22 +1234,29 @@ fields.incoming[0x00A] = L{ {ctype='unsigned short', label='Main'}, -- 50 {ctype='unsigned short', label='Sub'}, -- 52 {ctype='unsigned short', label='Ranged'}, -- 54 - {ctype='data[18]', label='_unknown4'}, -- 56 + {ctype='unsigned short', label='Day Music'}, -- 56 + {ctype='unsigned short', label='Night Music'}, -- 58 + {ctype='unsigned short', label='Solo Combat Music'}, -- 5A + {ctype='unsigned short', label='Party Combat Music'}, -- 5C + {ctype='data[4]', label='_unknown4'}, -- 5E + {ctype='unsigned short', label='Menu Zone'}, -- 62 Only set if the menu ID is sent, used as the zone for menu responses (0x5b, 0x5c) + {ctype='unsigned short', label='Menu ID'}, -- 64 + {ctype='unsigned short', label='_unknown5'}, -- 66 {ctype='unsigned short', label='Weather', fn=weather}, -- 68 - {ctype='unsigned short', label='_unknown5'}, -- 6A - {ctype='data[24]', label='_unknown6'}, -- 6C + {ctype='unsigned short', label='_unknown6'}, -- 6A + {ctype='data[24]', label='_unknown7'}, -- 6C {ctype='char[16]', label='Player Name'}, -- 84 - {ctype='data[12]', label='_unknown7'}, -- 94 + {ctype='data[12]', label='_unknown8'}, -- 94 {ctype='unsigned int', label='Abyssea Timestamp', fn=time}, -- A0 - {ctype='unsigned int', label='_unknown8', const=0x0003A020}, -- A4 - {ctype='data[2]', label='_unknown9'}, -- A8 + {ctype='unsigned int', label='_unknown9', const=0x0003A020}, -- A4 + {ctype='data[2]', label='_unknown10'}, -- A8 {ctype='unsigned short', label='Zone model'}, -- AA - {ctype='data[8]', label='_unknown10'}, -- AC 0xAC is 2 for some zones, 0 for others + {ctype='data[8]', label='_unknown11'}, -- AC 0xAC is 2 for some zones, 0 for others {ctype='unsigned char', label='Main Job', fn=job}, -- B4 - {ctype='unsigned char', label='_unknown11'}, -- B5 - {ctype='unsigned char', label='_unknown12'}, -- B6 + {ctype='unsigned char', label='_unknown12'}, -- B5 + {ctype='unsigned char', label='_unknown13'}, -- B6 {ctype='unsigned char', label='Sub Job', fn=job}, -- B7 - {ctype='unsigned int', label='_unknown13'}, -- B8 + {ctype='unsigned int', label='_unknown14'}, -- B8 {ref=types.job_level, lookup={res.jobs, 0x00}, count=0x10}, -- BC {ctype='signed short', label='STR'}, -- CC {ctype='signed short', label='DEX'}, -- CE @@ -1256,7 +1274,7 @@ fields.incoming[0x00A] = L{ {ctype='signed short', label='CHR Bonus'}, -- E6 {ctype='unsigned int', label='Max HP'}, -- E8 {ctype='unsigned int', label='Max MP'}, -- EC - {ctype='data[20]', label='_unknown14'}, -- F0 + {ctype='data[20]', label='_unknown15'}, -- F0 } -- Zone Response From b4b8bfa13da230f0deecb6fa4be67fecc296d02c Mon Sep 17 00:00:00 2001 From: Chiaia Date: Fri, 23 Feb 2018 05:39:47 -0500 Subject: [PATCH 0051/1002] Update rolltracker.lua --- addons/rolltracker/rolltracker.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/rolltracker/rolltracker.lua b/addons/rolltracker/rolltracker.lua index 89eaf7c971..b14d2bad8e 100644 --- a/addons/rolltracker/rolltracker.lua +++ b/addons/rolltracker/rolltracker.lua @@ -124,7 +124,7 @@ windower.register_event('load', function() ['Ninja'] = {4,5,5,14,6,7,9,2,10,11,18,'-10',' Evasion Bonus',4, 2}, ['Scholar\'s'] = {'?','?','?','?','?','?','?','?','?','?','?','?',' Conserve MP',2, 0}, ['Allies\''] = {6,7,17,9,11,13,15,17,17,5,17,'?','% Skillchain Damage',3, 1,{6,11120, 27084, 27085, 5}}, - ['Companion\'s'] = {{4,20},{20, 50},{6,20},{8, 20},{10,30},{12,30},{14,30},{16,40},{18, 40}, {3,10},{30, 70},'-?',' Pet: Regen/Regain',2, {1,5}}, + ['Companion\'s'] = {{4,20},{20,50},{6,20},{8,20},{10,30},{12,30},{14,30},{16,40},{18,40},{3,10},{25,60},'-0',' Pet: Regen/Regain',2, {1,5}}, ['Avenger\'s'] = {'?','?','?','?','?','?','?','?','?','?','?','?',' Counter Rate',4, 0}, ['Blitzer\'s'] = {2,3.4,4.5,11.3,5.3,6.4,7.2,8.3,1.5,10.2,12.1,'-?', '% Attack delay reduction',4, 1, {4,11080, 26772, 26773, 5}}, ['Courser\'s'] = {'?','?','?','?','?','?','?','?','?','?','?','?',' Snapshot',3, 0}, --11160, 27443, 27444 From b4b7a8d2648b935fc603a47f7e5ddee03f41aa66 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Fri, 23 Feb 2018 20:49:23 -0500 Subject: [PATCH 0052/1002] Update rolltracker.lua --- addons/rolltracker/rolltracker.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/rolltracker/rolltracker.lua b/addons/rolltracker/rolltracker.lua index b14d2bad8e..287f68965c 100644 --- a/addons/rolltracker/rolltracker.lua +++ b/addons/rolltracker/rolltracker.lua @@ -124,7 +124,7 @@ windower.register_event('load', function() ['Ninja'] = {4,5,5,14,6,7,9,2,10,11,18,'-10',' Evasion Bonus',4, 2}, ['Scholar\'s'] = {'?','?','?','?','?','?','?','?','?','?','?','?',' Conserve MP',2, 0}, ['Allies\''] = {6,7,17,9,11,13,15,17,17,5,17,'?','% Skillchain Damage',3, 1,{6,11120, 27084, 27085, 5}}, - ['Companion\'s'] = {{4,20},{20,50},{6,20},{8,20},{10,30},{12,30},{14,30},{16,40},{18,40},{3,10},{25,60},'-0',' Pet: Regen/Regain',2, {1,5}}, + ['Companion\'s'] = {{4,20},{20,50},{6,20},{8,20},{10,30},{12,30},{14,30},{16,40},{18,40},{3,10},{25,60},'-0',' Pet: Regen/Regain',2, {2,5}}, ['Avenger\'s'] = {'?','?','?','?','?','?','?','?','?','?','?','?',' Counter Rate',4, 0}, ['Blitzer\'s'] = {2,3.4,4.5,11.3,5.3,6.4,7.2,8.3,1.5,10.2,12.1,'-?', '% Attack delay reduction',4, 1, {4,11080, 26772, 26773, 5}}, ['Courser\'s'] = {'?','?','?','?','?','?','?','?','?','?','?','?',' Snapshot',3, 0}, --11160, 27443, 27444 From b5905e685cfb8c0ce17a24d10948e2e5cde65a7e Mon Sep 17 00:00:00 2001 From: Karuberu Date: Thu, 1 Mar 2018 14:42:01 -0500 Subject: [PATCH 0053/1002] Lookup addon A simple addon that looks up search terms through in-game commands. --- addons/Lookup/Lookup.lua | 190 +++++++++++++++++++++++++++++++++++++++ addons/Lookup/README.md | 100 +++++++++++++++++++++ 2 files changed, 290 insertions(+) create mode 100644 addons/Lookup/Lookup.lua create mode 100644 addons/Lookup/README.md diff --git a/addons/Lookup/Lookup.lua b/addons/Lookup/Lookup.lua new file mode 100644 index 0000000000..819456a173 --- /dev/null +++ b/addons/Lookup/Lookup.lua @@ -0,0 +1,190 @@ +--[[ + Copyright (c) 2018, Karuberu + 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 Lookup 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 THE COPYRIGHT HOLDERS OR CONTRIBUTORS 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.name = 'Lookup' +_addon.author = 'Karuberu' +_addon.version = '1.0' +_addon.language = 'english' +_addon.command = 'lookup' + +config = require('config') +res = require('resources') + +settings = nil +ids = nil +last_item = nil + +function initialize() + load_settings() + initialize_ids() +end + +function load_settings() + settings = config.load({ + default = 'ffxiclopedia'; + url = { + ffxiclopedia = 'http://ffxiclopedia.wikia.com/wiki/Special:Search?go=Go&search=%s'; + bgwiki = 'https://www.bg-wiki.com/bg/Special:Search?go=Go&search=%s'; + ffxidb = { + item = 'http://www.ffxidb.com/items/%s'; + zone = 'http://www.ffxidb.com/zones/%s'; + search = 'http://www.ffxidb.com/search?q=%s'; + }; + ffxiah = { + item = 'http://www.ffxiah.com/item/%s'; + search = 'http://www.ffxiah.com/search/item?q=%s'; + player = 'https://www.ffxiah.com/search/player?name=%s'; + }; + google = 'https://www.google.com/search?q=%s'; + }; + }) +end + +function initialize_ids() + ids = { + items = {}; + zones = {}; + } + for item in res.items:it() do + ids.items[item.name] = item.id + ids.items[item.name_log] = item.id + end + for zone in res.zones:it() do + ids.zones[zone.name] = zone.id + end +end + +function find_id(name) + return { + item = ids.items[name]; + zone = ids.zones[name]; + } +end + +function get_name(id, list) + for key, value in next, list do + if value == id then + return key + end + end + return nil +end + +function translate(str) + return windower.convert_auto_trans(str) +end + +function get_selection(str) + local target = str:match('<(.+)>') + if target == 'job' then + str = windower.ffxi.get_player().main_job_full + elseif target == 'subjob' or target == 'sj' then + str = windower.ffxi.get_player().sub_job_full + elseif target == 'zone' or target == 'area' then + if windower.ffxi.get_info().mog_house then + str = 'Mog House' + else + str = get_name(windower.ffxi.get_info().zone, ids.zones) + end + elseif target == 'lastitem' or target == 'item' then + str = get_name(last_item, ids.items) + elseif target ~= nil then + local mob = windower.ffxi.get_mob_by_target(str:match('<(.+)>')) + if mob ~= nil then + str = mob.name + else + str = nil + end + end + return str +end + +function set_default(term) + settings.default = term + config.save(settings, 'all') +end + +function set_last_item(bag, index, id, count) + if bag == 0 then + last_item = id + end +end + +function process_command(command, term) + if term == nil or term == '' then + term = command + command = settings.default + else + command = command:lower() + end + + if command == 'default' then + set_default(term) + return + end + + term = translate(term) + term = get_selection(term) + + if term == nil or term == '' then + return + end + + local url + local id = find_id(term) + if command == 'ffxiclopedia' or command == 'ffxi' or command == 'wikia' then + url = settings.url.ffxiclopedia:format(term) + elseif command == 'bg' or command == 'bgwiki' or command == 'bg-wiki' then + url = settings.url.bgwiki:format(term) + elseif command == 'db' or command == 'ffxidb' then + if id.item ~= nil then + url = settings.url.ffxidb.item:format(id.item) + elseif id.zone ~= nil then + url = settings.url.ffxidb.zone:format(id.zone) + else + url = settings.url.ffxidb.search:format(term) + end + elseif command == 'ah' or command == 'ffxiah' then + if id.item ~= nil then + url = settings.url.ffxiah.item:format(id.item) + else + url = settings.url.ffxiah.search:format(term) + end + elseif command == 'ahp' or command == 'ffxiahp' or command == 'ffxiahplayer' then + url = settings.url.ffxiah.player:format(term) + elseif command == 'google' then + url = settings.url.google:format(term) + end + + if url ~= nil then + windower.open_url(url) + end +end + +windower.register_event('load', initialize) +windower.register_event('add item', set_last_item) +windower.register_event('addon command', process_command) diff --git a/addons/Lookup/README.md b/addons/Lookup/README.md new file mode 100644 index 0000000000..806c6fee60 --- /dev/null +++ b/addons/Lookup/README.md @@ -0,0 +1,100 @@ +# Lookup +A simple [Windower4](http://www.windower.net/) addon that looks up search terms through in-game commands. + +The default search is performed with the following command: +``` +//lookup "Search Term" +``` +This will open up the search in your default browser. + +The search term can be plain text, auto-translate text, or one of the available [selectors](#selectors). If the search term contains a space, it must be surrounded in quotes (this does not apply to selectors). + +The available search sites are [FFXIclopedia](http://ffxiclopedia.wikia.com/), [BGWiki](http://www.bg-wiki.com), [FFXIAH](http://www.ffxiah.com), [FFXIDB](http://www.ffxidb.com), and [Google](http://www.google.com). + +See the [commands](#commands) section for a list of all available commands. + +## Selectors +Selectors can be used in place of plain text search terms. They are very useful for quickly getting information about something in the environment or a recently obtained item. + +| Selector | Replacement | +|----------|-------------| +| `` | The current target's name. | +| `` | The current battle target'name . | +| `` | The name of the current player's pet. | +| `` | The current player's name. | +| `` | The name of the player that last sent a tell to you. | +| `` | The current player's main job. | +| ``
`` | The current player's subjob. | +| ``
`` | The current area/zone. | +| ``
`` | The last item placed in the player's inventory, including items moved from other bags. | + +## Commands +``` +//lookup "Search Term" +``` +Searches for the term on the default site. The default site is set to "ffxiclopedia" initially, but can be changed with the "default" command. + +#### Default +``` +//lookup default "site" +``` +Sets the default site to search with. Saved in the global settings (not character-specific). + +#### FFXIclopedia +``` +//lookup ffxiclopedia "Search Term" +``` +``` +//lookup ffxi "Search Term" +``` +``` +//lookup wikia "Search Term" +``` +Searches for the term on [FFXIclopedia](http://ffxiclopedia.wikia.com/). + +#### BGWiki +``` +//lookup bg-wiki "Search Term" +``` +``` +//lookup bgwiki "Search Term" +``` +``` +//lookup bg "Search Term" +``` +Searches for the term on [BGWiki](http://www.bg-wiki.com). + +#### FFXIAH +``` +//lookup ffxiah "Item" +``` +``` +//lookup ah "Item" +``` +Searches for the item on [FFXIAH](http://www.ffxiah.com). + +``` +//lookup ffxiahplayer "Player" +``` +``` +//lookup ffxiahp "Player" +``` +``` +//lookup ahp "Player" +``` +Searches for the player on [FFXIAH](http://www.ffxiah.com). + +#### FFXIDB +``` +//lookup ffxidb "Search Term" +``` +``` +//lookup db "Search Term" +``` +Searches for the term on [FFXIDB](http://www.ffxidb.com). + +#### Google +``` +//lookup google "Search Term" +``` +Searches for the term on [Google](http://www.google.com). From 4ba76f01f5b68864d04f1f9d993ffa9e31e60f47 Mon Sep 17 00:00:00 2001 From: Karuberu Date: Sun, 4 Mar 2018 21:50:00 -0500 Subject: [PATCH 0054/1002] Tabs to spaces *Converted tabs to four spaces. --- addons/Lookup/Lookup.lua | 284 +++++++++++++++++++-------------------- 1 file changed, 142 insertions(+), 142 deletions(-) diff --git a/addons/Lookup/Lookup.lua b/addons/Lookup/Lookup.lua index 819456a173..524d490d4c 100644 --- a/addons/Lookup/Lookup.lua +++ b/addons/Lookup/Lookup.lua @@ -1,29 +1,29 @@ --[[ - Copyright (c) 2018, Karuberu - 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 Lookup 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 THE COPYRIGHT HOLDERS OR CONTRIBUTORS 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. + Copyright (c) 2018, Karuberu + 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 Lookup 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 THE COPYRIGHT HOLDERS OR CONTRIBUTORS 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.name = 'Lookup' _addon.author = 'Karuberu' @@ -39,150 +39,150 @@ ids = nil last_item = nil function initialize() - load_settings() - initialize_ids() + load_settings() + initialize_ids() end function load_settings() - settings = config.load({ - default = 'ffxiclopedia'; - url = { - ffxiclopedia = 'http://ffxiclopedia.wikia.com/wiki/Special:Search?go=Go&search=%s'; - bgwiki = 'https://www.bg-wiki.com/bg/Special:Search?go=Go&search=%s'; - ffxidb = { - item = 'http://www.ffxidb.com/items/%s'; - zone = 'http://www.ffxidb.com/zones/%s'; - search = 'http://www.ffxidb.com/search?q=%s'; - }; - ffxiah = { - item = 'http://www.ffxiah.com/item/%s'; - search = 'http://www.ffxiah.com/search/item?q=%s'; - player = 'https://www.ffxiah.com/search/player?name=%s'; - }; - google = 'https://www.google.com/search?q=%s'; - }; - }) + settings = config.load({ + default = 'ffxiclopedia'; + url = { + ffxiclopedia = 'http://ffxiclopedia.wikia.com/wiki/Special:Search?go=Go&search=%s'; + bgwiki = 'https://www.bg-wiki.com/bg/Special:Search?go=Go&search=%s'; + ffxidb = { + item = 'http://www.ffxidb.com/items/%s'; + zone = 'http://www.ffxidb.com/zones/%s'; + search = 'http://www.ffxidb.com/search?q=%s'; + }; + ffxiah = { + item = 'http://www.ffxiah.com/item/%s'; + search = 'http://www.ffxiah.com/search/item?q=%s'; + player = 'https://www.ffxiah.com/search/player?name=%s'; + }; + google = 'https://www.google.com/search?q=%s'; + }; + }) end function initialize_ids() - ids = { - items = {}; - zones = {}; - } - for item in res.items:it() do - ids.items[item.name] = item.id - ids.items[item.name_log] = item.id - end - for zone in res.zones:it() do - ids.zones[zone.name] = zone.id - end + ids = { + items = {}; + zones = {}; + } + for item in res.items:it() do + ids.items[item.name] = item.id + ids.items[item.name_log] = item.id + end + for zone in res.zones:it() do + ids.zones[zone.name] = zone.id + end end function find_id(name) - return { - item = ids.items[name]; - zone = ids.zones[name]; - } + return { + item = ids.items[name]; + zone = ids.zones[name]; + } end function get_name(id, list) - for key, value in next, list do - if value == id then - return key - end - end - return nil + for key, value in next, list do + if value == id then + return key + end + end + return nil end function translate(str) - return windower.convert_auto_trans(str) + return windower.convert_auto_trans(str) end function get_selection(str) - local target = str:match('<(.+)>') - if target == 'job' then - str = windower.ffxi.get_player().main_job_full - elseif target == 'subjob' or target == 'sj' then - str = windower.ffxi.get_player().sub_job_full - elseif target == 'zone' or target == 'area' then - if windower.ffxi.get_info().mog_house then - str = 'Mog House' - else - str = get_name(windower.ffxi.get_info().zone, ids.zones) - end - elseif target == 'lastitem' or target == 'item' then - str = get_name(last_item, ids.items) - elseif target ~= nil then - local mob = windower.ffxi.get_mob_by_target(str:match('<(.+)>')) - if mob ~= nil then - str = mob.name - else - str = nil - end - end - return str + local target = str:match('<(.+)>') + if target == 'job' then + str = windower.ffxi.get_player().main_job_full + elseif target == 'subjob' or target == 'sj' then + str = windower.ffxi.get_player().sub_job_full + elseif target == 'zone' or target == 'area' then + if windower.ffxi.get_info().mog_house then + str = 'Mog House' + else + str = get_name(windower.ffxi.get_info().zone, ids.zones) + end + elseif target == 'lastitem' or target == 'item' then + str = get_name(last_item, ids.items) + elseif target ~= nil then + local mob = windower.ffxi.get_mob_by_target(str:match('<(.+)>')) + if mob ~= nil then + str = mob.name + else + str = nil + end + end + return str end function set_default(term) - settings.default = term - config.save(settings, 'all') + settings.default = term + config.save(settings, 'all') end function set_last_item(bag, index, id, count) - if bag == 0 then - last_item = id - end + if bag == 0 then + last_item = id + end end function process_command(command, term) - if term == nil or term == '' then - term = command - command = settings.default - else - command = command:lower() - end - - if command == 'default' then - set_default(term) - return - end - - term = translate(term) - term = get_selection(term) - - if term == nil or term == '' then - return - end - - local url - local id = find_id(term) - if command == 'ffxiclopedia' or command == 'ffxi' or command == 'wikia' then - url = settings.url.ffxiclopedia:format(term) - elseif command == 'bg' or command == 'bgwiki' or command == 'bg-wiki' then - url = settings.url.bgwiki:format(term) - elseif command == 'db' or command == 'ffxidb' then - if id.item ~= nil then - url = settings.url.ffxidb.item:format(id.item) - elseif id.zone ~= nil then - url = settings.url.ffxidb.zone:format(id.zone) - else - url = settings.url.ffxidb.search:format(term) - end - elseif command == 'ah' or command == 'ffxiah' then - if id.item ~= nil then - url = settings.url.ffxiah.item:format(id.item) - else - url = settings.url.ffxiah.search:format(term) - end - elseif command == 'ahp' or command == 'ffxiahp' or command == 'ffxiahplayer' then - url = settings.url.ffxiah.player:format(term) - elseif command == 'google' then - url = settings.url.google:format(term) - end - - if url ~= nil then - windower.open_url(url) - end + if term == nil or term == '' then + term = command + command = settings.default + else + command = command:lower() + end + + if command == 'default' then + set_default(term) + return + end + + term = translate(term) + term = get_selection(term) + + if term == nil or term == '' then + return + end + + local url + local id = find_id(term) + if command == 'ffxiclopedia' or command == 'ffxi' or command == 'wikia' then + url = settings.url.ffxiclopedia:format(term) + elseif command == 'bg' or command == 'bgwiki' or command == 'bg-wiki' then + url = settings.url.bgwiki:format(term) + elseif command == 'db' or command == 'ffxidb' then + if id.item ~= nil then + url = settings.url.ffxidb.item:format(id.item) + elseif id.zone ~= nil then + url = settings.url.ffxidb.zone:format(id.zone) + else + url = settings.url.ffxidb.search:format(term) + end + elseif command == 'ah' or command == 'ffxiah' then + if id.item ~= nil then + url = settings.url.ffxiah.item:format(id.item) + else + url = settings.url.ffxiah.search:format(term) + end + elseif command == 'ahp' or command == 'ffxiahp' or command == 'ffxiahplayer' then + url = settings.url.ffxiah.player:format(term) + elseif command == 'google' then + url = settings.url.google:format(term) + end + + if url ~= nil then + windower.open_url(url) + end end windower.register_event('load', initialize) From de908b6b04a0ff5566c3a7bd7c7b465b499d01bc Mon Sep 17 00:00:00 2001 From: Karuberu Date: Sun, 4 Mar 2018 21:58:59 -0500 Subject: [PATCH 0055/1002] Configuration and efficiency improvements +Added lookup to the addons.xml file. +Added "lu" as a shortened version of the "lookup" addon command. +Added commands for modifying site settings. *Corrected the copyright symbol. *Modified the site settings to use "${term}" instead of "%s". *Modified the site settings to be more user configurable. *Renamed a few functions so that their purpose is more clear. *Modified get_name to be more efficient. *Modified the selectors to be more clear and consistent with FFXI. *Modified the "default" command to allow player-specific settings. -Removed the addon language restriction. --- addons/Lookup/Lookup.lua | 224 ++++++++++++++++++++++++--------------- addons/Lookup/README.md | 59 +++++++++-- addons/addons.xml | 7 ++ 3 files changed, 201 insertions(+), 89 deletions(-) diff --git a/addons/Lookup/Lookup.lua b/addons/Lookup/Lookup.lua index 524d490d4c..652c66273b 100644 --- a/addons/Lookup/Lookup.lua +++ b/addons/Lookup/Lookup.lua @@ -1,5 +1,5 @@ --[[ - Copyright (c) 2018, Karuberu + Copyright © 2018, Karuberu All rights reserved. Redistribution and use in source and binary forms, with or without @@ -28,8 +28,7 @@ _addon.name = 'Lookup' _addon.author = 'Karuberu' _addon.version = '1.0' -_addon.language = 'english' -_addon.command = 'lookup' +_addon.commands = {'lookup', 'lu'} config = require('config') res = require('resources') @@ -38,32 +37,44 @@ settings = nil ids = nil last_item = nil -function initialize() - load_settings() - initialize_ids() -end - function load_settings() settings = config.load({ default = 'ffxiclopedia'; - url = { - ffxiclopedia = 'http://ffxiclopedia.wikia.com/wiki/Special:Search?go=Go&search=%s'; - bgwiki = 'https://www.bg-wiki.com/bg/Special:Search?go=Go&search=%s'; + sites = { + ffxiclopedia = { + search = 'http://ffxiclopedia.wikia.com/wiki/Special:Search?go=Go&search=${term}'; + }; + ['bg-wiki'] = { + search = 'https://www.bg-wiki.com/bg/Special:Search?go=Go&search=${term}'; + }; ffxidb = { - item = 'http://www.ffxidb.com/items/%s'; - zone = 'http://www.ffxidb.com/zones/%s'; - search = 'http://www.ffxidb.com/search?q=%s'; + item = 'http://www.ffxidb.com/items/${term}'; + zone = 'http://www.ffxidb.com/zones/${term}'; + search = 'http://www.ffxidb.com/search?q=${term}'; }; ffxiah = { - item = 'http://www.ffxiah.com/item/%s'; - search = 'http://www.ffxiah.com/search/item?q=%s'; - player = 'https://www.ffxiah.com/search/player?name=%s'; + item = 'http://www.ffxiah.com/item/${term}'; + search = 'http://www.ffxiah.com/search/item?q=${term}'; + }; + ffxiahplayer = { + search = 'https://www.ffxiah.com/search/player?name=${term}'; + }; + google = { + search = 'https://www.google.com/search?q=${term}'; }; - google = 'https://www.google.com/search?q=%s'; + ffxi = { redirect = 'ffxiclopedia'; }; + wikia = { redirect = 'ffxiclopedia'; }; + bgwiki = { redirect = 'bg-wiki'; }; + bg = { redirect = 'bg-wiki'; }; + db = { redirect = 'ffxidb'; }; + ah = { redirect = 'ffxiah'; }; + ffxiahp = { redirect = 'ffxiahplayer'; }; + ahp = { redirect = 'ffxiahplayer'; }; }; }) end +-- Creates a list of item and zone ids by name for quicker lookup by name function initialize_ids() ids = { items = {}; @@ -74,11 +85,14 @@ function initialize_ids() ids.items[item.name_log] = item.id end for zone in res.zones:it() do - ids.zones[zone.name] = zone.id + ids.zones[zone.name] = zone.id end end -function find_id(name) +function get_id(name) + if id == nil then + return {} + end return { item = ids.items[name]; zone = ids.zones[name]; @@ -86,46 +100,60 @@ function find_id(name) end function get_name(id, list) - for key, value in next, list do - if value == id then - return key - end + if id == nil then + return nil end - return nil + return (list[id] or {}).name end +-- Converts auto-translate strings to plain text. +-- If the string is not an auto-translate string, the original string is returned. function translate(str) return windower.convert_auto_trans(str) end -function get_selection(str) +-- Checks to see if the string is a selector (enclosed by <>) and returns a replacement. +-- If the string is not a selector, the original string is returned. +function parse_selection(str) local target = str:match('<(.+)>') - if target == 'job' then - str = windower.ffxi.get_player().main_job_full - elseif target == 'subjob' or target == 'sj' then - str = windower.ffxi.get_player().sub_job_full - elseif target == 'zone' or target == 'area' then + if target == nil then + return str + end + + -- custom selection handlers + if target == 'job' or target == 'mjob' then + return windower.ffxi.get_player().main_job_full + elseif target == 'sjob' then + return windower.ffxi.get_player().sub_job_full + elseif target == 'zone' then if windower.ffxi.get_info().mog_house then - str = 'Mog House' + return 'Mog House' else - str = get_name(windower.ffxi.get_info().zone, ids.zones) - end - elseif target == 'lastitem' or target == 'item' then - str = get_name(last_item, ids.items) - elseif target ~= nil then - local mob = windower.ffxi.get_mob_by_target(str:match('<(.+)>')) - if mob ~= nil then - str = mob.name - else - str = nil + return get_name(windower.ffxi.get_info().zone, res.zones) end + elseif target == 'item' then + return get_name(last_item, res.items) + end + -- default to windower's selection handlers + return (windower.ffxi.get_mob_by_target(str) or {}).name +end + +function set_default_site(command_modifier, site) + settings.default = site + if command_modifier == 'player' or command_modifier == 'p' then + -- save only for the current character + settings:save() + else + -- save for all characters + settings:save('all') end - return str end -function set_default(term) - settings.default = term - config.save(settings, 'all') +function modify_site_settings(site, type, url) + if url == 'remove' then + url = nil + end + settings.sites[site][type] = url end function set_last_item(bag, index, id, count) @@ -134,57 +162,87 @@ function set_last_item(bag, index, id, count) end end -function process_command(command, term) - if term == nil or term == '' then - term = command - command = settings.default +-- Replaces the named parameters in the url +function format_url(url, term) + if term == nil then + return term + end + return url:gsub('${term}', '%s':format(term)) +end + +function get_site(command) + local site = settings.sites[command] + if site ~= nil and site.redirect ~= nil then + site = settings.sites[site.redirect] + end + return site +end + +function get_url(site, term) + term = translate(term) + term = parse_selection(term) + local id = get_id(term) + if id.item ~= nil and site.item ~= nil then + url = format_url(site.item, id.item) + elseif id.zone ~= nil and site.zone ~= nil then + url = format_url(site.zone, id.zone) else - command = command:lower() + url = format_url(site.search, term) end + return url +end + +function process_command(...) + -- get the first argument and set it as the command for now + local command = ({...}[1] or ''):lower() if command == 'default' then - set_default(term) + local command_modifier, default_site + if {...}[3] ~= nil then + -- if there are three or more arguments, the second one is the modifier + command_modifier = {...}[2] + default_site = {...}[3] + else + default_site = {...}[2] + end + set_default_site(command_modifier, default_site) + return + elseif command == 'site' then + local site = {...}[2] + local type = {...}[3] + local url = {...}[4] + modify_site_settings(site, type, url) return end - term = translate(term) - term = get_selection(term) - - if term == nil or term == '' then + local term; + if {...}[2] ~= nil then + -- if there are two arguments, the first is the command and the second the term + command = {...}[1] + term = {...}[2] + else + -- otherwise, just a term is provided, so use the default command + command = settings.default + term = {...}[1] + end + if term == nil then return end - local url - local id = find_id(term) - if command == 'ffxiclopedia' or command == 'ffxi' or command == 'wikia' then - url = settings.url.ffxiclopedia:format(term) - elseif command == 'bg' or command == 'bgwiki' or command == 'bg-wiki' then - url = settings.url.bgwiki:format(term) - elseif command == 'db' or command == 'ffxidb' then - if id.item ~= nil then - url = settings.url.ffxidb.item:format(id.item) - elseif id.zone ~= nil then - url = settings.url.ffxidb.zone:format(id.zone) - else - url = settings.url.ffxidb.search:format(term) - end - elseif command == 'ah' or command == 'ffxiah' then - if id.item ~= nil then - url = settings.url.ffxiah.item:format(id.item) - else - url = settings.url.ffxiah.search:format(term) - end - elseif command == 'ahp' or command == 'ffxiahp' or command == 'ffxiahplayer' then - url = settings.url.ffxiah.player:format(term) - elseif command == 'google' then - url = settings.url.google:format(term) + local site = get_site(command:lower()) + if site == nil then + return end - if url ~= nil then - windower.open_url(url) + local url = get_url(site, term) + if url == nil then + return end + windower.open_url(url) end -windower.register_event('load', initialize) +load_settings() +initialize_ids() + windower.register_event('add item', set_last_item) windower.register_event('addon command', process_command) diff --git a/addons/Lookup/README.md b/addons/Lookup/README.md index 806c6fee60..d091c0e983 100644 --- a/addons/Lookup/README.md +++ b/addons/Lookup/README.md @@ -5,17 +5,33 @@ The default search is performed with the following command: ``` //lookup "Search Term" ``` -This will open up the search in your default browser. +Alternatively, the shorthand `lu` can be used: +``` +//lu "Search Term" +``` + +Running this command will open up the search in your default browser. The search term can be plain text, auto-translate text, or one of the available [selectors](#selectors). If the search term contains a space, it must be surrounded in quotes (this does not apply to selectors). -The available search sites are [FFXIclopedia](http://ffxiclopedia.wikia.com/), [BGWiki](http://www.bg-wiki.com), [FFXIAH](http://www.ffxiah.com), [FFXIDB](http://www.ffxidb.com), and [Google](http://www.google.com). +The default search sites are [FFXIclopedia](http://ffxiclopedia.wikia.com/), [BGWiki](http://www.bg-wiki.com), [FFXIAH](http://www.ffxiah.com), [FFXIDB](http://www.ffxidb.com), and [Google](http://www.google.com). See the [site command](#site) for how to add additional sites. See the [commands](#commands) section for a list of all available commands. ## Selectors Selectors can be used in place of plain text search terms. They are very useful for quickly getting information about something in the environment or a recently obtained item. +The following selectors are accepted by this addon: + +| Selector | Replacement | +|----------|-------------| +| ``
`` | The current player's main job. | +| `` | The current player's subjob. | +| `` | The current area/zone. | +| `` | The last item placed in the player's inventory, including items moved from other bags. | + +The selectors found in [Windower's documentation](https://github.com/Windower/Lua/wiki/FFXI-Functions#windowerffxiget_mob_by_targettarget) are also accepted. Some of the more useful selectors are listed below, for convenience: + | Selector | Replacement | |----------|-------------| | `` | The current target's name. | @@ -23,10 +39,6 @@ Selectors can be used in place of plain text search terms. They are very useful | `` | The name of the current player's pet. | | `` | The current player's name. | | `` | The name of the player that last sent a tell to you. | -| `` | The current player's main job. | -| ``
`` | The current player's subjob. | -| ``
`` | The current area/zone. | -| ``
`` | The last item placed in the player's inventory, including items moved from other bags. | ## Commands ``` @@ -34,12 +46,47 @@ Selectors can be used in place of plain text search terms. They are very useful ``` Searches for the term on the default site. The default site is set to "ffxiclopedia" initially, but can be changed with the "default" command. +Alternatively, the shorthand `lu` can be used: +``` +//lu "Search Term" +``` + #### Default ``` //lookup default "site" ``` Sets the default site to search with. Saved in the global settings (not character-specific). +``` +//lookup default player "site" +``` +``` +//lookup default p "site" +``` +Saves the default site only for the current player. + +#### Site +``` +//lookup site "site" search "http://www.example.com/search?q=${term}" +``` +Adds or modifies the site lookup capability. + +The second argument, `"site"` is the site that you're modifying. For example, specifying `"ffxiclopedia"` would modify the settings for `ffxiclopedia` searches. New sites can also be added this way. + +The third argument, `search`, can be substituted for `zone` or `item` if the site supports zone or item ids in its url. + +The last argument is the url of the search. The `${term}` in the url will be substituted for the search term when a lookup is performed. + +``` +//lookup site "site" remove +``` +Removes all lookup capability for the specified site (`"site"`). + +``` +//lookup site "site" search remove +``` +Removes the `search` lookup capability for the specified site (`"site"`). The `search` argument can also be substituted for `zone` or `item`. + #### FFXIclopedia ``` //lookup ffxiclopedia "Search Term" diff --git a/addons/addons.xml b/addons/addons.xml index 9e075fdd77..5bc38003ff 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -309,6 +309,13 @@ https://github.com/Windower/Lua/issues http://www.ffxiah.com/player/Leviathan/Arcon + + Lookup + Karuberu + Lookup website information from an in-game command. Accepts auto-translate text and selectors like "<t>". Opens in a browser window. + https://github.com/Karuberu/Lua/issues + https://github.com/Karuberu/Lua/issues + Lottery Arcon From 402332774431d80d80de56757c6d27bc3abdf826 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Sat, 17 Mar 2018 09:17:58 -0400 Subject: [PATCH 0056/1002] Update rolltracker.lua --- addons/rolltracker/rolltracker.lua | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/addons/rolltracker/rolltracker.lua b/addons/rolltracker/rolltracker.lua index 287f68965c..c7b3a4cdaf 100644 --- a/addons/rolltracker/rolltracker.lua +++ b/addons/rolltracker/rolltracker.lua @@ -25,7 +25,7 @@ --SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'RollTracker' -_addon.version = '1.6.0.0' +_addon.version = '1.7.0.0' _addon.author = 'Balloon' _addon.command = 'rolltracker' @@ -105,26 +105,26 @@ windower.register_event('load', function() ['Evoker\'s'] = {1,1,1,1,3,2,2,2,1,3,4,'-1', ' Refresh!',5, 1}, ['Rogue\'s'] = {2,2,3,4,12,5,6,6,1,8,14,'-6', '% Critical Hit Rate!', 5, 1}, ['Corsair\'s'] = {10, 11, 11, 12, 20, 13, 15, 16, 8, 17, 24, '-6', '% Experience Bonus',5, 2}, - ['Hunter\'s'] = {10,13,15,40,18,20,25,5,27,30,50,'-?', ' Accuracy Bonus',4, 5}, + ['Hunter\'s'] = {10,13,15,40,18,20,25,5,28,30,50,'-15', ' Accuracy Bonus',4, 5}, ['Magus\'s'] = {5,20,6,8,9,3,10,13,14,15,25,'-8',' Magic Defense Bonus',2, 2}, ['Healer\'s'] = {3,4,12,5,6,7,1,8,9,10,16,'-4','% Cure Potency',3, 1}, - ['Drachen'] = {10,13,15,40,18,20,25,5,28,30,50,'-15',' Pet: Accuracy Bonus',4, 5}, - ['Choral'] = {8,42,11,15,19,4,23,27,31,35,50,'+25', '- Spell Interruption Rate',2, 0}, + ['Drachen'] = {10,13,15,40,18,20,25,5,28,30,50,'0',' Pet: Accuracy Bonus',4, 5}, + ['Choral'] = {8,42,11,15,19,4,23,27,31,35,50,'+25', '- Spell Interruption Rate',2, 4}, ['Monk\'s'] = {8,10,32,12,14,15,4,20,22,24,40,'-?', ' Subtle Blow', 3, 4}, - ['Beast'] = {6,8,9,25,11,13,16,3,17,19,31,'-10', '% Pet: Attack Bonus',4, 3}, + ['Beast'] = {6,8,9,25,11,13,16,3,17,19,31,'0', '% Pet: Attack Bonus',4, 3}, ['Samurai'] = {7,32,10,12,14,4,16,20,22,24,40,'-10',' Store TP Bonus',2, 4}, ['Warlock\'s'] = {2,3,4,12,5,6,7,1,8,9,15,'-5',' Magic Accuracy Bonus',4, 1}, ['Puppet'] = {5,8,35,11,14,18,2,22,26,30,40,'-8',' Pet: Magic Attack Bonus',3, 3}, ['Gallant\'s'] = {48,60,200,72,88,104,32,120,140,160,240,'-11.72','% Defense Bonus', 3, 24},--/1024 ['Dancer\'s'] = {3,4,12,5,6,7,1,8,9,10,16,'-4',' Regen',3, 2}, - ['Bolter\'s'] = {0.3,0.3,0.8,0.4,0.4,0.5,0.5,0.6,0.2,0.7,1.0,'-8','% Movement Speed',3, 0.2}, + ['Bolter\'s'] = {0.3,0.3,0.8,0.4,0.4,0.5,0.5,0.6,0.2,0.7,1.0,'0','% Movement Speed',3, 0.2}, ['Caster\'s'] = {6,15,7,8,9,10,5,11,12,13,20,'-10','% Fast Cast',2, 3,{7, 11140, 27269, 27269, 10}}, ['Tactician\'s'] = {10,10,10,10,30,10,10,0,20,20,40,'-10',' Regain',5, 2, {5, 11100, 26930, 26931, 10}}, ['Miser\'s'] = {30,50,70,90,200,110,20,130,150,170,250,'0',' Save TP',5, 15}, - ['Ninja'] = {4,5,5,14,6,7,9,2,10,11,18,'-10',' Evasion Bonus',4, 2}, + ['Ninja'] = {10,13,15,40,18,20,25,5,28,30,50,'-15',' Evasion Bonus',4, 5}, ['Scholar\'s'] = {'?','?','?','?','?','?','?','?','?','?','?','?',' Conserve MP',2, 0}, ['Allies\''] = {6,7,17,9,11,13,15,17,17,5,17,'?','% Skillchain Damage',3, 1,{6,11120, 27084, 27085, 5}}, - ['Companion\'s'] = {{4,20},{20,50},{6,20},{8,20},{10,30},{12,30},{14,30},{16,40},{18,40},{3,10},{25,60},'-0',' Pet: Regen/Regain',2, {2,5}}, + ['Companion\'s'] = {{4,20},{20,50},{6,20},{8,20},{10,30},{12,30},{14,30},{16,40},{18,40},{3,10},{25,60},'0',' Pet: Regen/Regain',2, {2,5}}, ['Avenger\'s'] = {'?','?','?','?','?','?','?','?','?','?','?','?',' Counter Rate',4, 0}, ['Blitzer\'s'] = {2,3.4,4.5,11.3,5.3,6.4,7.2,8.3,1.5,10.2,12.1,'-?', '% Attack delay reduction',4, 1, {4,11080, 26772, 26773, 5}}, ['Courser\'s'] = {'?','?','?','?','?','?','?','?','?','?','?','?',' Snapshot',3, 0}, --11160, 27443, 27444 From d90c602327f104ea8acd029ef0f7cf69873ac287 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Wed, 21 Mar 2018 11:14:42 -0400 Subject: [PATCH 0057/1002] Update fields.lua --- addons/libs/packets/fields.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 28bad9066c..9742ae290e 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -95,8 +95,7 @@ do end bufftime = function(ts) - -- Todo... - return fn(ts) + return fn((ts / 60) + 501079520 + 1009810800) end end From 8355e1364248fcacbb4b9e8854e74f3c0a58d502 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Wed, 21 Mar 2018 11:28:04 -0400 Subject: [PATCH 0058/1002] Update packet_parsing.lua --- addons/GearSwap/packet_parsing.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/GearSwap/packet_parsing.lua b/addons/GearSwap/packet_parsing.lua index f035b1887c..7a5295e1a2 100644 --- a/addons/GearSwap/packet_parsing.lua +++ b/addons/GearSwap/packet_parsing.lua @@ -456,7 +456,7 @@ parse.i[0x063] = function (data) for i=1,32 do local buff_id = data:unpack('H',i*2+7) if buff_id ~= 255 and buff_id ~= 0 then -- 255 is used for "no buff" - local t = data:unpack('I',i*4+0x45)/60+1439307535 + local t = data:unpack('I',i*4+0x45)/60+501079520+1009810800 newbuffs[i] = setmetatable({ name=res.buffs[buff_id].name, buff=copy_entry(res.buffs[buff_id]), @@ -710,4 +710,4 @@ function initialize_packet_parsing() end end -end \ No newline at end of file +end From 197cab47452819ebe777a2c20db873084f5a2ec0 Mon Sep 17 00:00:00 2001 From: John Hobart Date: Fri, 23 Mar 2018 17:48:52 -0400 Subject: [PATCH 0059/1002] SpellBook initial commit --- addons/SpellBook/SpellBook.lua | 257 +++++++++++++++++++++++++++++++++ addons/SpellBook/readme.md | 19 +++ 2 files changed, 276 insertions(+) create mode 100644 addons/SpellBook/SpellBook.lua create mode 100644 addons/SpellBook/readme.md diff --git a/addons/SpellBook/SpellBook.lua b/addons/SpellBook/SpellBook.lua new file mode 100644 index 0000000000..dc655379aa --- /dev/null +++ b/addons/SpellBook/SpellBook.lua @@ -0,0 +1,257 @@ +_addon.name = 'SpellBook' +_addon.author = 'SigilBaram' +_addon.version = '0.0.1' +_addon.command = 'sb' + +require('sets') +require('tables') +res = require('resources') + +spell_types = { + whitemagic= { type = 'WhiteMagic', readable = 'White Magic spells' }, + blackmagic= { type = 'BlackMagic', readable = 'Black Magic spells' }, + songs= { type = 'BardSong', readable = 'Bard songs' }, + ninjutsu= { type = 'Ninjutsu', readable = 'Ninjutsu' }, + summoning= { type = 'SummonerPact', readable = 'Summoning spells' }, + bluemagic= { type = 'BlueMagic', readable = 'Blue Magic spels' }, + geomancy= { type = 'Geomancy', readable = 'Geomancy spells' }, + trusts= { type = 'Trust', readable = 'Trusts'}, + all= { type = 'all', readable = 'spells of all types'} +} + +windower.register_event( 'addon command', function ( command, ... ) + local args = L{...} + local player = windower.ffxi.get_player() + local jobs = build_job_list() + + command = command and command:lower() + + if command == 'help' then + display_help() + elseif command == nil or command == 'current' then + spells_by_current() + elseif command == 'main' then + local level = args[1] or player.main_job_level + if level == 'all' or tonumber(level) ~= nil then + if level == 'all' then + level = 1500 + end + level = tonumber(level) + spells_by_job( player.main_job_id, tonumber(level) ) + else + invalid_input() + end + elseif command == 'sub' then + local level = args[1] or player.sub_job_level + if level == 'all' or tonumber(level) ~= nil then + spells_by_job( player.sub_job_id, tonumber(level) ) + else + invalid_input() + end + elseif spell_types[command:lower()] then + if args[1] == 'all' then + spells_by_type( spell_types[command:lower()], false ) + else + spells_by_type( spell_types[command:lower()], true ) + end + elseif jobs[command:lower()] then + local job = jobs[command:upper()] + local level = args[1] or player.jobs[res.jobs[job].ens] + if level == 'all' then + level = 1500 + end + spells_by_job( job, tonumber(level) ) + else + invalid_input() + end +end) + +--[[Builds a list of jobs with short name as the key and id as the value.]] +function build_job_list() + local jobs = {} + for id,val in pairs(res.jobs) do + jobs[val.ens] = id + end + return jobs +end + +--[[Display an error message for invalid input.]] +function invalid_input() + windower.add_to_chat( 7, 'Invalid input. See //' .. _addon.command .. ' help.') +end + +--[[Display help text for the addon.]] +function display_help() + windower.add_to_chat( 7, _addon.name .. ' version ' .. _addon.version ) + windower.add_to_chat( 7, '//' .. _addon.command .. ' help -- show this help text' ) + windower.add_to_chat( 7, '//' .. _addon.command .. ' [current] -- Shows learnable spells based on current main and sub job and level.') + windower.add_to_chat( 7, '//' .. _addon.command .. ' [] -- Show missing spells for current main or sub job. Defaults to the job\'s current level.' ) + windower.add_to_chat( 7, '//' .. _addon.command .. ' [] -- Show missings spells for specified job and level. Defaults to the job\'s level.' ) + windower.add_to_chat( 7, '//' .. _addon.command .. ' [all]-- Show learnable spells by category. Limited to spells which are learnable, unless all is added after the category.' ) + windower.add_to_chat( 7, 'Categories: whitemagic|blackmagic|songs|ninjustu|summoning|bluemagic|geomancy|trusts|all (Trusts are not included in all)' ) +end + +--[[Returns true if the player has a job which is high enough level to learn + the given spell.]] +function is_learnable(spell) + local player_levels = windower.ffxi.get_player().jobs + for job,level in pairs(spell.levels) do + if player_levels[res.jobs[job].ens] >= level then + return true + end + end + return false +end + +--[[Formats a spell as the spell's name followed by a list of jobs and levels + which would qualify to learn the spell.]] +function format_spell(spell) + local format = string.format('%-20s',spell.en) + + if spell.type ~= 'Trust' then + local levels = T{} + for job_id,level in pairs(spell.levels) do + levels:append( res.jobs[job_id].ens .. ' ' .. tostring(level) ) + end + format = format .. ' ( ' .. levels:concat(', ') .. ' )' + else + format = format .. ' ( Trust )' + end + return format +end + +--[[Show missing spells of a given type. If learnable is true, then the + results will be limited to spells for which the player has a job at a + level required to learn the spell.]] +function spells_by_type(spell_type, learnable) + local missing_spells = T{} + local player_spells = windower.ffxi.get_spells() + + for spell_id,spell in pairs(res.spells) do + if ((spell_type.type == 'all' and spell.type ~= 'Trust') or spell.type == spell_type.type) and next(spell.levels) ~= nill and not player_spells[spell_id] and (is_learnable(spell) or not learnable) then + missing_spells:append(format_spell(spell)) + end + end + + if learnable then + windower.add_to_chat( 7, 'Showing learnable ' .. spell_type.readable .. '.') + else + windower.add_to_chat( 7, 'Showing all missing ' .. spell_type.readable .. '.') + end + + if next(missing_spells) ~= nil then + missing_spells:sort() + for _,spell in ipairs(missing_spells) do + windower.add_to_chat( 7, spell) + end + else + if learnable then + windower.add_to_chat( 7, 'Congratulations! You know all currently learnable ' .. spell_type.readable .. '.') + else + windower.add_to_chat( 7, 'Congratulations! You know all ' .. spell_type.readable .. '.') + end + end +end + +--[[List unkown spells for a specific job (by id), up to an optional level. + If no level_cap is given then the maximum is used.]] +function spells_by_job(job, level_cap) + local missing_spells = T{} + local player_spells = windower.ffxi.get_spells() + + level_cap = level_cap or 1500 + + for spell_id,spell in pairs(res.spells) do + local spell_level = spell.levels[job] + if spell_level and spell_level <= tonumber(level_cap) and spell.type ~= 'Trust' and not player_spells[spell_id] then + missing_spells[spell_level] = missing_spells[spell_level] or T{} + missing_spells[spell_level]:append(spell.en) + end + end + + if next(missing_spells) ~= nil then + windower.add_to_chat( 7, 'Showing missing spells for ' .. res.jobs[job].en .. ' up to level ' .. level_cap .. '.' ) + + for level=1,tonumber(level_cap) do + if missing_spells[level] then + missing_spells[level]:sort() + windower.add_to_chat( 7, level .. ': ' .. missing_spells[level]:concat(', ') ) + end + end + else + if level_cap >= 1500 then + windower.add_to_chat( 7, 'Congratulations! You know all spells for ' .. res.jobs[job].en .. '.') + else + windower.add_to_chat( 7, 'Congratulations! You know all spells for ' .. res.jobs[job].en .. ' up to ' .. tostring(level_cap) .. '.') + end + end +end + +--[[Show missing spells for the current main and sub jobs.]] +function spells_by_current() + local missing_spells = T{} + local player = windower.ffxi.get_player() + local player_spells = windower.ffxi.get_spells() + + for spell_id,spell in pairs(res.spells) do + local main_level = spell.levels[player.main_job_id] + local sub_level = spell.levels[player.sub_job_id] + local spell_level = nil + + if main_level and main_level > player.main_job_level then + main_level = nil + end + if sub_level and sub_level> player.sub_job_level then + sub_level = nil + end + + if main_level and sub_level then + spell_level = math.min( main_level, sub_level ) + else + spell_level = spell_level or main_level or sub_level + end + + if spell_level and spell.type ~= 'Trust' and not player_spells[spell_id] then + missing_spells:append(format_spell(spell)) + end + end + + if next(missing_spells) ~= nil then + windower.add_to_chat( 7, 'Showing learnable spells for ' .. player.main_job:lower() .. tostring(player.main_job_level) ..'/' .. player.sub_job:lower() .. tostring(player.sub_job_level) ..'.') + + missing_spells:sort() + for _,spell in ipairs(missing_spells) do + windower.add_to_chat( 7, spell ) + end + else + windower.add_to_chat( 7, 'Congratulations! You know all spells for ' .. player.main_job:lower() .. tostring(player.main_job_level) ..'/' .. player.sub_job:lower() .. tostring(player.sub_job_level) ..'.') + end +end + +--[[ +Copyright © 2018, John S Hobart +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 SpellBook 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 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. +]] diff --git a/addons/SpellBook/readme.md b/addons/SpellBook/readme.md new file mode 100644 index 0000000000..00bec23f8d --- /dev/null +++ b/addons/SpellBook/readme.md @@ -0,0 +1,19 @@ +##SpellBook + +This addon helps you find missing spells. You can search by job and level, +or by category. + +##Usage + +``` +Find missing spells for current jobs and level: +//sb help -- show this help text +//sb [current] -- Shows learnable spells based on current main and sub job and level. +//sb [] -- Show missing spells for current main or sub job. Defaults to the job\'s current level. +//sb [] -- Show missings spells for specified job and level. Defaults to the job\'s level. +//sb [all]-- Show learnable spells by category. Limited to spells which are learnable, unless all is added after the category. +Categories: whitemagic|blackmagic|songs|ninjustu|summoning|bluemagic|geomancy|trusts|all (Trusts are not included in all) +``` + +##Credits +Inspired by the SpellCheck addon by Zubis From e1267fe022bc6d09d97615ff8606d3d444f7bf6a Mon Sep 17 00:00:00 2001 From: John Hobart Date: Fri, 23 Mar 2018 17:53:16 -0400 Subject: [PATCH 0060/1002] Readme typo --- addons/SpellBook/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/SpellBook/readme.md b/addons/SpellBook/readme.md index 00bec23f8d..c5aae14f39 100644 --- a/addons/SpellBook/readme.md +++ b/addons/SpellBook/readme.md @@ -1,4 +1,4 @@ -##SpellBook +#SpellBook This addon helps you find missing spells. You can search by job and level, or by category. From 654f77e209ae51fbb0a2eb3e8750545eb357303b Mon Sep 17 00:00:00 2001 From: John Hobart Date: Fri, 23 Mar 2018 17:54:36 -0400 Subject: [PATCH 0061/1002] readme typo --- addons/SpellBook/readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/SpellBook/readme.md b/addons/SpellBook/readme.md index c5aae14f39..661808fe46 100644 --- a/addons/SpellBook/readme.md +++ b/addons/SpellBook/readme.md @@ -16,4 +16,5 @@ Categories: whitemagic|blackmagic|songs|ninjustu|summoning|bluemagic|geomancy|tr ``` ##Credits + Inspired by the SpellCheck addon by Zubis From 0c2c5ca573d0d832a3b7bef0397e78447395b92d Mon Sep 17 00:00:00 2001 From: John Hobart Date: Fri, 23 Mar 2018 17:59:10 -0400 Subject: [PATCH 0062/1002] more readme typos I think I got them this time... --- addons/SpellBook/readme.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/SpellBook/readme.md b/addons/SpellBook/readme.md index 661808fe46..7aee2ac976 100644 --- a/addons/SpellBook/readme.md +++ b/addons/SpellBook/readme.md @@ -1,9 +1,9 @@ -#SpellBook +# SpellBook This addon helps you find missing spells. You can search by job and level, or by category. -##Usage +## Usage ``` Find missing spells for current jobs and level: @@ -15,6 +15,6 @@ Find missing spells for current jobs and level: Categories: whitemagic|blackmagic|songs|ninjustu|summoning|bluemagic|geomancy|trusts|all (Trusts are not included in all) ``` -##Credits +## Credits Inspired by the SpellCheck addon by Zubis From d2e8150db496d1dc27bf62ee8a0a14cb879a841c Mon Sep 17 00:00:00 2001 From: aukon Date: Fri, 23 Mar 2018 23:35:59 +0000 Subject: [PATCH 0063/1002] Debuffed Addon --- addons/Debuffed/Debuffed.lua | 250 +++++++++++++++++++++++++++++++++++ addons/Debuffed/debuffs.lua | 54 ++++++++ 2 files changed, 304 insertions(+) create mode 100644 addons/Debuffed/Debuffed.lua create mode 100644 addons/Debuffed/debuffs.lua diff --git a/addons/Debuffed/Debuffed.lua b/addons/Debuffed/Debuffed.lua new file mode 100644 index 0000000000..08f493fbcf --- /dev/null +++ b/addons/Debuffed/Debuffed.lua @@ -0,0 +1,250 @@ +--[[ +Copyright (c) 2018, Auk +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 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 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.name = 'Debuffed' +_addon.author = 'Auk' +_addon.version = '1.0.0.1' +_addon.commands = {'dbf','debuffed'} + +config = require('config') +debuffs = require('debuffs') +packets = require('packets') +res = require('resources') +texts = require('texts') +require('logger') + +defaults = {} +defaults.interval = .1 +defaults.mode = 'blacklist' +defaults.whitelist = S{} +defaults.blacklist = S{} + +settings = config.load(defaults) +box = texts.new('${current_string}', settings) +box:show() + +list_commands = T{ + w = 'whitelist', + wlist = 'whitelist', + white = 'whitelist', + whitelist = 'whitelist', + b = 'blacklist', + blist = 'blacklist', + black = 'blacklist', + blacklist = 'blacklist' +} + +sort_commands = T{ + a = 'add', + add = 'add', + ['+'] = 'add', + r = 'remove', + remove = 'remove', + ['-'] = 'remove' +} + +frame_time = 0 +debuffed_mobs = {} + +function update_box() + local current_string = '' + local target = windower.ffxi.get_mob_by_target('t') + local count = 0 + + if target and target.valid_target and (target.claim_id ~= 0 or target.spawn_type == 16) then + local data = debuffed_mobs[target.id] + + if data then + current_string = 'Debuffed ['..target.name..']\n' + for effect, spell in pairs(data) do + local name = debuffs[spell[1]].name + + if settings.mode == 'whitelist' and settings.whitelist:contains(name) or settings.mode == 'blacklist' and not settings.blacklist:contains(name) then + if debuffs[spell[1]].duration > 0 then + current_string = current_string..'\n'..name + current_string = current_string..': '..string.format('%.0f', math.max(0, spell[2] - os.clock())) + else + current_string = current_string..'\n'..name + end + count = count + 1 + end + end + end + end + box.current_string = count > 0 and current_string or '' +end + +function handle_overwrites(target, new, t) + if debuffed_mobs[target] then + for effect, spell in pairs(debuffed_mobs[target]) do + local old = debuffs[spell[1]].overwrites + + -- Check if there isn't a higher priority debuff active + if #old > 0 then + for _, v in ipairs(old) do + if new == v then + return false + end + end + end + + -- Check if a lower priority debuff is being overwritten + if #t > 0 then + for _, v in ipairs(t) do + if spell[1] == v then + debuffed_mobs[target][effect] = nil + end + end + end + end + end + return true +end + +function apply_debuff(target, effect, spell) + if not debuffed_mobs[target] then + debuffed_mobs[target] = {} + end + + -- Check overwrite conditions + local overwrites = debuffs[spell].overwrites + if not handle_overwrites(target, spell, overwrites) then + return + end + + -- Create timer + debuffed_mobs[target][effect] = {spell, os.clock() + debuffs[spell].duration} +end + +function inc_action(act) + if act.category == 4 then + + -- Damaging spells + if S{2,252}:contains(act.targets[1].actions[1].message) then + local target = act.targets[1].id + local spell = act.param + + if debuffs[spell] then + local effect = debuffs[spell].effect + apply_debuff(target, effect, spell) + end + + -- Non-damaging spells + elseif S{236,237,268,271}:contains(act.targets[1].actions[1].message) then + local effect = act.targets[1].actions[1].param + local target = act.targets[1].id + local spell = act.param + + if debuffs[spell] and debuffs[spell].effect == effect then + apply_debuff(target, effect, spell) + end + end + end +end + +function inc_action_message(arr) + + -- Unit died + if S{6,20,113,406,605,646}:contains(arr.message_id) then + debuffed_mobs[arr.target_id] = nil + + -- Debuff expired + elseif S{204,206}:contains(arr.message_id) then + if debuffed_mobs[arr.target_id] then + debuffed_mobs[arr.target_id][arr.param_1] = nil + end + end +end + +windower.register_event('logout','zone change', function() + debuffed_mobs = {} +end) + +windower.register_event('incoming chunk', function(id, data) + if id == 0x028 then + inc_action(windower.packets.parse_action(data)) + elseif id == 0x029 then + local arr = {} + arr.target_id = data:unpack('I',0x09) + arr.param_1 = data:unpack('I',0x0D) + arr.message_id = data:unpack('H',0x19)%32768 + + inc_action_message(arr) + end +end) + +windower.register_event('prerender', function() + local curr = os.clock() + if curr > frame_time + settings.interval then + frame_time = curr + update_box() + end +end) + +windower.register_event('addon command', function(command1, command2, ...) + local args = L{...} + command1 = command1 and command1:lower() or nil + command2 = command2 and command2:lower() or nil + + local name = args:concat(' ') + if command1 == 'm' or command1 == 'mode' then + if settings.mode == 'blacklist' then + settings.mode = 'whitelist' + else + settings.mode = 'blacklist' + end + log('Changed to %s mode.':format(settings.mode)) + settings:save() + elseif command1 == 'i' or command1 == 'interval' then + settings.interval = tonumber(command2) or .1 + log('Refresh interval set to %s seconds.':format(settings.interval)) + settings:save() + elseif list_commands:containskey(command1) then + if sort_commands:containskey(command2) then + local spell = res.spells:with('name', windower.wc_match-{name}) + command1 = list_commands[command1] + command2 = sort_commands[command2] + + if spell == nil then + error('No spells found that match: %s':format(name)) + elseif command2 == 'add' then + settings[command1]:add(spell.name) + log('Added spell to %s: %s':format(command1, spell.name)) + else + settings[command1]:remove(spell.name) + log('Removed spell from %s: %s':format(command1, spell.name)) + end + settings:save() + end + else + print('%s (v%s)':format(_addon.name, _addon.version)) + print(' \\cs(255,255,255)mode\\cr - Switches between blacklist and whitelist mode (default: blacklist)') + print(' \\cs(255,255,255)interval \\cr - Allows you to change the refresh interval (default: 0.1)') + print(' \\cs(255,255,255)blacklist|whitelist add|remove \\cr - Adds or removes the spell to the specified list') + end +end) \ No newline at end of file diff --git a/addons/Debuffed/debuffs.lua b/addons/Debuffed/debuffs.lua new file mode 100644 index 0000000000..dc6b59cd65 --- /dev/null +++ b/addons/Debuffed/debuffs.lua @@ -0,0 +1,54 @@ + return { + [23] = {name="Dia", effect=134, duration=60, overwrites={}}, + [24] = {name="Dia II", effect=134, duration=120, overwrites={23,230}}, + [25] = {name="Dia III", effect=134, duration=90, overwrites={23,24,230,231}}, + [56] = {name="Slow", effect=13, duration=120, overwrites={}}, + [58] = {name="Paralyze", effect=4, duration=120, overwrites={}}, + [59] = {name="Silence", effect=6, duration=120, overwrites={}}, + [79] = {name="Slow II", effect=13, duration=120, overwrites={56}}, + [80] = {name="Paralyze II", effect=4, duration=120, overwrites={58}}, + [98] = {name="Repose", effect=2, duration=90, overwrites={253}}, + [216] = {name="Gravity", effect=12, duration=120, overwrites={}}, + [217] = {name="Gravity II", effect=12, duration=120, overwrites={216}}, + [220] = {name="Poison", effect=3, duration=90, overwrites={}}, + [221] = {name="Poison II", effect=3, duration=120, overwrites={220}}, + [230] = {name="Bio", effect=135, duration=60, overwrites={23}}, + [231] = {name="Bio II", effect=135, duration=120, overwrites={23,24,230}}, + [232] = {name="Bio III", effect=135, duration=30, overwrites={23,24,25,230,231}}, + [253] = {name="Sleep", effect=2, duration=60, overwrites={}}, + [254] = {name="Blind", effect=5, duration=180, overwrites={}}, + [255] = {name="Break", effect=7, duration=30, overwrites={}}, + [258] = {name="Bind", effect=11, duration=60, overwrites={}}, + [259] = {name="Sleep II", effect=2, duration=120, overwrites={253,273}}, + [273] = {name="Sleepga", effect=2, duration=90, overwrites={}}, + [274] = {name="Sleepga II", effect=2, duration=120, overwrites={253,273}}, + [276] = {name="Blind II", effect=5, duration=180, overwrites={254}}, + [278] = {name="Geohelix", effect=186, duration=230, overwrites={}}, + [279] = {name="Hydrohelix", effect=186, duration=230, overwrites={}}, + [280] = {name="Anemohelix", effect=186, duration=230, overwrites={}}, + [281] = {name="Pyrohelix", effect=186, duration=230, overwrites={}}, + [282] = {name="Cryohelix", effect=186, duration=230, overwrites={}}, + [283] = {name="Ionohelix", effect=186, duration=230, overwrites={}}, + [284] = {name="Noctohelix", effect=186, duration=230, overwrites={}}, + [285] = {name="Luminohelix", effect=186, duration=230, overwrites={}}, + [286] = {name="Addle", effect=21, duration=120, overwrites={}}, + [678] = {name="Dream Flower", effect=2, duration=90, overwrites={}}, + [717] = {name="Sweeping Gouge", effect=149, duration=120, overwrites={}}, + [727] = {name="Silent Storm", effect=6, duration=300, overwrites={}}, + [728] = {name="Tenebral Crush", effect=149, duration=90, overwrites={}}, + [841] = {name="Distract", effect=148, duration=120, overwrites={}}, + [842] = {name="Distract II", effect=148, duration=120, overwrites={841}}, + [843] = {name="Frazzle", effect=404, duration=120, overwrites={}}, + [844] = {name="Frazzle II", effect=404, duration=120, overwrites={843}}, + [882] = {name="Distract III", effect=148, duration=120, overwrites={841,842}}, + [883] = {name="Frazzle III", effect=404, duration=120, overwrites={843,844}}, + [884] = {name="Addle II", effect=21, duration=120, overwrites={286}}, + [885] = {name="Geohelix II", effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, + [886] = {name="Hydrohelix II", effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, + [887] = {name="Anemohelix II", effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, + [888] = {name="Pyrohelix II", effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, + [889] = {name="Cryohelix II", effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, + [890] = {name="Ionohelix II", effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, + [891] = {name="Noctohelix II", effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, + [892] = {name="Luminohelix II", effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}} + } \ No newline at end of file From 550e3d2e0b89d97842540f79b5877eaddd3d56b4 Mon Sep 17 00:00:00 2001 From: aukon Date: Sat, 24 Mar 2018 00:15:08 +0000 Subject: [PATCH 0064/1002] Create README.md --- addons/Debuffed/README.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 addons/Debuffed/README.md diff --git a/addons/Debuffed/README.md b/addons/Debuffed/README.md new file mode 100644 index 0000000000..3d831e9472 --- /dev/null +++ b/addons/Debuffed/README.md @@ -0,0 +1,28 @@ +# Debuffed + +An addon that tracks and displays debuffs on your current target. Filters are available to customise which debuffs are shown. + +### Commands + +`//debuffed mode` + +This will switch between blacklist and whitelist mode for debuff filtering. + +`//debuffed interval ` + +This allows you to adjust the refresh interval for the textbox. It will be updated every \ number of seconds. + +`//debuffed blacklist|whitelist add|remove ` + +This adds or removes the spell \ to the specified filter. + +### Abbreviations + +The following abbreviations are available for addon commands: +* `debuffed` to `dbf` +* `mode` to `m` +* `interval` to `i` +* `blacklist` to `b` or `blist` or `black` +* `whitelist` to `w` or `wlist` or `white` +* `add` to `a` or `+` +* `remove` to `r` or `-` From 2c7bcc1c53d3e444181344a48a54ca173f05d9ae Mon Sep 17 00:00:00 2001 From: aukon Date: Sat, 24 Mar 2018 00:21:36 +0000 Subject: [PATCH 0065/1002] Update addons.xml --- addons/addons.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/addons/addons.xml b/addons/addons.xml index 5bc38003ff..20dfd52b2e 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -697,4 +697,11 @@ https://github.com/Snapsmojo/Lua/issues http://www.ffxiah.com/player/Fenrir/Snaps + + Debuffed + Auk + Tracks and displays debuffs on your current target. + https://github.com/aukon/Lua/issues + https://discord.gg/b275nMv + From a45d56a1ad931734aca75b4e7691496b9ffe0676 Mon Sep 17 00:00:00 2001 From: aukon Date: Sat, 24 Mar 2018 12:09:42 +0000 Subject: [PATCH 0066/1002] Code cleanup --- addons/Debuffed/Debuffed.lua | 104 +++++++++++++++++----------------- addons/Debuffed/debuffs.lua | 106 +++++++++++++++++------------------ 2 files changed, 107 insertions(+), 103 deletions(-) diff --git a/addons/Debuffed/Debuffed.lua b/addons/Debuffed/Debuffed.lua index 08f493fbcf..216764528f 100644 --- a/addons/Debuffed/Debuffed.lua +++ b/addons/Debuffed/Debuffed.lua @@ -1,5 +1,5 @@ --[[ -Copyright (c) 2018, Auk +Copyright © 2018, Auk All rights reserved. Redistribution and use in source and binary forms, with or without @@ -10,14 +10,14 @@ modification, are permitted provided that the following conditions are met: * 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 nor the + * Neither the name of Debuffed 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 BE LIABLE FOR ANY +DISCLAIMED. IN NO EVENT SHALL Auk 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 @@ -72,53 +72,56 @@ frame_time = 0 debuffed_mobs = {} function update_box() - local current_string = '' + local lines = L{} local target = windower.ffxi.get_mob_by_target('t') - local count = 0 if target and target.valid_target and (target.claim_id ~= 0 or target.spawn_type == 16) then local data = debuffed_mobs[target.id] if data then - current_string = 'Debuffed ['..target.name..']\n' for effect, spell in pairs(data) do - local name = debuffs[spell[1]].name + local name = res.spells[spell[1]].name if settings.mode == 'whitelist' and settings.whitelist:contains(name) or settings.mode == 'blacklist' and not settings.blacklist:contains(name) then if debuffs[spell[1]].duration > 0 then - current_string = current_string..'\n'..name - current_string = current_string..': '..string.format('%.0f', math.max(0, spell[2] - os.clock())) + lines:append("%s: %.0f":format(name, math.max(0, spell[2] - os.clock()))) else - current_string = current_string..'\n'..name + lines:append(name) end - count = count + 1 end end end + + if lines:length() == 0 then + box.current_string = '' + else + box.current_string = 'Debuffed [' .. target.name .. ']\n\n' .. lines:concat('\n') + end end - box.current_string = count > 0 and current_string or '' end function handle_overwrites(target, new, t) - if debuffed_mobs[target] then - for effect, spell in pairs(debuffed_mobs[target]) do - local old = debuffs[spell[1]].overwrites - - -- Check if there isn't a higher priority debuff active - if #old > 0 then - for _, v in ipairs(old) do - if new == v then - return false - end + if not debuffed_mobs[target] then + return true + end + + for effect, spell in pairs(debuffed_mobs[target]) do + local old = debuffs[spell[1]].overwrites + + -- Check if there isn't a higher priority debuff active + if #old > 0 then + for _, v in ipairs(old) do + if new == v then + return false end end - - -- Check if a lower priority debuff is being overwritten - if #t > 0 then - for _, v in ipairs(t) do - if spell[1] == v then - debuffed_mobs[target][effect] = nil - end + end + + -- Check if a lower priority debuff is being overwritten + if #t > 0 then + for _, v in ipairs(t) do + if spell[1] == v then + debuffed_mobs[target][effect] = nil end end end @@ -142,27 +145,28 @@ function apply_debuff(target, effect, spell) end function inc_action(act) - if act.category == 4 then + if act.category ~= 4 then + return + end - -- Damaging spells - if S{2,252}:contains(act.targets[1].actions[1].message) then - local target = act.targets[1].id - local spell = act.param - - if debuffs[spell] then - local effect = debuffs[spell].effect - apply_debuff(target, effect, spell) - end - - -- Non-damaging spells - elseif S{236,237,268,271}:contains(act.targets[1].actions[1].message) then - local effect = act.targets[1].actions[1].param - local target = act.targets[1].id - local spell = act.param - - if debuffs[spell] and debuffs[spell].effect == effect then - apply_debuff(target, effect, spell) - end + -- Damaging spells + if S{2,252}:contains(act.targets[1].actions[1].message) then + local target = act.targets[1].id + local spell = act.param + + if debuffs[spell] then + local effect = debuffs[spell].effect + apply_debuff(target, effect, spell) + end + + -- Non-damaging spells + elseif S{236,237,268,271}:contains(act.targets[1].actions[1].message) then + local effect = act.targets[1].actions[1].param + local target = act.targets[1].id + local spell = act.param + + if debuffs[spell] and debuffs[spell].effect == effect then + apply_debuff(target, effect, spell) end end end @@ -247,4 +251,4 @@ windower.register_event('addon command', function(command1, command2, ...) print(' \\cs(255,255,255)interval \\cr - Allows you to change the refresh interval (default: 0.1)') print(' \\cs(255,255,255)blacklist|whitelist add|remove \\cr - Adds or removes the spell to the specified list') end -end) \ No newline at end of file +end) diff --git a/addons/Debuffed/debuffs.lua b/addons/Debuffed/debuffs.lua index dc6b59cd65..60f892dfd7 100644 --- a/addons/Debuffed/debuffs.lua +++ b/addons/Debuffed/debuffs.lua @@ -1,54 +1,54 @@ return { - [23] = {name="Dia", effect=134, duration=60, overwrites={}}, - [24] = {name="Dia II", effect=134, duration=120, overwrites={23,230}}, - [25] = {name="Dia III", effect=134, duration=90, overwrites={23,24,230,231}}, - [56] = {name="Slow", effect=13, duration=120, overwrites={}}, - [58] = {name="Paralyze", effect=4, duration=120, overwrites={}}, - [59] = {name="Silence", effect=6, duration=120, overwrites={}}, - [79] = {name="Slow II", effect=13, duration=120, overwrites={56}}, - [80] = {name="Paralyze II", effect=4, duration=120, overwrites={58}}, - [98] = {name="Repose", effect=2, duration=90, overwrites={253}}, - [216] = {name="Gravity", effect=12, duration=120, overwrites={}}, - [217] = {name="Gravity II", effect=12, duration=120, overwrites={216}}, - [220] = {name="Poison", effect=3, duration=90, overwrites={}}, - [221] = {name="Poison II", effect=3, duration=120, overwrites={220}}, - [230] = {name="Bio", effect=135, duration=60, overwrites={23}}, - [231] = {name="Bio II", effect=135, duration=120, overwrites={23,24,230}}, - [232] = {name="Bio III", effect=135, duration=30, overwrites={23,24,25,230,231}}, - [253] = {name="Sleep", effect=2, duration=60, overwrites={}}, - [254] = {name="Blind", effect=5, duration=180, overwrites={}}, - [255] = {name="Break", effect=7, duration=30, overwrites={}}, - [258] = {name="Bind", effect=11, duration=60, overwrites={}}, - [259] = {name="Sleep II", effect=2, duration=120, overwrites={253,273}}, - [273] = {name="Sleepga", effect=2, duration=90, overwrites={}}, - [274] = {name="Sleepga II", effect=2, duration=120, overwrites={253,273}}, - [276] = {name="Blind II", effect=5, duration=180, overwrites={254}}, - [278] = {name="Geohelix", effect=186, duration=230, overwrites={}}, - [279] = {name="Hydrohelix", effect=186, duration=230, overwrites={}}, - [280] = {name="Anemohelix", effect=186, duration=230, overwrites={}}, - [281] = {name="Pyrohelix", effect=186, duration=230, overwrites={}}, - [282] = {name="Cryohelix", effect=186, duration=230, overwrites={}}, - [283] = {name="Ionohelix", effect=186, duration=230, overwrites={}}, - [284] = {name="Noctohelix", effect=186, duration=230, overwrites={}}, - [285] = {name="Luminohelix", effect=186, duration=230, overwrites={}}, - [286] = {name="Addle", effect=21, duration=120, overwrites={}}, - [678] = {name="Dream Flower", effect=2, duration=90, overwrites={}}, - [717] = {name="Sweeping Gouge", effect=149, duration=120, overwrites={}}, - [727] = {name="Silent Storm", effect=6, duration=300, overwrites={}}, - [728] = {name="Tenebral Crush", effect=149, duration=90, overwrites={}}, - [841] = {name="Distract", effect=148, duration=120, overwrites={}}, - [842] = {name="Distract II", effect=148, duration=120, overwrites={841}}, - [843] = {name="Frazzle", effect=404, duration=120, overwrites={}}, - [844] = {name="Frazzle II", effect=404, duration=120, overwrites={843}}, - [882] = {name="Distract III", effect=148, duration=120, overwrites={841,842}}, - [883] = {name="Frazzle III", effect=404, duration=120, overwrites={843,844}}, - [884] = {name="Addle II", effect=21, duration=120, overwrites={286}}, - [885] = {name="Geohelix II", effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, - [886] = {name="Hydrohelix II", effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, - [887] = {name="Anemohelix II", effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, - [888] = {name="Pyrohelix II", effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, - [889] = {name="Cryohelix II", effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, - [890] = {name="Ionohelix II", effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, - [891] = {name="Noctohelix II", effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, - [892] = {name="Luminohelix II", effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}} - } \ No newline at end of file + [23] = {effect=134, duration=60, overwrites={}}, -- Dia + [24] = {effect=134, duration=120, overwrites={23,230}}, -- Dia II + [25] = {effect=134, duration=90, overwrites={23,24,230,231}}, -- Dia III + [56] = {effect=13, duration=120, overwrites={}}, -- Slow + [58] = {effect=4, duration=120, overwrites={}}, -- Paralyze + [59] = {effect=6, duration=120, overwrites={}}, -- Silence + [79] = {effect=13, duration=120, overwrites={56}}, -- Slow II + [80] = {effect=4, duration=120, overwrites={58}}, -- Paralyze II + [98] = {effect=2, duration=90, overwrites={253}}, -- Repose + [216] = {effect=12, duration=120, overwrites={}}, -- Gravity + [217] = {effect=12, duration=120, overwrites={216}}, -- Gravity II + [220] = {effect=3, duration=90, overwrites={}}, -- Poison + [221] = {effect=3, duration=120, overwrites={220}}, -- Poison II + [230] = {effect=135, duration=60, overwrites={23}}, -- Bio + [231] = {effect=135, duration=120, overwrites={23,24,230}}, -- Bio II + [232] = {effect=135, duration=30, overwrites={23,24,25,230,231}}, -- Bio III + [253] = {effect=2, duration=60, overwrites={}}, -- Sleep + [254] = {effect=5, duration=180, overwrites={}}, -- Blind + [255] = {effect=7, duration=30, overwrites={}}, -- Break + [258] = {effect=11, duration=60, overwrites={}}, -- Bind + [259] = {effect=2, duration=120, overwrites={253,273}}, -- Sleep II + [273] = {effect=2, duration=90, overwrites={}}, -- Sleepga + [274] = {effect=2, duration=120, overwrites={253,273}}, -- Sleepga II + [276] = {effect=5, duration=180, overwrites={254}}, -- Blind II + [278] = {effect=186, duration=230, overwrites={}}, -- Geohelix + [279] = {effect=186, duration=230, overwrites={}}, -- Hydrohelix + [280] = {effect=186, duration=230, overwrites={}}, -- Anemohelix + [281] = {effect=186, duration=230, overwrites={}}, -- Pyrohelix + [282] = {effect=186, duration=230, overwrites={}}, -- Cryohelix + [283] = {effect=186, duration=230, overwrites={}}, -- Ionohelix + [284] = {effect=186, duration=230, overwrites={}}, -- Noctohelix + [285] = {effect=186, duration=230, overwrites={}}, -- Luminohelix + [286] = {effect=21, duration=120, overwrites={}}, -- Addle + [678] = {effect=2, duration=90, overwrites={}}, -- Dream Flower + [717] = {effect=149, duration=120, overwrites={}}, -- Sweeping Gouge + [727] = {effect=6, duration=300, overwrites={}}, -- Silent Storm + [728] = {effect=149, duration=90, overwrites={717}}, -- Tenebral Crush + [841] = {effect=148, duration=120, overwrites={}}, -- Distract + [842] = {effect=148, duration=120, overwrites={841}}, -- Distract II + [843] = {effect=404, duration=120, overwrites={}}, -- Frazzle + [844] = {effect=404, duration=120, overwrites={843}}, -- Frazzle II + [882] = {effect=148, duration=120, overwrites={841,842}}, -- Distract III + [883] = {effect=404, duration=120, overwrites={843,844}}, -- Frazzle III + [884] = {effect=21, duration=120, overwrites={286}}, -- Addle II + [885] = {effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, -- Geohelix II + [886] = {effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, -- Hydrohelix II + [887] = {effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, -- Anemohelix II + [888] = {effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, -- Pyrohelix II + [889] = {effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, -- Cryohelix II + [890] = {effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, -- Ionohelix II + [891] = {effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, -- Noctohelix II + [892] = {effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}} -- Luminohelix II + } From 600598f03809cfd54a088697e910bd6aa5e30cc0 Mon Sep 17 00:00:00 2001 From: aukon Date: Sat, 24 Mar 2018 12:23:51 +0000 Subject: [PATCH 0067/1002] Add timers command --- addons/Debuffed/Debuffed.lua | 10 ++++++++-- addons/Debuffed/README.md | 5 +++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/addons/Debuffed/Debuffed.lua b/addons/Debuffed/Debuffed.lua index 216764528f..a65af3a871 100644 --- a/addons/Debuffed/Debuffed.lua +++ b/addons/Debuffed/Debuffed.lua @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'Debuffed' _addon.author = 'Auk' -_addon.version = '1.0.0.1' +_addon.version = '1.0.0.2' _addon.commands = {'dbf','debuffed'} config = require('config') @@ -41,6 +41,7 @@ require('logger') defaults = {} defaults.interval = .1 defaults.mode = 'blacklist' +defaults.timers = true defaults.whitelist = S{} defaults.blacklist = S{} @@ -83,7 +84,7 @@ function update_box() local name = res.spells[spell[1]].name if settings.mode == 'whitelist' and settings.whitelist:contains(name) or settings.mode == 'blacklist' and not settings.blacklist:contains(name) then - if debuffs[spell[1]].duration > 0 then + if settings.timers and debuffs[spell[1]].duration > 0 then lines:append("%s: %.0f":format(name, math.max(0, spell[2] - os.clock()))) else lines:append(name) @@ -224,6 +225,10 @@ windower.register_event('addon command', function(command1, command2, ...) end log('Changed to %s mode.':format(settings.mode)) settings:save() + elseif command1 == 't' or command1 == 'timers' then + settings.timers = not settings.timers + log('Timer display %s.':format(settings.timers and 'enabled' or 'disabled')) + settings:save() elseif command1 == 'i' or command1 == 'interval' then settings.interval = tonumber(command2) or .1 log('Refresh interval set to %s seconds.':format(settings.interval)) @@ -248,6 +253,7 @@ windower.register_event('addon command', function(command1, command2, ...) else print('%s (v%s)':format(_addon.name, _addon.version)) print(' \\cs(255,255,255)mode\\cr - Switches between blacklist and whitelist mode (default: blacklist)') + print(' \\cs(255,255,255)timers\\cr - Toggles display of debuff timers (default: true)') print(' \\cs(255,255,255)interval \\cr - Allows you to change the refresh interval (default: 0.1)') print(' \\cs(255,255,255)blacklist|whitelist add|remove \\cr - Adds or removes the spell to the specified list') end diff --git a/addons/Debuffed/README.md b/addons/Debuffed/README.md index 3d831e9472..b9b6900870 100644 --- a/addons/Debuffed/README.md +++ b/addons/Debuffed/README.md @@ -8,6 +8,10 @@ An addon that tracks and displays debuffs on your current target. Filters are av This will switch between blacklist and whitelist mode for debuff filtering. +`//debuffed timers` + +This toggles the display of timers for debuffs. + `//debuffed interval ` This allows you to adjust the refresh interval for the textbox. It will be updated every \ number of seconds. @@ -21,6 +25,7 @@ This adds or removes the spell \ to the specified filter. The following abbreviations are available for addon commands: * `debuffed` to `dbf` * `mode` to `m` +* `timers` to `t` * `interval` to `i` * `blacklist` to `b` or `blist` or `black` * `whitelist` to `w` or `wlist` or `white` From b0c813dea003ba61f5a922aebc46c064e08cde51 Mon Sep 17 00:00:00 2001 From: aukon Date: Sat, 24 Mar 2018 15:48:47 +0000 Subject: [PATCH 0068/1002] Hide timers below 0 --- addons/Debuffed/Debuffed.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/addons/Debuffed/Debuffed.lua b/addons/Debuffed/Debuffed.lua index a65af3a871..438d579295 100644 --- a/addons/Debuffed/Debuffed.lua +++ b/addons/Debuffed/Debuffed.lua @@ -82,10 +82,12 @@ function update_box() if data then for effect, spell in pairs(data) do local name = res.spells[spell[1]].name + local remains = math.max(0, spell[2] - os.clock()) if settings.mode == 'whitelist' and settings.whitelist:contains(name) or settings.mode == 'blacklist' and not settings.blacklist:contains(name) then - if settings.timers and debuffs[spell[1]].duration > 0 then - lines:append("%s: %.0f":format(name, math.max(0, spell[2] - os.clock()))) + + if settings.timers and remains > 0 then + lines:append("%s: %.0f":format(name, remains)) else lines:append(name) end From 8cf459636197bfadae659050e266b43da7ec94b3 Mon Sep 17 00:00:00 2001 From: aukon Date: Sat, 24 Mar 2018 15:50:32 +0000 Subject: [PATCH 0069/1002] Revert "Hide timers below 0" This reverts commit b0c813dea003ba61f5a922aebc46c064e08cde51. --- addons/Debuffed/Debuffed.lua | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/addons/Debuffed/Debuffed.lua b/addons/Debuffed/Debuffed.lua index 438d579295..a65af3a871 100644 --- a/addons/Debuffed/Debuffed.lua +++ b/addons/Debuffed/Debuffed.lua @@ -82,12 +82,10 @@ function update_box() if data then for effect, spell in pairs(data) do local name = res.spells[spell[1]].name - local remains = math.max(0, spell[2] - os.clock()) if settings.mode == 'whitelist' and settings.whitelist:contains(name) or settings.mode == 'blacklist' and not settings.blacklist:contains(name) then - - if settings.timers and remains > 0 then - lines:append("%s: %.0f":format(name, remains)) + if settings.timers and debuffs[spell[1]].duration > 0 then + lines:append("%s: %.0f":format(name, math.max(0, spell[2] - os.clock()))) else lines:append(name) end From 1aef04a6eb72172a965025590844d0c99e69be08 Mon Sep 17 00:00:00 2001 From: aukon Date: Sat, 24 Mar 2018 15:51:30 +0000 Subject: [PATCH 0070/1002] Hide timers below 0 --- addons/Debuffed/Debuffed.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/addons/Debuffed/Debuffed.lua b/addons/Debuffed/Debuffed.lua index a65af3a871..481886a77b 100644 --- a/addons/Debuffed/Debuffed.lua +++ b/addons/Debuffed/Debuffed.lua @@ -82,10 +82,11 @@ function update_box() if data then for effect, spell in pairs(data) do local name = res.spells[spell[1]].name + local remains = math.max(0, spell[2] - os.clock()) if settings.mode == 'whitelist' and settings.whitelist:contains(name) or settings.mode == 'blacklist' and not settings.blacklist:contains(name) then - if settings.timers and debuffs[spell[1]].duration > 0 then - lines:append("%s: %.0f":format(name, math.max(0, spell[2] - os.clock()))) + if settings.timers and remains > 0 then + lines:append("%s: %.0f":format(name, remains)) else lines:append(name) end From c32d5be50f194feffbaafc0d8b40c825dc65762a Mon Sep 17 00:00:00 2001 From: John Hobart Date: Sat, 24 Mar 2018 14:52:43 -0400 Subject: [PATCH 0071/1002] Add some further funcitonality Count of missing spells and list of spells that should be excluded, since they aren't available to players --- addons/SpellBook/Exceptions.lua | 25 +++++++++++++++++++++++++ addons/SpellBook/SpellBook.lua | 18 ++++++++++++++---- 2 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 addons/SpellBook/Exceptions.lua diff --git a/addons/SpellBook/Exceptions.lua b/addons/SpellBook/Exceptions.lua new file mode 100644 index 0000000000..91bafb4bcf --- /dev/null +++ b/addons/SpellBook/Exceptions.lua @@ -0,0 +1,25 @@ +spell_exceptions = { + [31] = true, -- Banish IV + [40] = true, -- Banishga III + [34] = true, -- Diaga II + [35] = true, -- Diaga III + [358] = true, -- Hastega + [356] = true, -- Paralyga + [359] = true, -- Silencega + [357] = true, -- Slowga + [361] = true, -- Blindga + [362] = true, -- Bindga + [257] = true, -- Curse + [360] = true, -- Dispelga + [226] = true, -- Poisonga II + [256] = true, -- Virus + [244] = true, -- Meteor II + [351] = true, -- Dokumori: Ni + [342] = true, -- Jubaku: Ni + [349] = true, -- Kurayami: San + [355] = true, -- Tonko: San + [416] = true, -- Cactuar Fugue + [407] = true, -- Chocobo Hum + [363] = true, -- Sleepga + [364] = true, -- Sleepga II +} diff --git a/addons/SpellBook/SpellBook.lua b/addons/SpellBook/SpellBook.lua index dc655379aa..d76c20d6d8 100644 --- a/addons/SpellBook/SpellBook.lua +++ b/addons/SpellBook/SpellBook.lua @@ -6,6 +6,7 @@ _addon.command = 'sb' require('sets') require('tables') res = require('resources') +require('Exceptions') -- Import invalid spell set spell_types = { whitemagic= { type = 'WhiteMagic', readable = 'White Magic spells' }, @@ -54,7 +55,7 @@ windower.register_event( 'addon command', function ( command, ... ) else spells_by_type( spell_types[command:lower()], true ) end - elseif jobs[command:lower()] then + elseif jobs[command:upper()] then local job = jobs[command:upper()] local level = args[1] or player.jobs[res.jobs[job].ens] if level == 'all' then @@ -126,10 +127,12 @@ end function spells_by_type(spell_type, learnable) local missing_spells = T{} local player_spells = windower.ffxi.get_spells() + local spell_count = 0 for spell_id,spell in pairs(res.spells) do - if ((spell_type.type == 'all' and spell.type ~= 'Trust') or spell.type == spell_type.type) and next(spell.levels) ~= nill and not player_spells[spell_id] and (is_learnable(spell) or not learnable) then + if ((spell_type.type == 'all' and spell.type ~= 'Trust') or spell.type == spell_type.type) and next(spell.levels) ~= nill and not player_spells[spell_id] and (is_learnable(spell) or not learnable) and not spell_exceptions[spell_id] then missing_spells:append(format_spell(spell)) + spell_count = spell_count + 1 end end @@ -144,6 +147,7 @@ function spells_by_type(spell_type, learnable) for _,spell in ipairs(missing_spells) do windower.add_to_chat( 7, spell) end + windower.add_to_chat( 7, 'List Complete. You are missing ' .. tostring(spell_count) .. ' ' .. spell_type.readable .. '.') else if learnable then windower.add_to_chat( 7, 'Congratulations! You know all currently learnable ' .. spell_type.readable .. '.') @@ -158,14 +162,16 @@ end function spells_by_job(job, level_cap) local missing_spells = T{} local player_spells = windower.ffxi.get_spells() + local spell_count = 0 level_cap = level_cap or 1500 for spell_id,spell in pairs(res.spells) do local spell_level = spell.levels[job] - if spell_level and spell_level <= tonumber(level_cap) and spell.type ~= 'Trust' and not player_spells[spell_id] then + if spell_level and spell_level <= tonumber(level_cap) and spell.type ~= 'Trust' and not player_spells[spell_id] and not spell_exceptions[spell_id] then missing_spells[spell_level] = missing_spells[spell_level] or T{} missing_spells[spell_level]:append(spell.en) + spell_count = spell_count + 1 end end @@ -178,6 +184,7 @@ function spells_by_job(job, level_cap) windower.add_to_chat( 7, level .. ': ' .. missing_spells[level]:concat(', ') ) end end + windower.add_to_chat( 7, 'List Complete. You are missing ' .. tostring(spell_count) .. ' ' .. res.jobs[job].en .. ' spells.') else if level_cap >= 1500 then windower.add_to_chat( 7, 'Congratulations! You know all spells for ' .. res.jobs[job].en .. '.') @@ -192,6 +199,7 @@ function spells_by_current() local missing_spells = T{} local player = windower.ffxi.get_player() local player_spells = windower.ffxi.get_spells() + local spell_count = 0 for spell_id,spell in pairs(res.spells) do local main_level = spell.levels[player.main_job_id] @@ -211,8 +219,9 @@ function spells_by_current() spell_level = spell_level or main_level or sub_level end - if spell_level and spell.type ~= 'Trust' and not player_spells[spell_id] then + if spell_level and spell.type ~= 'Trust' and not player_spells[spell_id] and not spell_exceptions[spell_id] then missing_spells:append(format_spell(spell)) + spell_count = spell_count + 1 end end @@ -223,6 +232,7 @@ function spells_by_current() for _,spell in ipairs(missing_spells) do windower.add_to_chat( 7, spell ) end + windower.add_to_chat( 7, 'List Complete. You are missing ' .. tostring(spell_count) .. ' spells for ' .. player.main_job:lower() .. tostring(player.main_job_level) ..'/' .. player.sub_job:lower() .. tostring(player.sub_job_level) ..'.') else windower.add_to_chat( 7, 'Congratulations! You know all spells for ' .. player.main_job:lower() .. tostring(player.main_job_level) ..'/' .. player.sub_job:lower() .. tostring(player.sub_job_level) ..'.') end From daa680c43ceb6aa5605c0f891f24586cbd4637e0 Mon Sep 17 00:00:00 2001 From: John Hobart Date: Sat, 24 Mar 2018 15:07:33 -0400 Subject: [PATCH 0072/1002] Change command from sb to spellbook conflicted with the existing plugin scoreboard --- addons/SpellBook/SpellBook.lua | 2 +- addons/SpellBook/readme.md | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/addons/SpellBook/SpellBook.lua b/addons/SpellBook/SpellBook.lua index d76c20d6d8..086aff1890 100644 --- a/addons/SpellBook/SpellBook.lua +++ b/addons/SpellBook/SpellBook.lua @@ -1,7 +1,7 @@ _addon.name = 'SpellBook' _addon.author = 'SigilBaram' _addon.version = '0.0.1' -_addon.command = 'sb' +_addon.command = 'spellbook' require('sets') require('tables') diff --git a/addons/SpellBook/readme.md b/addons/SpellBook/readme.md index 7aee2ac976..0bf81a9ec4 100644 --- a/addons/SpellBook/readme.md +++ b/addons/SpellBook/readme.md @@ -7,11 +7,11 @@ or by category. ``` Find missing spells for current jobs and level: -//sb help -- show this help text -//sb [current] -- Shows learnable spells based on current main and sub job and level. -//sb [] -- Show missing spells for current main or sub job. Defaults to the job\'s current level. -//sb [] -- Show missings spells for specified job and level. Defaults to the job\'s level. -//sb [all]-- Show learnable spells by category. Limited to spells which are learnable, unless all is added after the category. +//spellbook help -- show this help text +//spellbook [current] -- Shows learnable spells based on current main and sub job and level. +//spellbook [] -- Show missing spells for current main or sub job. Defaults to the job's current level. +//spellbook [] -- Show missings spells for specified job and level. Defaults to the job's level. +//spellbook [all]-- Show learnable spells by category. Limited to spells which are learnable, unless all is added after the category. Categories: whitemagic|blackmagic|songs|ninjustu|summoning|bluemagic|geomancy|trusts|all (Trusts are not included in all) ``` From 447c21fe801587cb0df99603840615b9258c43d6 Mon Sep 17 00:00:00 2001 From: John Hobart Date: Sat, 24 Mar 2018 15:16:08 -0400 Subject: [PATCH 0073/1002] add short command --- addons/SpellBook/SpellBook.lua | 14 +++++++------- addons/SpellBook/readme.md | 11 +++++------ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/addons/SpellBook/SpellBook.lua b/addons/SpellBook/SpellBook.lua index 086aff1890..40c1d0ee72 100644 --- a/addons/SpellBook/SpellBook.lua +++ b/addons/SpellBook/SpellBook.lua @@ -1,7 +1,7 @@ _addon.name = 'SpellBook' _addon.author = 'SigilBaram' _addon.version = '0.0.1' -_addon.command = 'spellbook' +_addon.commands = {'spellbook','spbk'} require('sets') require('tables') @@ -78,17 +78,17 @@ end --[[Display an error message for invalid input.]] function invalid_input() - windower.add_to_chat( 7, 'Invalid input. See //' .. _addon.command .. ' help.') + windower.add_to_chat( 7, 'Invalid input. See //spbk help.') end --[[Display help text for the addon.]] function display_help() windower.add_to_chat( 7, _addon.name .. ' version ' .. _addon.version ) - windower.add_to_chat( 7, '//' .. _addon.command .. ' help -- show this help text' ) - windower.add_to_chat( 7, '//' .. _addon.command .. ' [current] -- Shows learnable spells based on current main and sub job and level.') - windower.add_to_chat( 7, '//' .. _addon.command .. ' [] -- Show missing spells for current main or sub job. Defaults to the job\'s current level.' ) - windower.add_to_chat( 7, '//' .. _addon.command .. ' [] -- Show missings spells for specified job and level. Defaults to the job\'s level.' ) - windower.add_to_chat( 7, '//' .. _addon.command .. ' [all]-- Show learnable spells by category. Limited to spells which are learnable, unless all is added after the category.' ) + windower.add_to_chat( 7, '//spbk help -- show this help text' ) + windower.add_to_chat( 7, '//spbk [current] -- Shows learnable spells based on current main and sub job and level.') + windower.add_to_chat( 7, '//spbk [] -- Show missing spells for current main or sub job. Defaults to the job\'s current level.' ) + windower.add_to_chat( 7, '//spbk [] -- Show missings spells for specified job and level. Defaults to the job\'s level.' ) + windower.add_to_chat( 7, '//spbk [all]-- Show learnable spells by category. Limited to spells which are learnable, unless all is added after the category.' ) windower.add_to_chat( 7, 'Categories: whitemagic|blackmagic|songs|ninjustu|summoning|bluemagic|geomancy|trusts|all (Trusts are not included in all)' ) end diff --git a/addons/SpellBook/readme.md b/addons/SpellBook/readme.md index 0bf81a9ec4..63a27e97d3 100644 --- a/addons/SpellBook/readme.md +++ b/addons/SpellBook/readme.md @@ -6,12 +6,11 @@ or by category. ## Usage ``` -Find missing spells for current jobs and level: -//spellbook help -- show this help text -//spellbook [current] -- Shows learnable spells based on current main and sub job and level. -//spellbook [] -- Show missing spells for current main or sub job. Defaults to the job's current level. -//spellbook [] -- Show missings spells for specified job and level. Defaults to the job's level. -//spellbook [all]-- Show learnable spells by category. Limited to spells which are learnable, unless all is added after the category. +//spbk help -- show this help text +//spbk [current] -- Shows learnable spells based on current main and sub job and level. +//spbk [] -- Show missing spells for current main or sub job. Defaults to the job's current level. +//spbk [] -- Show missings spells for specified job and level. Defaults to the job's level. +//spbk [all]-- Show learnable spells by category. Limited to spells which are learnable, unless all is added after the category. Categories: whitemagic|blackmagic|songs|ninjustu|summoning|bluemagic|geomancy|trusts|all (Trusts are not included in all) ``` From f2535eaaffd30b24a4cc991976cc82b279e1ff52 Mon Sep 17 00:00:00 2001 From: John Hobart Date: Sat, 24 Mar 2018 16:39:07 -0400 Subject: [PATCH 0074/1002] Fixed a typo --- addons/SpellBook/SpellBook.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/SpellBook/SpellBook.lua b/addons/SpellBook/SpellBook.lua index 40c1d0ee72..700e7c3e4b 100644 --- a/addons/SpellBook/SpellBook.lua +++ b/addons/SpellBook/SpellBook.lua @@ -14,7 +14,7 @@ spell_types = { songs= { type = 'BardSong', readable = 'Bard songs' }, ninjutsu= { type = 'Ninjutsu', readable = 'Ninjutsu' }, summoning= { type = 'SummonerPact', readable = 'Summoning spells' }, - bluemagic= { type = 'BlueMagic', readable = 'Blue Magic spels' }, + bluemagic= { type = 'BlueMagic', readable = 'Blue Magic spells' }, geomancy= { type = 'Geomancy', readable = 'Geomancy spells' }, trusts= { type = 'Trust', readable = 'Trusts'}, all= { type = 'all', readable = 'spells of all types'} From 600f653ee0f01803545e0e5e0f04f33afcbbfce3 Mon Sep 17 00:00:00 2001 From: John Hobart Date: Tue, 27 Mar 2018 15:49:15 -0400 Subject: [PATCH 0075/1002] Code cleanup and fixed JP Broke up some long lines and added code for handling job points. --- addons/SpellBook/SpellBook.lua | 86 ++++++++++++++++++++++++++-------- 1 file changed, 66 insertions(+), 20 deletions(-) diff --git a/addons/SpellBook/SpellBook.lua b/addons/SpellBook/SpellBook.lua index 700e7c3e4b..c4719f08f9 100644 --- a/addons/SpellBook/SpellBook.lua +++ b/addons/SpellBook/SpellBook.lua @@ -112,7 +112,11 @@ function format_spell(spell) if spell.type ~= 'Trust' then local levels = T{} for job_id,level in pairs(spell.levels) do - levels:append( res.jobs[job_id].ens .. ' ' .. tostring(level) ) + if level <= 99 then + levels:append( res.jobs[job_id].ens .. ' ' .. tostring(level) ) + else + levels:append( res.jobs[job_id].ens .. ' ' .. tostring(level) .. 'jp' ) + end end format = format .. ' ( ' .. levels:concat(', ') .. ' )' else @@ -130,16 +134,21 @@ function spells_by_type(spell_type, learnable) local spell_count = 0 for spell_id,spell in pairs(res.spells) do - if ((spell_type.type == 'all' and spell.type ~= 'Trust') or spell.type == spell_type.type) and next(spell.levels) ~= nill and not player_spells[spell_id] and (is_learnable(spell) or not learnable) and not spell_exceptions[spell_id] then + if ((spell_type.type == 'all' and spell.type ~= 'Trust') or + spell.type == spell_type.type) and next(spell.levels) ~= nill and + not player_spells[spell_id] and (is_learnable(spell) or + not learnable) and not spell_exceptions[spell_id] then missing_spells:append(format_spell(spell)) spell_count = spell_count + 1 end end if learnable then - windower.add_to_chat( 7, 'Showing learnable ' .. spell_type.readable .. '.') + windower.add_to_chat( 7, 'Showing learnable ' .. + spell_type.readable .. '.') else - windower.add_to_chat( 7, 'Showing all missing ' .. spell_type.readable .. '.') + windower.add_to_chat( 7, 'Showing all missing ' .. + spell_type.readable .. '.') end if next(missing_spells) ~= nil then @@ -147,12 +156,17 @@ function spells_by_type(spell_type, learnable) for _,spell in ipairs(missing_spells) do windower.add_to_chat( 7, spell) end - windower.add_to_chat( 7, 'List Complete. You are missing ' .. tostring(spell_count) .. ' ' .. spell_type.readable .. '.') + windower.add_to_chat( 7, + 'List Complete. You are missing ' .. + tostring(spell_count) .. ' ' .. spell_type.readable .. '.') else if learnable then - windower.add_to_chat( 7, 'Congratulations! You know all currently learnable ' .. spell_type.readable .. '.') + windower.add_to_chat( 7, + 'Congratulations! You know all currently learnable ' .. + spell_type.readable .. '.') else - windower.add_to_chat( 7, 'Congratulations! You know all ' .. spell_type.readable .. '.') + windower.add_to_chat( 7, 'Congratulations! You know all ' .. + spell_type.readable .. '.') end end end @@ -164,11 +178,13 @@ function spells_by_job(job, level_cap) local player_spells = windower.ffxi.get_spells() local spell_count = 0 - level_cap = level_cap or 1500 + level_cap = tonumber(level_cap) or 1500 for spell_id,spell in pairs(res.spells) do local spell_level = spell.levels[job] - if spell_level and spell_level <= tonumber(level_cap) and spell.type ~= 'Trust' and not player_spells[spell_id] and not spell_exceptions[spell_id] then + if spell_level and spell_level <= level_cap and + spell.type ~= 'Trust' and not player_spells[spell_id] and + not spell_exceptions[spell_id] then missing_spells[spell_level] = missing_spells[spell_level] or T{} missing_spells[spell_level]:append(spell.en) spell_count = spell_count + 1 @@ -176,20 +192,33 @@ function spells_by_job(job, level_cap) end if next(missing_spells) ~= nil then - windower.add_to_chat( 7, 'Showing missing spells for ' .. res.jobs[job].en .. ' up to level ' .. level_cap .. '.' ) + windower.add_to_chat( 7, + string.format('Showing missing spells for %s up to level %s.', + res.jobs[job].en, level_cap )) - for level=1,tonumber(level_cap) do + for level=1,level_cap do if missing_spells[level] then missing_spells[level]:sort() - windower.add_to_chat( 7, level .. ': ' .. missing_spells[level]:concat(', ') ) + if level <= 99 then + windower.add_to_chat( 7, + level .. ': ' .. missing_spells[level]:concat(', ') ) + else + windower.add_to_chat( 7, + level .. 'jp: ' .. missing_spells[level]:concat(', ') ) + end end end - windower.add_to_chat( 7, 'List Complete. You are missing ' .. tostring(spell_count) .. ' ' .. res.jobs[job].en .. ' spells.') + windower.add_to_chat( 7, 'List Complete. You are missing ' .. + tostring(spell_count) .. ' ' .. res.jobs[job].en .. ' spells.') else if level_cap >= 1500 then - windower.add_to_chat( 7, 'Congratulations! You know all spells for ' .. res.jobs[job].en .. '.') + windower.add_to_chat( 7, + 'Congratulations! You know all spells for ' .. + res.jobs[job].en .. '.') else - windower.add_to_chat( 7, 'Congratulations! You know all spells for ' .. res.jobs[job].en .. ' up to ' .. tostring(level_cap) .. '.') + windower.add_to_chat( 7, + 'Congratulations! You know all spells for ' .. + res.jobs[job].en .. ' up to ' .. tostring(level_cap) .. '.') end end end @@ -201,12 +230,22 @@ function spells_by_current() local player_spells = windower.ffxi.get_spells() local spell_count = 0 + + local main_job_level = player.main_job_level + local main_job_jp = player.job_points[player.main_job:lower()].jp_spent + + -- The player has over 100 spend jp an + if main_job_jp > 99 then + main_job_level = main_job_jp + end + for spell_id,spell in pairs(res.spells) do local main_level = spell.levels[player.main_job_id] local sub_level = spell.levels[player.sub_job_id] local spell_level = nil - if main_level and main_level > player.main_job_level then + + if main_level and main_level > main_job_level then main_level = nil end if sub_level and sub_level> player.sub_job_level then @@ -219,22 +258,29 @@ function spells_by_current() spell_level = spell_level or main_level or sub_level end - if spell_level and spell.type ~= 'Trust' and not player_spells[spell_id] and not spell_exceptions[spell_id] then + if spell_level and spell.type ~= 'Trust' and + not player_spells[spell_id] and not spell_exceptions[spell_id] then missing_spells:append(format_spell(spell)) spell_count = spell_count + 1 end end if next(missing_spells) ~= nil then - windower.add_to_chat( 7, 'Showing learnable spells for ' .. player.main_job:lower() .. tostring(player.main_job_level) ..'/' .. player.sub_job:lower() .. tostring(player.sub_job_level) ..'.') + windower.add_to_chat( 7, string.format('Showing learnable spells for %s%d/%s%d.', + player.main_job:lower(), player.main_job_level, + player.sub_job:lower(), player.sub_job_level )) missing_spells:sort() for _,spell in ipairs(missing_spells) do windower.add_to_chat( 7, spell ) end - windower.add_to_chat( 7, 'List Complete. You are missing ' .. tostring(spell_count) .. ' spells for ' .. player.main_job:lower() .. tostring(player.main_job_level) ..'/' .. player.sub_job:lower() .. tostring(player.sub_job_level) ..'.') + windower.add_to_chat( 7, string.format('List Complete. You are missing %d spells for %s%d/%s%d.', + spell_count, player.main_job:lower(), player.main_job_level, + player.sub_job:lower(), player.sub_job_level)) else - windower.add_to_chat( 7, 'Congratulations! You know all spells for ' .. player.main_job:lower() .. tostring(player.main_job_level) ..'/' .. player.sub_job:lower() .. tostring(player.sub_job_level) ..'.') + windower.add_to_chat( 7, string.format('Congratulations! You know all spells for %s%d/%s%d!', + player.main_job:lower(), player.main_job_level, + player.sub_job:lower(), player.sub_job_level )) end end From 6772455dc7936a887bdcec11712e7257aba26f37 Mon Sep 17 00:00:00 2001 From: John Hobart Date: Tue, 27 Mar 2018 16:25:15 -0400 Subject: [PATCH 0076/1002] Documented Exceptions.lua --- addons/SpellBook/Exceptions.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/addons/SpellBook/Exceptions.lua b/addons/SpellBook/Exceptions.lua index 91bafb4bcf..bd1796ebeb 100644 --- a/addons/SpellBook/Exceptions.lua +++ b/addons/SpellBook/Exceptions.lua @@ -1,3 +1,5 @@ +-- This set lists spell IDs that cannot be learned by player, so that they are +-- excluded by SpellBook. spell_exceptions = { [31] = true, -- Banish IV [40] = true, -- Banishga III @@ -20,6 +22,9 @@ spell_exceptions = { [355] = true, -- Tonko: San [416] = true, -- Cactuar Fugue [407] = true, -- Chocobo Hum + + -- The following spells have the same name as other spells, + -- but have different IDs. [363] = true, -- Sleepga [364] = true, -- Sleepga II } From d7f6b14ff4c19e1c4b478a67361e337ee717b0c2 Mon Sep 17 00:00:00 2001 From: aukon Date: Wed, 28 Mar 2018 15:44:38 +0100 Subject: [PATCH 0077/1002] Use resources for debuffs --- addons/Debuffed/Debuffed.lua | 39 ++++++++++++++++---------- addons/Debuffed/debuffs.lua | 54 ------------------------------------ 2 files changed, 24 insertions(+), 69 deletions(-) delete mode 100644 addons/Debuffed/debuffs.lua diff --git a/addons/Debuffed/Debuffed.lua b/addons/Debuffed/Debuffed.lua index 481886a77b..0c1cf65f88 100644 --- a/addons/Debuffed/Debuffed.lua +++ b/addons/Debuffed/Debuffed.lua @@ -32,7 +32,6 @@ _addon.version = '1.0.0.2' _addon.commands = {'dbf','debuffed'} config = require('config') -debuffs = require('debuffs') packets = require('packets') res = require('resources') texts = require('texts') @@ -102,17 +101,27 @@ function update_box() end end +function convert_overwrites(spell) + local str = res.spells[spell].overwrites + local t = {} + + if str then + str:gsub("[0-9]+",function(s) table.insert(t, tonumber(s)) end) + end + return L(t) +end + function handle_overwrites(target, new, t) if not debuffed_mobs[target] then return true end for effect, spell in pairs(debuffed_mobs[target]) do - local old = debuffs[spell[1]].overwrites + local old = convert_overwrites(spell[1]) -- Check if there isn't a higher priority debuff active - if #old > 0 then - for _, v in ipairs(old) do + if old:length() > 0 then + for _,v in ipairs(old) do if new == v then return false end @@ -120,8 +129,8 @@ function handle_overwrites(target, new, t) end -- Check if a lower priority debuff is being overwritten - if #t > 0 then - for _, v in ipairs(t) do + if t:length() > 0 then + for _,v in ipairs(t) do if spell[1] == v then debuffed_mobs[target][effect] = nil end @@ -135,39 +144,39 @@ function apply_debuff(target, effect, spell) if not debuffed_mobs[target] then debuffed_mobs[target] = {} end - + -- Check overwrite conditions - local overwrites = debuffs[spell].overwrites + local overwrites = convert_overwrites(spell) if not handle_overwrites(target, spell, overwrites) then return end -- Create timer - debuffed_mobs[target][effect] = {spell, os.clock() + debuffs[spell].duration} + debuffed_mobs[target][effect] = {spell, os.clock() + res.spells[spell].duration} end function inc_action(act) if act.category ~= 4 then return end - + -- Damaging spells if S{2,252}:contains(act.targets[1].actions[1].message) then local target = act.targets[1].id local spell = act.param - - if debuffs[spell] then - local effect = debuffs[spell].effect + local effect = res.spells[spell].status + + if effect then apply_debuff(target, effect, spell) end -- Non-damaging spells elseif S{236,237,268,271}:contains(act.targets[1].actions[1].message) then - local effect = act.targets[1].actions[1].param local target = act.targets[1].id + local effect = act.targets[1].actions[1].param local spell = act.param - if debuffs[spell] and debuffs[spell].effect == effect then + if res.spells[spell].status and res.spells[spell].status == effect then apply_debuff(target, effect, spell) end end diff --git a/addons/Debuffed/debuffs.lua b/addons/Debuffed/debuffs.lua deleted file mode 100644 index 60f892dfd7..0000000000 --- a/addons/Debuffed/debuffs.lua +++ /dev/null @@ -1,54 +0,0 @@ - return { - [23] = {effect=134, duration=60, overwrites={}}, -- Dia - [24] = {effect=134, duration=120, overwrites={23,230}}, -- Dia II - [25] = {effect=134, duration=90, overwrites={23,24,230,231}}, -- Dia III - [56] = {effect=13, duration=120, overwrites={}}, -- Slow - [58] = {effect=4, duration=120, overwrites={}}, -- Paralyze - [59] = {effect=6, duration=120, overwrites={}}, -- Silence - [79] = {effect=13, duration=120, overwrites={56}}, -- Slow II - [80] = {effect=4, duration=120, overwrites={58}}, -- Paralyze II - [98] = {effect=2, duration=90, overwrites={253}}, -- Repose - [216] = {effect=12, duration=120, overwrites={}}, -- Gravity - [217] = {effect=12, duration=120, overwrites={216}}, -- Gravity II - [220] = {effect=3, duration=90, overwrites={}}, -- Poison - [221] = {effect=3, duration=120, overwrites={220}}, -- Poison II - [230] = {effect=135, duration=60, overwrites={23}}, -- Bio - [231] = {effect=135, duration=120, overwrites={23,24,230}}, -- Bio II - [232] = {effect=135, duration=30, overwrites={23,24,25,230,231}}, -- Bio III - [253] = {effect=2, duration=60, overwrites={}}, -- Sleep - [254] = {effect=5, duration=180, overwrites={}}, -- Blind - [255] = {effect=7, duration=30, overwrites={}}, -- Break - [258] = {effect=11, duration=60, overwrites={}}, -- Bind - [259] = {effect=2, duration=120, overwrites={253,273}}, -- Sleep II - [273] = {effect=2, duration=90, overwrites={}}, -- Sleepga - [274] = {effect=2, duration=120, overwrites={253,273}}, -- Sleepga II - [276] = {effect=5, duration=180, overwrites={254}}, -- Blind II - [278] = {effect=186, duration=230, overwrites={}}, -- Geohelix - [279] = {effect=186, duration=230, overwrites={}}, -- Hydrohelix - [280] = {effect=186, duration=230, overwrites={}}, -- Anemohelix - [281] = {effect=186, duration=230, overwrites={}}, -- Pyrohelix - [282] = {effect=186, duration=230, overwrites={}}, -- Cryohelix - [283] = {effect=186, duration=230, overwrites={}}, -- Ionohelix - [284] = {effect=186, duration=230, overwrites={}}, -- Noctohelix - [285] = {effect=186, duration=230, overwrites={}}, -- Luminohelix - [286] = {effect=21, duration=120, overwrites={}}, -- Addle - [678] = {effect=2, duration=90, overwrites={}}, -- Dream Flower - [717] = {effect=149, duration=120, overwrites={}}, -- Sweeping Gouge - [727] = {effect=6, duration=300, overwrites={}}, -- Silent Storm - [728] = {effect=149, duration=90, overwrites={717}}, -- Tenebral Crush - [841] = {effect=148, duration=120, overwrites={}}, -- Distract - [842] = {effect=148, duration=120, overwrites={841}}, -- Distract II - [843] = {effect=404, duration=120, overwrites={}}, -- Frazzle - [844] = {effect=404, duration=120, overwrites={843}}, -- Frazzle II - [882] = {effect=148, duration=120, overwrites={841,842}}, -- Distract III - [883] = {effect=404, duration=120, overwrites={843,844}}, -- Frazzle III - [884] = {effect=21, duration=120, overwrites={286}}, -- Addle II - [885] = {effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, -- Geohelix II - [886] = {effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, -- Hydrohelix II - [887] = {effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, -- Anemohelix II - [888] = {effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, -- Pyrohelix II - [889] = {effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, -- Cryohelix II - [890] = {effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, -- Ionohelix II - [891] = {effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}}, -- Noctohelix II - [892] = {effect=186, duration=230, overwrites={278,279,280,281,282,283,284,285}} -- Luminohelix II - } From 0bbf36c896301b3c2cc50e672a6ab6e07517bd02 Mon Sep 17 00:00:00 2001 From: aukon Date: Wed, 4 Apr 2018 17:44:40 +0100 Subject: [PATCH 0078/1002] Fix debuffs not being cleared --- addons/Debuffed/Debuffed.lua | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/addons/Debuffed/Debuffed.lua b/addons/Debuffed/Debuffed.lua index 0c1cf65f88..dc341069bf 100644 --- a/addons/Debuffed/Debuffed.lua +++ b/addons/Debuffed/Debuffed.lua @@ -92,12 +92,12 @@ function update_box() end end end - - if lines:length() == 0 then - box.current_string = '' - else - box.current_string = 'Debuffed [' .. target.name .. ']\n\n' .. lines:concat('\n') - end + end + + if lines:length() == 0 then + box.current_string = '' + else + box.current_string = 'Debuffed [' .. target.name .. ']\n\n' .. lines:concat('\n') end end From 078b8bb765ba043656a2b3d740b14485987a01d7 Mon Sep 17 00:00:00 2001 From: John Hobart Date: Wed, 11 Apr 2018 11:37:19 -0400 Subject: [PATCH 0079/1002] Fixed up spacing and comments --- addons/SpellBook/Exceptions.lua | 5 -- addons/SpellBook/SpellBook.lua | 134 ++++++++++++++++++-------------- 2 files changed, 74 insertions(+), 65 deletions(-) diff --git a/addons/SpellBook/Exceptions.lua b/addons/SpellBook/Exceptions.lua index bd1796ebeb..91bafb4bcf 100644 --- a/addons/SpellBook/Exceptions.lua +++ b/addons/SpellBook/Exceptions.lua @@ -1,5 +1,3 @@ --- This set lists spell IDs that cannot be learned by player, so that they are --- excluded by SpellBook. spell_exceptions = { [31] = true, -- Banish IV [40] = true, -- Banishga III @@ -22,9 +20,6 @@ spell_exceptions = { [355] = true, -- Tonko: San [416] = true, -- Cactuar Fugue [407] = true, -- Chocobo Hum - - -- The following spells have the same name as other spells, - -- but have different IDs. [363] = true, -- Sleepga [364] = true, -- Sleepga II } diff --git a/addons/SpellBook/SpellBook.lua b/addons/SpellBook/SpellBook.lua index c4719f08f9..f392491c9c 100644 --- a/addons/SpellBook/SpellBook.lua +++ b/addons/SpellBook/SpellBook.lua @@ -6,7 +6,7 @@ _addon.commands = {'spellbook','spbk'} require('sets') require('tables') res = require('resources') -require('Exceptions') -- Import invalid spell set +require('Exceptions') -- Import unlearnable spell set, until it's in resources. spell_types = { whitemagic= { type = 'WhiteMagic', readable = 'White Magic spells' }, @@ -20,7 +20,7 @@ spell_types = { all= { type = 'all', readable = 'spells of all types'} } -windower.register_event( 'addon command', function ( command, ... ) +windower.register_event('addon command', function (command, ...) local args = L{...} local player = windower.ffxi.get_player() local jobs = build_job_list() @@ -38,22 +38,22 @@ windower.register_event( 'addon command', function ( command, ... ) level = 1500 end level = tonumber(level) - spells_by_job( player.main_job_id, tonumber(level) ) + spells_by_job(player.main_job_id, tonumber(level)) else invalid_input() end elseif command == 'sub' then local level = args[1] or player.sub_job_level if level == 'all' or tonumber(level) ~= nil then - spells_by_job( player.sub_job_id, tonumber(level) ) + spells_by_job(player.sub_job_id, tonumber(level)) else invalid_input() end elseif spell_types[command:lower()] then if args[1] == 'all' then - spells_by_type( spell_types[command:lower()], false ) + spells_by_type(spell_types[command:lower()], false) else - spells_by_type( spell_types[command:lower()], true ) + spells_by_type(spell_types[command:lower()], true) end elseif jobs[command:upper()] then local job = jobs[command:upper()] @@ -61,13 +61,16 @@ windower.register_event( 'addon command', function ( command, ... ) if level == 'all' then level = 1500 end - spells_by_job( job, tonumber(level) ) + spells_by_job(job, tonumber(level)) else invalid_input() end end) ---[[Builds a list of jobs with short name as the key and id as the value.]] +--[[ +Builds a list of jobs with short name as the key and id as the value, for +reading in user input. +--]] function build_job_list() local jobs = {} for id,val in pairs(res.jobs) do @@ -76,24 +79,26 @@ function build_job_list() return jobs end ---[[Display an error message for invalid input.]] +-- Display an error message for invalid input. function invalid_input() - windower.add_to_chat( 7, 'Invalid input. See //spbk help.') + windower.add_to_chat(7, 'Invalid input. See //spbk help.') end ---[[Display help text for the addon.]] +-- Display help text for the addon. function display_help() - windower.add_to_chat( 7, _addon.name .. ' version ' .. _addon.version ) - windower.add_to_chat( 7, '//spbk help -- show this help text' ) - windower.add_to_chat( 7, '//spbk [current] -- Shows learnable spells based on current main and sub job and level.') - windower.add_to_chat( 7, '//spbk [] -- Show missing spells for current main or sub job. Defaults to the job\'s current level.' ) - windower.add_to_chat( 7, '//spbk [] -- Show missings spells for specified job and level. Defaults to the job\'s level.' ) - windower.add_to_chat( 7, '//spbk [all]-- Show learnable spells by category. Limited to spells which are learnable, unless all is added after the category.' ) - windower.add_to_chat( 7, 'Categories: whitemagic|blackmagic|songs|ninjustu|summoning|bluemagic|geomancy|trusts|all (Trusts are not included in all)' ) + windower.add_to_chat(7, _addon.name .. ' version ' .. _addon.version) + windower.add_to_chat(7, '//spbk help -- show this help text') + windower.add_to_chat(7, '//spbk [current] -- Shows learnable spells based on current main and sub job and level.') + windower.add_to_chat(7, '//spbk [] -- Show missing spells for current main or sub job. Defaults to the job\'s current level.') + windower.add_to_chat(7, '//spbk [] -- Show missings spells for specified job and level. Defaults to the job\'s level.') + windower.add_to_chat(7, '//spbk [all] -- Show learnable spells by category. Limited to spells which are learnable, unless all is added after the category.') + windower.add_to_chat(7, 'Categories: whitemagic|blackmagic|songs|ninjustu|summoning|bluemagic|geomancy|trusts|all (Trusts are not included in all)') end ---[[Returns true if the player has a job which is high enough level to learn - the given spell.]] +--[[ +Returns true if the player has any jobs which is high enough level to learn +the given spell. +--]] function is_learnable(spell) local player_levels = windower.ffxi.get_player().jobs for job,level in pairs(spell.levels) do @@ -104,8 +109,10 @@ function is_learnable(spell) return false end ---[[Formats a spell as the spell's name followed by a list of jobs and levels - which would qualify to learn the spell.]] +--[[ +Formats a spell as the spell's name followed by a list of jobs and levels +which would qualify to learn that spell. +--]] function format_spell(spell) local format = string.format('%-20s',spell.en) @@ -113,9 +120,9 @@ function format_spell(spell) local levels = T{} for job_id,level in pairs(spell.levels) do if level <= 99 then - levels:append( res.jobs[job_id].ens .. ' ' .. tostring(level) ) + levels:append(res.jobs[job_id].ens .. ' ' .. tostring(level)) else - levels:append( res.jobs[job_id].ens .. ' ' .. tostring(level) .. 'jp' ) + levels:append(res.jobs[job_id].ens .. ' ' .. tostring(level) .. 'jp') end end format = format .. ' ( ' .. levels:concat(', ') .. ' )' @@ -125,9 +132,11 @@ function format_spell(spell) return format end ---[[Show missing spells of a given type. If learnable is true, then the - results will be limited to spells for which the player has a job at a - level required to learn the spell.]] +--[[ +Show missing spells of a given type. If learnable is true, then the +results will be limited to spells for which the player has a job at a +level required to learn the spell. +--]] function spells_by_type(spell_type, learnable) local missing_spells = T{} local player_spells = windower.ffxi.get_spells() @@ -135,44 +144,47 @@ function spells_by_type(spell_type, learnable) for spell_id,spell in pairs(res.spells) do if ((spell_type.type == 'all' and spell.type ~= 'Trust') or - spell.type == spell_type.type) and next(spell.levels) ~= nill and - not player_spells[spell_id] and (is_learnable(spell) or - not learnable) and not spell_exceptions[spell_id] then + spell.type == spell_type.type) and next(spell.levels) ~= nill and + not player_spells[spell_id] and (is_learnable(spell) or + not learnable) and not spell_exceptions[spell_id] then + missing_spells:append(format_spell(spell)) spell_count = spell_count + 1 end end if learnable then - windower.add_to_chat( 7, 'Showing learnable ' .. + windower.add_to_chat(7, 'Showing learnable ' .. spell_type.readable .. '.') else - windower.add_to_chat( 7, 'Showing all missing ' .. + windower.add_to_chat(7, 'Showing all missing ' .. spell_type.readable .. '.') end if next(missing_spells) ~= nil then missing_spells:sort() for _,spell in ipairs(missing_spells) do - windower.add_to_chat( 7, spell) + windower.add_to_chat(7, spell) end - windower.add_to_chat( 7, + windower.add_to_chat(7, 'List Complete. You are missing ' .. tostring(spell_count) .. ' ' .. spell_type.readable .. '.') else if learnable then - windower.add_to_chat( 7, + windower.add_to_chat(7, 'Congratulations! You know all currently learnable ' .. spell_type.readable .. '.') else - windower.add_to_chat( 7, 'Congratulations! You know all ' .. + windower.add_to_chat(7, 'Congratulations! You know all ' .. spell_type.readable .. '.') end end end ---[[List unkown spells for a specific job (by id), up to an optional level. - If no level_cap is given then the maximum is used.]] +--[[ +List unkown spells for a specific job (by id), up to an optional level. +If no level_cap is given then the maximum is used. +--]] function spells_by_job(job, level_cap) local missing_spells = T{} local player_spells = windower.ffxi.get_spells() @@ -183,8 +195,9 @@ function spells_by_job(job, level_cap) for spell_id,spell in pairs(res.spells) do local spell_level = spell.levels[job] if spell_level and spell_level <= level_cap and - spell.type ~= 'Trust' and not player_spells[spell_id] and - not spell_exceptions[spell_id] then + spell.type ~= 'Trust' and not player_spells[spell_id] and + not spell_exceptions[spell_id] then + missing_spells[spell_level] = missing_spells[spell_level] or T{} missing_spells[spell_level]:append(spell.en) spell_count = spell_count + 1 @@ -192,38 +205,38 @@ function spells_by_job(job, level_cap) end if next(missing_spells) ~= nil then - windower.add_to_chat( 7, + windower.add_to_chat(7, string.format('Showing missing spells for %s up to level %s.', - res.jobs[job].en, level_cap )) + res.jobs[job].en, level_cap)) for level=1,level_cap do if missing_spells[level] then missing_spells[level]:sort() if level <= 99 then - windower.add_to_chat( 7, - level .. ': ' .. missing_spells[level]:concat(', ') ) + windower.add_to_chat(7, + level .. ': ' .. missing_spells[level]:concat(', ')) else - windower.add_to_chat( 7, - level .. 'jp: ' .. missing_spells[level]:concat(', ') ) + windower.add_to_chat(7, + level .. 'jp: ' .. missing_spells[level]:concat(', ')) end end end - windower.add_to_chat( 7, 'List Complete. You are missing ' .. + windower.add_to_chat(7, 'List Complete. You are missing ' .. tostring(spell_count) .. ' ' .. res.jobs[job].en .. ' spells.') else if level_cap >= 1500 then - windower.add_to_chat( 7, + windower.add_to_chat(7, 'Congratulations! You know all spells for ' .. res.jobs[job].en .. '.') else - windower.add_to_chat( 7, + windower.add_to_chat(7, 'Congratulations! You know all spells for ' .. res.jobs[job].en .. ' up to ' .. tostring(level_cap) .. '.') end end end ---[[Show missing spells for the current main and sub jobs.]] +-- Show missing spells for the current main and sub jobs. function spells_by_current() local missing_spells = T{} local player = windower.ffxi.get_player() @@ -234,7 +247,7 @@ function spells_by_current() local main_job_level = player.main_job_level local main_job_jp = player.job_points[player.main_job:lower()].jp_spent - -- The player has over 100 spend jp an + -- If the player has over 99 spend jp, then switch to treating JP as level. if main_job_jp > 99 then main_job_level = main_job_jp end @@ -253,34 +266,35 @@ function spells_by_current() end if main_level and sub_level then - spell_level = math.min( main_level, sub_level ) + spell_level = math.min(main_level, sub_level) else spell_level = spell_level or main_level or sub_level end if spell_level and spell.type ~= 'Trust' and - not player_spells[spell_id] and not spell_exceptions[spell_id] then + not player_spells[spell_id] and not spell_exceptions[spell_id] then + missing_spells:append(format_spell(spell)) spell_count = spell_count + 1 end end if next(missing_spells) ~= nil then - windower.add_to_chat( 7, string.format('Showing learnable spells for %s%d/%s%d.', + windower.add_to_chat(7, string.format('Showing learnable spells for %s%d/%s%d.', player.main_job:lower(), player.main_job_level, - player.sub_job:lower(), player.sub_job_level )) + player.sub_job:lower(), player.sub_job_level)) missing_spells:sort() for _,spell in ipairs(missing_spells) do - windower.add_to_chat( 7, spell ) + windower.add_to_chat(7, spell) end - windower.add_to_chat( 7, string.format('List Complete. You are missing %d spells for %s%d/%s%d.', + windower.add_to_chat(7, string.format('List Complete. You are missing %d spells for %s%d/%s%d.', spell_count, player.main_job:lower(), player.main_job_level, player.sub_job:lower(), player.sub_job_level)) else - windower.add_to_chat( 7, string.format('Congratulations! You know all spells for %s%d/%s%d!', + windower.add_to_chat(7, string.format('Congratulations! You know all spells for %s%d/%s%d!', player.main_job:lower(), player.main_job_level, - player.sub_job:lower(), player.sub_job_level )) + player.sub_job:lower(), player.sub_job_level)) end end @@ -310,4 +324,4 @@ 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. -]] +--]] From c28faae379b31c284a05595962a718c17b4c99a4 Mon Sep 17 00:00:00 2001 From: John Hobart Date: Wed, 11 Apr 2018 12:28:35 -0400 Subject: [PATCH 0080/1002] Use unlearnable from resources.spells --- addons/SpellBook/Exceptions.lua | 25 ------------------------- addons/SpellBook/SpellBook.lua | 26 ++++++++++++++++---------- 2 files changed, 16 insertions(+), 35 deletions(-) delete mode 100644 addons/SpellBook/Exceptions.lua diff --git a/addons/SpellBook/Exceptions.lua b/addons/SpellBook/Exceptions.lua deleted file mode 100644 index 91bafb4bcf..0000000000 --- a/addons/SpellBook/Exceptions.lua +++ /dev/null @@ -1,25 +0,0 @@ -spell_exceptions = { - [31] = true, -- Banish IV - [40] = true, -- Banishga III - [34] = true, -- Diaga II - [35] = true, -- Diaga III - [358] = true, -- Hastega - [356] = true, -- Paralyga - [359] = true, -- Silencega - [357] = true, -- Slowga - [361] = true, -- Blindga - [362] = true, -- Bindga - [257] = true, -- Curse - [360] = true, -- Dispelga - [226] = true, -- Poisonga II - [256] = true, -- Virus - [244] = true, -- Meteor II - [351] = true, -- Dokumori: Ni - [342] = true, -- Jubaku: Ni - [349] = true, -- Kurayami: San - [355] = true, -- Tonko: San - [416] = true, -- Cactuar Fugue - [407] = true, -- Chocobo Hum - [363] = true, -- Sleepga - [364] = true, -- Sleepga II -} diff --git a/addons/SpellBook/SpellBook.lua b/addons/SpellBook/SpellBook.lua index f392491c9c..65f27914ea 100644 --- a/addons/SpellBook/SpellBook.lua +++ b/addons/SpellBook/SpellBook.lua @@ -6,7 +6,6 @@ _addon.commands = {'spellbook','spbk'} require('sets') require('tables') res = require('resources') -require('Exceptions') -- Import unlearnable spell set, until it's in resources. spell_types = { whitemagic= { type = 'WhiteMagic', readable = 'White Magic spells' }, @@ -137,7 +136,7 @@ Show missing spells of a given type. If learnable is true, then the results will be limited to spells for which the player has a job at a level required to learn the spell. --]] -function spells_by_type(spell_type, learnable) +function spells_by_type(spell_type, learnable_only) local missing_spells = T{} local player_spells = windower.ffxi.get_spells() local spell_count = 0 @@ -146,14 +145,14 @@ function spells_by_type(spell_type, learnable) if ((spell_type.type == 'all' and spell.type ~= 'Trust') or spell.type == spell_type.type) and next(spell.levels) ~= nill and not player_spells[spell_id] and (is_learnable(spell) or - not learnable) and not spell_exceptions[spell_id] then + not learnable_only) and not spell.unlearnable then missing_spells:append(format_spell(spell)) spell_count = spell_count + 1 end end - if learnable then + if learnable_only then windower.add_to_chat(7, 'Showing learnable ' .. spell_type.readable .. '.') else @@ -166,11 +165,18 @@ function spells_by_type(spell_type, learnable) for _,spell in ipairs(missing_spells) do windower.add_to_chat(7, spell) end - windower.add_to_chat(7, - 'List Complete. You are missing ' .. - tostring(spell_count) .. ' ' .. spell_type.readable .. '.') + if learnable_only then + windower.add_to_chat(7, + 'List Complete. You are missing ' .. + tostring(spell_count) .. ' learnable ' .. + spell_type.readable .. '.') + else + windower.add_to_chat(7, + 'List Complete. You are missing ' .. + tostring(spell_count) .. ' ' .. spell_type.readable .. '.') + end else - if learnable then + if learnable_only then windower.add_to_chat(7, 'Congratulations! You know all currently learnable ' .. spell_type.readable .. '.') @@ -196,7 +202,7 @@ function spells_by_job(job, level_cap) local spell_level = spell.levels[job] if spell_level and spell_level <= level_cap and spell.type ~= 'Trust' and not player_spells[spell_id] and - not spell_exceptions[spell_id] then + not spell.unlearnable then missing_spells[spell_level] = missing_spells[spell_level] or T{} missing_spells[spell_level]:append(spell.en) @@ -272,7 +278,7 @@ function spells_by_current() end if spell_level and spell.type ~= 'Trust' and - not player_spells[spell_id] and not spell_exceptions[spell_id] then + not player_spells[spell_id] and not spell.unlearnable then missing_spells:append(format_spell(spell)) spell_count = spell_count + 1 From 7c292b70a0528c17f25c3bab75225764a6c0f6cb Mon Sep 17 00:00:00 2001 From: John Hobart Date: Wed, 11 Apr 2018 12:50:15 -0400 Subject: [PATCH 0081/1002] Further distinguish between level and jp --- addons/SpellBook/SpellBook.lua | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/addons/SpellBook/SpellBook.lua b/addons/SpellBook/SpellBook.lua index 65f27914ea..a67c3f577f 100644 --- a/addons/SpellBook/SpellBook.lua +++ b/addons/SpellBook/SpellBook.lua @@ -211,19 +211,25 @@ function spells_by_job(job, level_cap) end if next(missing_spells) ~= nil then - windower.add_to_chat(7, - string.format('Showing missing spells for %s up to level %s.', - res.jobs[job].en, level_cap)) + if level_cap > 99 then + windower.add_to_chat(7, + string.format('Showing missing spells for %s up to level %s.', + res.jobs[job].en, level_cap)) + else + windower.add_to_chat(7, + string.format('Showing missing spells for %s up to %sjp.', + res.jobs[job].en, level_cap)) + end for level=1,level_cap do if missing_spells[level] then missing_spells[level]:sort() - if level <= 99 then + if level > 99 then windower.add_to_chat(7, - level .. ': ' .. missing_spells[level]:concat(', ')) + level .. 'jp: ' .. missing_spells[level]:concat(', ')) else windower.add_to_chat(7, - level .. 'jp: ' .. missing_spells[level]:concat(', ')) + level .. ': ' .. missing_spells[level]:concat(', ')) end end end @@ -235,9 +241,17 @@ function spells_by_job(job, level_cap) 'Congratulations! You know all spells for ' .. res.jobs[job].en .. '.') else - windower.add_to_chat(7, - 'Congratulations! You know all spells for ' .. - res.jobs[job].en .. ' up to ' .. tostring(level_cap) .. '.') + if level_cap > 99 then + windower.add_to_chat(7, + 'Congratulations! You know all spells for ' .. + res.jobs[job].en .. ' up to ' .. + tostring(level_cap) .. 'jp.') + else + windower.add_to_chat(7, + 'Congratulations! You know all spells for ' .. + res.jobs[job].en .. ' up to level ' .. + tostring(level_cap) .. '.') + end end end end From e17dd07977a05dc5b53dd5071c06c6d50e6cac02 Mon Sep 17 00:00:00 2001 From: John Hobart Date: Wed, 11 Apr 2018 13:05:43 -0400 Subject: [PATCH 0082/1002] Remove unused sets library --- addons/SpellBook/SpellBook.lua | 3 +-- addons/SpellBook/readme.md | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/addons/SpellBook/SpellBook.lua b/addons/SpellBook/SpellBook.lua index a67c3f577f..0a573cab3c 100644 --- a/addons/SpellBook/SpellBook.lua +++ b/addons/SpellBook/SpellBook.lua @@ -3,7 +3,6 @@ _addon.author = 'SigilBaram' _addon.version = '0.0.1' _addon.commands = {'spellbook','spbk'} -require('sets') require('tables') res = require('resources') @@ -91,7 +90,7 @@ function display_help() windower.add_to_chat(7, '//spbk [] -- Show missing spells for current main or sub job. Defaults to the job\'s current level.') windower.add_to_chat(7, '//spbk [] -- Show missings spells for specified job and level. Defaults to the job\'s level.') windower.add_to_chat(7, '//spbk [all] -- Show learnable spells by category. Limited to spells which are learnable, unless all is added after the category.') - windower.add_to_chat(7, 'Categories: whitemagic|blackmagic|songs|ninjustu|summoning|bluemagic|geomancy|trusts|all (Trusts are not included in all)') + windower.add_to_chat(7, 'Categories: whitemagic, blackmagic, songs, ninjustu, summoning, bluemagic, geomancy, trusts, all (Trusts are not included in all)') end --[[ diff --git a/addons/SpellBook/readme.md b/addons/SpellBook/readme.md index 63a27e97d3..5c1d074cc5 100644 --- a/addons/SpellBook/readme.md +++ b/addons/SpellBook/readme.md @@ -11,7 +11,7 @@ or by category. //spbk [] -- Show missing spells for current main or sub job. Defaults to the job's current level. //spbk [] -- Show missings spells for specified job and level. Defaults to the job's level. //spbk [all]-- Show learnable spells by category. Limited to spells which are learnable, unless all is added after the category. -Categories: whitemagic|blackmagic|songs|ninjustu|summoning|bluemagic|geomancy|trusts|all (Trusts are not included in all) +Categories: whitemagic, blackmagic, songs, ninjustu, summoning, bluemagic, geomancy, trusts, all (Trusts are not included in all) ``` ## Credits From 372294fa18ce1ade03996e9a78bebba1a86ae2bc Mon Sep 17 00:00:00 2001 From: John Hobart Date: Wed, 11 Apr 2018 13:14:45 -0400 Subject: [PATCH 0083/1002] Cut down on upper and lower in command processing --- addons/SpellBook/SpellBook.lua | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/addons/SpellBook/SpellBook.lua b/addons/SpellBook/SpellBook.lua index 0a573cab3c..47e6a02eda 100644 --- a/addons/SpellBook/SpellBook.lua +++ b/addons/SpellBook/SpellBook.lua @@ -47,14 +47,14 @@ windower.register_event('addon command', function (command, ...) else invalid_input() end - elseif spell_types[command:lower()] then + elseif spell_types[command] then if args[1] == 'all' then - spells_by_type(spell_types[command:lower()], false) + spells_by_type(spell_types[command], false) else - spells_by_type(spell_types[command:lower()], true) + spells_by_type(spell_types[command], true) end - elseif jobs[command:upper()] then - local job = jobs[command:upper()] + elseif jobs[command] then + local job = jobs[command] local level = args[1] or player.jobs[res.jobs[job].ens] if level == 'all' then level = 1500 @@ -72,7 +72,7 @@ reading in user input. function build_job_list() local jobs = {} for id,val in pairs(res.jobs) do - jobs[val.ens] = id + jobs[val.ens:lower()] = id end return jobs end From 1a304a9214f09b6af07bcaa3a646411bd46914d2 Mon Sep 17 00:00:00 2001 From: John Hobart Date: Wed, 11 Apr 2018 15:45:48 -0400 Subject: [PATCH 0084/1002] Improve input handling and output formatting --- addons/SpellBook/SpellBook.lua | 163 ++++++++++++++++++++------------- addons/SpellBook/readme.md | 1 + 2 files changed, 98 insertions(+), 66 deletions(-) diff --git a/addons/SpellBook/SpellBook.lua b/addons/SpellBook/SpellBook.lua index 47e6a02eda..43d5916291 100644 --- a/addons/SpellBook/SpellBook.lua +++ b/addons/SpellBook/SpellBook.lua @@ -31,27 +31,33 @@ windower.register_event('addon command', function (command, ...) spells_by_current() elseif command == 'main' then local level = args[1] or player.main_job_level - if level == 'all' or tonumber(level) ~= nil then - if level == 'all' then - level = 1500 - end - level = tonumber(level) - spells_by_job(player.main_job_id, tonumber(level)) + if level == 'all' then + level = 1500 + end + level = tonumber(level) + if level then + spells_by_job(player.main_job_id, level) else invalid_input() end elseif command == 'sub' then local level = args[1] or player.sub_job_level - if level == 'all' or tonumber(level) ~= nil then - spells_by_job(player.sub_job_id, tonumber(level)) + if level == 'all' then + level = 1500 + end + level = tonumber(level) + if level then + spells_by_job(player.sub_job_id, level) else invalid_input() end elseif spell_types[command] then if args[1] == 'all' then spells_by_type(spell_types[command], false) - else + elseif args[1] == nil then spells_by_type(spell_types[command], true) + else + invalid_input() end elseif jobs[command] then local job = jobs[command] @@ -59,7 +65,12 @@ windower.register_event('addon command', function (command, ...) if level == 'all' then level = 1500 end - spells_by_job(job, tonumber(level)) + level = tonumber(level) + if level then + spells_by_job(job, level) + else + invalid_input() + end else invalid_input() end @@ -91,6 +102,7 @@ function display_help() windower.add_to_chat(7, '//spbk [] -- Show missings spells for specified job and level. Defaults to the job\'s level.') windower.add_to_chat(7, '//spbk [all] -- Show learnable spells by category. Limited to spells which are learnable, unless all is added after the category.') windower.add_to_chat(7, 'Categories: whitemagic, blackmagic, songs, ninjustu, summoning, bluemagic, geomancy, trusts, all (Trusts are not included in all)') + windower.add_to_chat(7, 'Note: A limit on spent job points can be specified for spells learned from Gifts by entering a level of 100-1500. Spells are never given as Gifts for less than 100 jp.') end --[[ @@ -112,22 +124,29 @@ Formats a spell as the spell's name followed by a list of jobs and levels which would qualify to learn that spell. --]] function format_spell(spell) - local format = string.format('%-20s',spell.en) + local format if spell.type ~= 'Trust' then + local jobs = T{} local levels = T{} - for job_id,level in pairs(spell.levels) do - if level <= 99 then - levels:append(res.jobs[job_id].ens .. ' ' .. tostring(level)) + for job_id,_ in pairs(spell.levels) do + jobs:append(job_id) + end + jobs:sort() + for _,job_id in ipairs(jobs) do + if spell.levels[job_id] <= 99 then + levels:append(res.jobs[job_id].ens .. ' Lv.' .. + tostring(spell.levels[job_id])) else - levels:append(res.jobs[job_id].ens .. ' ' .. tostring(level) .. 'jp') + levels:append(res.jobs[job_id].ens .. ' Jp.' .. + tostring(spell.levels[job_id])) end end - format = format .. ' ( ' .. levels:concat(', ') .. ' )' + format = levels:concat(' / ') else - format = format .. ' ( Trust )' + format = ' ( Trust )' end - return format + return string.format('%-20s %s', spell.en, format) end --[[ @@ -152,11 +171,11 @@ function spells_by_type(spell_type, learnable_only) end if learnable_only then - windower.add_to_chat(7, 'Showing learnable ' .. - spell_type.readable .. '.') + windower.add_to_chat(7, string.format('Showing learnable %s.', + spell_type.readable)) else - windower.add_to_chat(7, 'Showing all missing ' .. - spell_type.readable .. '.') + windower.add_to_chat(7, string.format('Showing all missing %s.', + spell_type.readable)) end if next(missing_spells) ~= nil then @@ -165,23 +184,23 @@ function spells_by_type(spell_type, learnable_only) windower.add_to_chat(7, spell) end if learnable_only then - windower.add_to_chat(7, - 'List Complete. You are missing ' .. - tostring(spell_count) .. ' learnable ' .. - spell_type.readable .. '.') + windower.add_to_chat(7,string.format( + 'List Complete. You are missing %d learnable %s.', + spell_count, spell_type.readable)) else - windower.add_to_chat(7, - 'List Complete. You are missing ' .. - tostring(spell_count) .. ' ' .. spell_type.readable .. '.') + windower.add_to_chat(7,string.format( + 'List Complete. You are missing %d %s.', + spell_count, spell_type.readable)) end else if learnable_only then - windower.add_to_chat(7, - 'Congratulations! You know all currently learnable ' .. - spell_type.readable .. '.') + windower.add_to_chat(7,string.format( + 'Congratulations! You know all currently learnable %s.', + spell_type.readable)) else - windower.add_to_chat(7, 'Congratulations! You know all ' .. - spell_type.readable .. '.') + windower.add_to_chat(7,string.format( + 'Congratulations! You know all %s.', + spell_type.readable)) end end end @@ -195,8 +214,6 @@ function spells_by_job(job, level_cap) local player_spells = windower.ffxi.get_spells() local spell_count = 0 - level_cap = tonumber(level_cap) or 1500 - for spell_id,spell in pairs(res.spells) do local spell_level = spell.levels[job] if spell_level and spell_level <= level_cap and @@ -211,12 +228,12 @@ function spells_by_job(job, level_cap) if next(missing_spells) ~= nil then if level_cap > 99 then - windower.add_to_chat(7, - string.format('Showing missing spells for %s up to level %s.', + windower.add_to_chat(7, string.format( + 'Showing missing spells for %s up to %d spent job points.', res.jobs[job].en, level_cap)) else - windower.add_to_chat(7, - string.format('Showing missing spells for %s up to %sjp.', + windower.add_to_chat(7, string.format( + 'Showing missing spells for %s up to level %d.', res.jobs[job].en, level_cap)) end @@ -232,25 +249,28 @@ function spells_by_job(job, level_cap) end end end - windower.add_to_chat(7, 'List Complete. You are missing ' .. - tostring(spell_count) .. ' ' .. res.jobs[job].en .. ' spells.') + if level_cap > 99 then + windower.add_to_chat(7, string.format( + 'List Complete. You are missing %d %s spells up to %d spent job points.', + spell_count, res.jobs[job].en, level_cap)) + else + windower.add_to_chat(7, string.format( + 'List Complete. You are missing %d %s spells up to level %d.', + spell_count, res.jobs[job].en, level_cap)) + end else if level_cap >= 1500 then - windower.add_to_chat(7, - 'Congratulations! You know all spells for ' .. - res.jobs[job].en .. '.') + windower.add_to_chat(7,string.format( + 'Congratulations! You know all spells for %s.', + res.jobs[job].en)) + elseif level_cap > 99 then + windower.add_to_chat(7,string.format( + 'Congratulations! You know all spells for %s up to %d spent job points!', + res.jobs[job].en, level_cap)) else - if level_cap > 99 then - windower.add_to_chat(7, - 'Congratulations! You know all spells for ' .. - res.jobs[job].en .. ' up to ' .. - tostring(level_cap) .. 'jp.') - else - windower.add_to_chat(7, - 'Congratulations! You know all spells for ' .. - res.jobs[job].en .. ' up to level ' .. - tostring(level_cap) .. '.') - end + windower.add_to_chat(7,string.format( + 'Congratulations! You know all spells for %s up to level %d!', + res.jobs[job].en, level_cap)) end end end @@ -266,6 +286,9 @@ function spells_by_current() local main_job_level = player.main_job_level local main_job_jp = player.job_points[player.main_job:lower()].jp_spent + local main_level + local sub_level + -- If the player has over 99 spend jp, then switch to treating JP as level. if main_job_jp > 99 then main_job_level = main_job_jp @@ -280,7 +303,7 @@ function spells_by_current() if main_level and main_level > main_job_level then main_level = nil end - if sub_level and sub_level> player.sub_job_level then + if sub_level and sub_level > player.sub_job_level then sub_level = nil end @@ -299,21 +322,29 @@ function spells_by_current() end if next(missing_spells) ~= nil then - windower.add_to_chat(7, string.format('Showing learnable spells for %s%d/%s%d.', - player.main_job:lower(), player.main_job_level, - player.sub_job:lower(), player.sub_job_level)) + if main_job_jp > 0 then + windower.add_to_chat(7, string.format('Showing learnable spells for %s%d with %d spent job points and %s%d.', + player.main_job, player.main_job_level, + player.job_points[player.main_job:lower()].jp_spent, + player.sub_job, player.sub_job_level)) + else + windower.add_to_chat(7, string.format('Showing learnable spells for %s%d/%s%d.', + player.main_job, player.main_job_level, + player.sub_job, player.sub_job_level)) + end missing_spells:sort() for _,spell in ipairs(missing_spells) do windower.add_to_chat(7, spell) end - windower.add_to_chat(7, string.format('List Complete. You are missing %d spells for %s%d/%s%d.', - spell_count, player.main_job:lower(), player.main_job_level, - player.sub_job:lower(), player.sub_job_level)) + windower.add_to_chat(7, string.format('List Complete. You are missing %d learnable spells for %s%d/%s%d.', + spell_count, + player.main_job, player.main_job_level, + player.sub_job, player.sub_job_level)) else - windower.add_to_chat(7, string.format('Congratulations! You know all spells for %s%d/%s%d!', - player.main_job:lower(), player.main_job_level, - player.sub_job:lower(), player.sub_job_level)) + windower.add_to_chat(7, string.format('Congratulations! You know all learnable spells for %s%d/%s%d!', + player.main_job, player.main_job_level, + player.sub_job, player.sub_job_level)) end end diff --git a/addons/SpellBook/readme.md b/addons/SpellBook/readme.md index 5c1d074cc5..667c260310 100644 --- a/addons/SpellBook/readme.md +++ b/addons/SpellBook/readme.md @@ -12,6 +12,7 @@ or by category. //spbk [] -- Show missings spells for specified job and level. Defaults to the job's level. //spbk [all]-- Show learnable spells by category. Limited to spells which are learnable, unless all is added after the category. Categories: whitemagic, blackmagic, songs, ninjustu, summoning, bluemagic, geomancy, trusts, all (Trusts are not included in all) +Note: A limit on spent job points can be specified for spells learned from Gifts by entering a level of 100-1500. Spells are never given as Gifts for less than 100 jp. ``` ## Credits From 38f383afd1122cecafb5049caca7098cfd9744d1 Mon Sep 17 00:00:00 2001 From: John Hobart Date: Wed, 11 Apr 2018 16:07:20 -0400 Subject: [PATCH 0085/1002] Make main command check for spend job points --- addons/SpellBook/SpellBook.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/addons/SpellBook/SpellBook.lua b/addons/SpellBook/SpellBook.lua index 43d5916291..179a35155c 100644 --- a/addons/SpellBook/SpellBook.lua +++ b/addons/SpellBook/SpellBook.lua @@ -30,7 +30,12 @@ windower.register_event('addon command', function (command, ...) elseif command == nil or command == 'current' then spells_by_current() elseif command == 'main' then - local level = args[1] or player.main_job_level + local level = player.main_job_level + local job_points = player.job_points[player.main_job:lower()].jp_spent + if job_points > 99 then + level = job_points + end + level = args[1] or level if level == 'all' then level = 1500 end From 0235c571464323cfac019fcb44b99419aacf7e9d Mon Sep 17 00:00:00 2001 From: from20020516 Date: Sat, 14 Apr 2018 01:23:45 +0900 Subject: [PATCH 0086/1002] Add files via upload --- addons/checkparam/README.md | 11 ++ addons/checkparam/checkparam.lua | 174 ++++++++++++++++++++++++++++ addons/checkparam/data/settings.xml | 26 +++++ 3 files changed, 211 insertions(+) create mode 100644 addons/checkparam/README.md create mode 100644 addons/checkparam/checkparam.lua create mode 100644 addons/checkparam/data/settings.xml diff --git a/addons/checkparam/README.md b/addons/checkparam/README.md new file mode 100644 index 0000000000..2eee217d40 --- /dev/null +++ b/addons/checkparam/README.md @@ -0,0 +1,11 @@ +# checkparam + - //cp + - 装備中アイテムの任意のプロパティを合計して表示します。 + - displays the total of optional properties of the item being equipped. + - //cp debug + - 装備中アイテムの全てのプロパティを装備ごとに表示します。 + - displays all the properties of the item being equipped for each equipment. +## settings.xml + - 表示させるプロパティをジョブごとに定義します。 + - define the properties to be displayed for each job. + - || 改行/new line starts \ No newline at end of file diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua new file mode 100644 index 0000000000..34f0b2bb26 --- /dev/null +++ b/addons/checkparam/checkparam.lua @@ -0,0 +1,174 @@ +_addon.name = 'checkparam' +_addon.author = 'from20020516' +_addon.version = '1.0' +_addon.commands = {'cp','checkparam'} +res,extdata,config = require('resources'),require('extdata'),require('config') +settings = config.load('data/settings.xml') +function key_define() + job_define = settings[windower.ffxi.get_player().main_job:lower()] + return job_define and windower.regex.split(job_define,'[|]') + or {'store tp','quadruple attack','triple attack','double attack','', + 'magic accuracy','fast cast','haste','dual wield','', + 'magic attack bonus','magic burst damage','magic damage','', + 'enmity','cure potency'} +end +function split_text(txt,id,arg) + for key,value in string.gmatch(txt,"/?([%D]-):?([%+%-]?[0-9]+)%%?%s?") do + local key = windower.regex.replace(string.lower(key),'(\\"|\\.|\\s$)','') + local key = integrate[key] or key + local key = arg and arg..key or key + tbl[key] = tonumber(value) + (tbl[key] or 0) + if debug then + local color = windower.regex.match(key,'enhanced') and 170 + windower.add_to_chat(color or 72,'['..id..']'..res.items[id].en..'['..key..'] '..value..' '..tbl[key]) + end + end +end +function checkparam(arg1) + debug = arg1=='debug' + tbl,txt={}, + windower.send_command('input /checkparam ') + for slot,bag in pairs(windower.ffxi.get_items().equipment) do + gtbl = windower.ffxi.get_items().equipment + if not string.find(slot,'_bag') then + gear = windower.ffxi.get_items(gtbl[slot..'_bag'],gtbl[slot]) + if gtbl[slot] > 0 and gear.id < 65535 then + if res.item_descriptions[gear.id] then + local txt = windower.regex.split(res.item_descriptions[gear.id].en,"(Pet|Avatar|Automaton|Wyvern|Luopan): ") + for i,v in pairs(windower.regex.split(txt[1],"\n")) do + split_text(v,gear.id) + end + if txt[2] then + local txt = windower.regex.replace(txt[2],'\n',' ') + split_text(txt,gear.id,'pet: ') + end + end + if gear.extdata and extdata.decode(gear).type == 'Augmented Equipment' then + for slot,augment in pairs(extdata.decode(gear).augments) do + split_text(augment,gear.id) + end + end + if enhanced[res.items[gear.id].en] then + local txt = string.split(string.gsub(enhanced[res.items[gear.id].en], "([+-:][0-9]+)",",%1"),",") + tbl[txt[1]] = tonumber(txt[2]) + (tbl[txt[1]] or 0) + if debug then + windower.add_to_chat(170,'['..gear.id..']'..res.items[gear.id].en..'['..txt[1]..'] '..txt[2]..' '..tbl[txt[1]]) + end + end + end + end + end + windower.add_to_chat(69, '//checkparam') + for index,key in pairs(key_define()) do + txt = key == '' and txt..'\n' or (txt or '')..'['..key..'] '..(tbl[string.lower(key)] or 0)..' ' + end + windower.add_to_chat(70, txt) + collectgarbage() +end +integrate={ +--[[integrate same property.information needed for development. @from20020516]] +['quad atk']='quadruple attack', +['triple atk']='triple attack', +['double atk']='double attack', +['dblatk']='double attack', +['blood pact ability delay']='blood pact delay', +['blood pact ability delay ii']='blood pact delay ii', +['blood pact ab. del. ii']='blood pact delay ii', +['blood pact recast time ii']='blood pact delay ii', +['blood pact dmg']='blood pact damage', +['enhancing magic duration']='enhancing magic effect duration', +['eva']='evasion', +['indicolure spell duration']='indicolure effect duration', +['mag eva']='magic evasion', +['magic atk bonus']='magic attack bonus', +['magatkbns']='magic attack bonus', +['mag atk bonus']='magic attack bonus', +['mag acc']='magic accuracy', +['magic burst dmg']='magic burst damage', +['mag dmg']='magic damage', +['crithit rate']='critical hit rate', +} +enhanced={ +['Anhur Robe']='fast cast+10', +['Atinian Staff +1']='fast cast+2', +['Brutal Earring']='double attack+5', +['Charis Necklace']='dual wield+3', +['Cirque Necklace']='martial arts+10', +['Cizin Helm']='fast cast+5', +['Conveyance Cape']='elemental siphon+30', +['Debilis Medallion']='cursna+15', +['Earthcry Earring']='stoneskin+10', +['Eirene\'s Manteel']='fast cast+10', +['Emphatikos Rope']='aquaveil+1', +['Ephedra Ring']='cursna+10', +['Estq. Earring']='fast cast+2', +['Excelsis Ring']='drain and aspir potency+5', +['Ferine Earring']='rewards+2', +['Gende. Galoshes']='cursna+10', +['Gendewitha Gages']='fast cast+7', +['Geomancy Pants']='fast cast+10', +['Haoma\'s Ring']='cursna+15', +['Hearty Earring']='increases resistance to all status ailments+5', +['Iga Mimikazari']='dual wield+1', +['Impulse Belt']='snapshot+3', +['Kenkonken']='martial arts+55', +['Lifestream Cape']='fast cast+7', +['Locus Ring']='magic burst damage+5', +['Loquac. Earring']='fast cast+2', +['Majorelle Shield']='fast cast+5', +['Malison Medallion']='cursna+10', +['Manibozho Gloves']='snapshot+4', +['Mending Cape']='cursna+15', +['Nahtirah Hat']='fast cast+10', +['Nahtirah Trousers']='snapshot+9', +['Navarch\'s Mantle']='snapshot+5', +['Nusku\'s Sash']='dual wield+5', +['Oneiros Rope']='occult acumen+20', +['Orison Locket']='fast cast+5', +['Orunmila\'s Torque']='fast cast+5', +['Orvail Pants +1']='fast cast+5', +['Patentia Sash']='dual wield+5', +['Prolix Ring']='fast cast+2', +['Raider\'s Bmrng.']='dual wield+3', +['Static Earring']='magic burst damage+5', +['Savant\'s Earring']='sublimation+1', +['Shaolin Belt']='martial arts+10', +['Siegel Sash']='stoneskin+20', +['Spharai']='counter+14', +['Stone Gorget']='stoneskin+30', +['Suppanomimi']='dual wield+5', +['Swith Cape +1']='fast cast+4', +['Swith Cape']='fast cast+3', +['Veela Cape']='fast cast+1', +['Witful Belt']='fast cast+3', +['Yagrush']='divine benison+3', +} +windower.register_event('addon command', checkparam) +windower.send_command('cp') +--[[ +Copyright © 2018, from20020516 +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 checkparam 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 from20020516 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. +]] \ No newline at end of file diff --git a/addons/checkparam/data/settings.xml b/addons/checkparam/data/settings.xml new file mode 100644 index 0000000000..d22453ebed --- /dev/null +++ b/addons/checkparam/data/settings.xml @@ -0,0 +1,26 @@ + + + + store tp|double attack|triple attack|quadruple attack||weapon skill damage + store tp|double attack|triple attack|quadruple attack||martial arts|subtle blow + cure potency|cure potency ii|fast cast|cure spellcasting time||enmity|healing magic casting time|divine benison||damage taken|physical damage taken|magic damage taken + magic attack bonus|magic burst damage|magic burst damage ii||int|magic accuracy|magic damage||fast cast|elemental magic casting time + store tp|double attack|triple attack|quadruple attack||dual wield + enmity|damage taken|physical damage taken|magic damage taken||spell inturruption rate|pharanx|cure potency|fastcast + store tp|double attack|triple attack|quadruple attack||weapon skill damage + pet: double attack|pet: magic attack bonus|pet: damage taken + all songs|song effect duration|fast cast|song spellcasting time + store tp|snapshot|rapid shot|weapon skill damage + store tp|double attack|triple attack|quadruple attack||weapon skill damage + store tp|double attack|triple attack|quadruple attack||subtle blow + store tp|double attack|triple attack|quadruple attack||weapon skill damage + blood pact delay|blood pact delay ii|blood pact damage||avatar perpetuation cost|pet: magic attack bonus|pet: str|pet: double attack + store tp|double attack|triple attack|quadruple attack||critical hit rate|critical hit damage|weapon skill damage||fast cast|magic attack bonus|magic accuracy|cure potency + store tp|snapshot|rapid shot|fast cast|cure potency||magic accuracy|magic attack bonus|magic damage|weapon skill damage + pet: hp|pet: damage taken|pet: regen|martial arts||store tp|double attack|triple attack|quadruple attack + store tp|double attack|triple attack|quadruple attack|| + magic attack bonus|magic burst damage|magic burst damage ii||magic accuracy|magic damage|fast cast|elemental magic casting time||cure potency|enh mag eff dur|enhancing magic effect duration + pet: regen|pet: damage taken|indicolure effect duration|indi eff dur||fast cast|magic evasion + enmity|damage taken|physical damage taken|magic damage taken||spell inturruption rate|pharanx|inquartata|fastcast + + \ No newline at end of file From 442934ffbf28480d74832994fafa73609aa397a3 Mon Sep 17 00:00:00 2001 From: Mark Date: Sat, 14 Apr 2018 20:36:34 -0400 Subject: [PATCH 0087/1002] Apr. 2018 ambuscade capes --- addons/libs/extdata.lua | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/addons/libs/extdata.lua b/addons/libs/extdata.lua index a392074fc4..7f89ab7325 100644 --- a/addons/libs/extdata.lua +++ b/addons/libs/extdata.lua @@ -612,6 +612,14 @@ augment_values = { [0x436] = {{stat="Sniper Shot:DMG:", offset=1,multiplier=5,percent=true}}, [0x437] = {{stat="Detonator:DMG:", offset=1,multiplier=5,percent=true}}, [0x438] = {{stat="Weapon Skill:DMG:", offset=1,multiplier=5,percent=true}}, + + [0x480] = {{stat="DEF", offset=1,multiplier=10}}, + [0x481] = {{stat="Evasion", offset=1,multiplier=3}}, + [0x482] = {{stat="Mag. Evasion", offset=1,multiplier=3}}, + [0x483] = {{stat="Phys. dmg. taken", offset=1,multiplier=-2,percent=true}}, + [0x484] = {{stat="Magic dmg. taken", offset=1,multiplier=-2,percent=true}}, + [0x485] = {{stat="Spell interruption rate down", offset=1,multiplier=-2,percent=true}}, + [0x486] = {{stat="Occ. inc. resist. to stat. ailements", offset=1,multiplier=2}}, [0x4E0] = {{stat="Enh. Mag. eff. dur. ", offset=1}}, [0x4E1] = {{stat="Helix eff. dur. ", offset=1}}, From 54fd300767c0bbe944c90df90ceeb4c4f0e1c3a1 Mon Sep 17 00:00:00 2001 From: Mark Date: Sat, 14 Apr 2018 20:39:49 -0400 Subject: [PATCH 0088/1002] Typo in augment name --- addons/libs/extdata.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/extdata.lua b/addons/libs/extdata.lua index 7f89ab7325..d0d8bbeced 100644 --- a/addons/libs/extdata.lua +++ b/addons/libs/extdata.lua @@ -619,7 +619,7 @@ augment_values = { [0x483] = {{stat="Phys. dmg. taken", offset=1,multiplier=-2,percent=true}}, [0x484] = {{stat="Magic dmg. taken", offset=1,multiplier=-2,percent=true}}, [0x485] = {{stat="Spell interruption rate down", offset=1,multiplier=-2,percent=true}}, - [0x486] = {{stat="Occ. inc. resist. to stat. ailements", offset=1,multiplier=2}}, + [0x486] = {{stat="Occ. inc. resist. to stat. ailments", offset=1,multiplier=2}}, [0x4E0] = {{stat="Enh. Mag. eff. dur. ", offset=1}}, [0x4E1] = {{stat="Helix eff. dur. ", offset=1}}, From b74b9cf3d0261c5f5f1da626e86f16929545c15f Mon Sep 17 00:00:00 2001 From: Mark Date: Sun, 15 Apr 2018 01:31:18 -0400 Subject: [PATCH 0089/1002] Findall stuttering --- addons/findAll/findAll.lua | 2 -- 1 file changed, 2 deletions(-) diff --git a/addons/findAll/findAll.lua b/addons/findAll/findAll.lua index 7ff63096f4..75749e2904 100644 --- a/addons/findAll/findAll.lua +++ b/addons/findAll/findAll.lua @@ -469,7 +469,6 @@ function make_table(tab,tab_offset) ret = ret..tostring(v)..',\n' end end - coroutine.yield() return ret..offset..'}' end @@ -519,7 +518,6 @@ function update_global_storage() warning('Unable to retrieve updated item storage for %s.':format(f:sub(1,-5))) end end - coroutine.yield() end end From 271f5a47e36865395f6dadce47a5fbfb7ee0934b Mon Sep 17 00:00:00 2001 From: Chiaia Date: Sun, 15 Apr 2018 02:56:04 -0400 Subject: [PATCH 0090/1002] Version History to go along with the stutter issue --- addons/findAll/findAll.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/findAll/findAll.lua b/addons/findAll/findAll.lua index 75749e2904..ea4b59f2e0 100644 --- a/addons/findAll/findAll.lua +++ b/addons/findAll/findAll.lua @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'findAll' _addon.author = 'Zohno' -_addon.version = '1.20170501' +_addon.version = '1.20180415' _addon.commands = {'findall'} require('chat') From 76cff7c2a0319ec035568bb490923d341d6bb451 Mon Sep 17 00:00:00 2001 From: "J. Cameron McDonald" Date: Thu, 19 Apr 2018 21:03:04 -0500 Subject: [PATCH 0091/1002] Use prepared statements in get_notes --- addons/InfoBar/InfoBar.lua | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/addons/InfoBar/InfoBar.lua b/addons/InfoBar/InfoBar.lua index efa0f5ea20..d92c4b05cf 100644 --- a/addons/InfoBar/InfoBar.lua +++ b/addons/InfoBar/InfoBar.lua @@ -90,7 +90,7 @@ end function get_db(target, zones, level) local query = 'SELECT * FROM "monster" WHERE name = "'..target..'" AND zone = "'..zones..'"' local MOB_infobar = {} - + if db:isopen() and query then for id,name,family,job,zone,isaggressive,islinking,isnm,isfishing,levelmin,levelmax,sight,sound,magic,lowhp,healing,ts,th,scent,weakness,resistances,immunities,drops,stolen,spawn,spawntime in db:urows(query) do if name == target and zone == zones then @@ -145,9 +145,10 @@ function get_db(target, zones, level) end function get_notes(target) - local query = 'SELECT * FROM "notes" WHERE name = "'..target..'"' - if notesdb:isopen() and query then - for name, note in notesdb:urows(query) do + local statement = notesdb:prepare('SELECT * FROM "notes" WHERE name = ?;') + if notesdb:isopen() and statement then + statement:bind(1, target) + for name, note in statement:urows(query, { target }) do if name == target then return note or nil end @@ -203,16 +204,16 @@ end) windower.register_event('prerender', function() local info = windower.ffxi.get_info() - + if not info.logged_in or not windower.ffxi.get_player() or zoning_bool then box:hide() return end - + infobar.game_moon = res.moon_phases[info.moon_phase].name infobar.game_moon_pct = info.moon..'%' infobar.zone_name = res.zones[info.zone].name - + local pos = windower.ffxi.get_mob_by_target('st') or windower.ffxi.get_mob_by_target('t') or windower.ffxi.get_mob_by_target('me') if not pos then return end infobar.x = string.format('%0.3f', pos.x) @@ -220,7 +221,7 @@ windower.register_event('prerender', function() infobar.z = string.format('%0.3f', pos.z) infobar.facing = tostring(getDegrees(pos.facing))..'°' infobar.facing_dir = DegreesToDirection(pos.facing) - + box:update(infobar) box:show() end) From bd439762fd43f7d50aee915119ccf46258970047 Mon Sep 17 00:00:00 2001 From: "J. Cameron McDonald" Date: Thu, 19 Apr 2018 21:47:25 -0500 Subject: [PATCH 0092/1002] Clean up get_db function --- addons/InfoBar/InfoBar.lua | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/addons/InfoBar/InfoBar.lua b/addons/InfoBar/InfoBar.lua index efa0f5ea20..f7b371ab19 100644 --- a/addons/InfoBar/InfoBar.lua +++ b/addons/InfoBar/InfoBar.lua @@ -90,7 +90,8 @@ end function get_db(target, zones, level) local query = 'SELECT * FROM "monster" WHERE name = "'..target..'" AND zone = "'..zones..'"' local MOB_infobar = {} - + box:bold(false) + if db:isopen() and query then for id,name,family,job,zone,isaggressive,islinking,isnm,isfishing,levelmin,levelmax,sight,sound,magic,lowhp,healing,ts,th,scent,weakness,resistances,immunities,drops,stolen,spawn,spawntime in db:urows(query) do if name == target and zone == zones then @@ -108,8 +109,6 @@ function get_db(target, zones, level) MOB_infobar.isagressive = 'A' if levelmax and (level - tonumber(levelmax)) <= 10 then box:bold(true) - else - box:bold(false) end else MOB_infobar.isagressive = 'NA' @@ -128,18 +127,8 @@ function get_db(target, zones, level) scent == 1 and 'Sc' or '', } MOB_infobar.detect = detect:filter(-''):concat(',') - else - box:bold(false) - for i,v in pairs(MOB_infobar) do - v = '' - end end end - else - box:bold(false) - for i,v in pairs(MOB_infobar) do - v = '' - end end box:update(MOB_infobar) end From c05f86f4a95acd8408655c03b3aaebac182ae0ed Mon Sep 17 00:00:00 2001 From: John Hobart Date: Fri, 20 Apr 2018 20:14:51 -0400 Subject: [PATCH 0093/1002] Fix the missing name in the copyright --- addons/SpellBook/SpellBook.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/SpellBook/SpellBook.lua b/addons/SpellBook/SpellBook.lua index 179a35155c..d7b3135191 100644 --- a/addons/SpellBook/SpellBook.lua +++ b/addons/SpellBook/SpellBook.lua @@ -372,7 +372,7 @@ modification, are permitted provided that the following conditions are met: 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 BE LIABLE FOR ANY +DISCLAIMED. IN NO EVENT SHALL John S Hobart 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 From 89ef74e8f99b60dc66b756c3c7c5f7556971dbc4 Mon Sep 17 00:00:00 2001 From: John Hobart Date: Fri, 20 Apr 2018 20:24:33 -0400 Subject: [PATCH 0094/1002] Realign incorrect spacing --- addons/SpellBook/SpellBook.lua | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/addons/SpellBook/SpellBook.lua b/addons/SpellBook/SpellBook.lua index d7b3135191..4fca70fd82 100644 --- a/addons/SpellBook/SpellBook.lua +++ b/addons/SpellBook/SpellBook.lua @@ -1,21 +1,21 @@ _addon.name = 'SpellBook' _addon.author = 'SigilBaram' _addon.version = '0.0.1' -_addon.commands = {'spellbook','spbk'} +_addon.commands = {'spellbook','spbk'} require('tables') res = require('resources') spell_types = { - whitemagic= { type = 'WhiteMagic', readable = 'White Magic spells' }, - blackmagic= { type = 'BlackMagic', readable = 'Black Magic spells' }, - songs= { type = 'BardSong', readable = 'Bard songs' }, - ninjutsu= { type = 'Ninjutsu', readable = 'Ninjutsu' }, - summoning= { type = 'SummonerPact', readable = 'Summoning spells' }, - bluemagic= { type = 'BlueMagic', readable = 'Blue Magic spells' }, - geomancy= { type = 'Geomancy', readable = 'Geomancy spells' }, - trusts= { type = 'Trust', readable = 'Trusts'}, - all= { type = 'all', readable = 'spells of all types'} + whitemagic = { type = 'WhiteMagic', readable = 'White Magic spells' }, + blackmagic = { type = 'BlackMagic', readable = 'Black Magic spells' }, + songs = { type = 'BardSong', readable = 'Bard songs' }, + ninjutsu = { type = 'Ninjutsu', readable = 'Ninjutsu' }, + summoning = { type = 'SummonerPact', readable = 'Summoning spells' }, + bluemagic = { type = 'BlueMagic', readable = 'Blue Magic spells' }, + geomancy = { type = 'Geomancy', readable = 'Geomancy spells' }, + trusts = { type = 'Trust', readable = 'Trusts'}, + all = { type = 'all', readable = 'spells of all types'} } windower.register_event('addon command', function (command, ...) From 5c8aec64a37e5e4c8163bb93a8b06a562471198f Mon Sep 17 00:00:00 2001 From: John Hobart Date: Fri, 20 Apr 2018 21:15:04 -0400 Subject: [PATCH 0095/1002] Improve resource access and readability --- addons/SpellBook/SpellBook.lua | 39 +++++++++++++++++----------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/addons/SpellBook/SpellBook.lua b/addons/SpellBook/SpellBook.lua index 4fca70fd82..14b70b4235 100644 --- a/addons/SpellBook/SpellBook.lua +++ b/addons/SpellBook/SpellBook.lua @@ -28,7 +28,7 @@ windower.register_event('addon command', function (command, ...) if command == 'help' then display_help() elseif command == nil or command == 'current' then - spells_by_current() + spells_by_current(player) elseif command == 'main' then local level = player.main_job_level local job_points = player.job_points[player.main_job:lower()].jp_spent @@ -58,15 +58,15 @@ windower.register_event('addon command', function (command, ...) end elseif spell_types[command] then if args[1] == 'all' then - spells_by_type(spell_types[command], false) + spells_by_type(player, spell_types[command], false) elseif args[1] == nil then - spells_by_type(spell_types[command], true) + spells_by_type(player, spell_types[command], true) else invalid_input() end elseif jobs[command] then local job = jobs[command] - local level = args[1] or player.jobs[res.jobs[job].ens] + local level = args[1] or player.jobs[res.jobs[job].english_short] if level == 'all' then level = 1500 end @@ -88,7 +88,7 @@ reading in user input. function build_job_list() local jobs = {} for id,val in pairs(res.jobs) do - jobs[val.ens:lower()] = id + jobs[val.english_short:lower()] = id end return jobs end @@ -114,10 +114,10 @@ end Returns true if the player has any jobs which is high enough level to learn the given spell. --]] -function is_learnable(spell) - local player_levels = windower.ffxi.get_player().jobs +function is_learnable(player, spell) + local player_levels = player.jobs for job,level in pairs(spell.levels) do - if player_levels[res.jobs[job].ens] >= level then + if player_levels[res.jobs[job].english_short] >= level then return true end end @@ -140,10 +140,10 @@ function format_spell(spell) jobs:sort() for _,job_id in ipairs(jobs) do if spell.levels[job_id] <= 99 then - levels:append(res.jobs[job_id].ens .. ' Lv.' .. + levels:append(res.jobs[job_id].english_short .. ' Lv.' .. tostring(spell.levels[job_id])) else - levels:append(res.jobs[job_id].ens .. ' Jp.' .. + levels:append(res.jobs[job_id].english_short .. ' Jp.' .. tostring(spell.levels[job_id])) end end @@ -151,7 +151,7 @@ function format_spell(spell) else format = ' ( Trust )' end - return string.format('%-20s %s', spell.en, format) + return string.format('%-20s %s', spell.english, format) end --[[ @@ -159,15 +159,15 @@ Show missing spells of a given type. If learnable is true, then the results will be limited to spells for which the player has a job at a level required to learn the spell. --]] -function spells_by_type(spell_type, learnable_only) +function spells_by_type(player, spell_type, learnable_only) local missing_spells = T{} local player_spells = windower.ffxi.get_spells() local spell_count = 0 for spell_id,spell in pairs(res.spells) do if ((spell_type.type == 'all' and spell.type ~= 'Trust') or - spell.type == spell_type.type) and next(spell.levels) ~= nill and - not player_spells[spell_id] and (is_learnable(spell) or + spell.type == spell_type.type) and not spell.levels:empty() and + not player_spells[spell_id] and (is_learnable(player, spell) or not learnable_only) and not spell.unlearnable then missing_spells:append(format_spell(spell)) @@ -183,7 +183,7 @@ function spells_by_type(spell_type, learnable_only) spell_type.readable)) end - if next(missing_spells) ~= nil then + if not missing_spells:empty() then missing_spells:sort() for _,spell in ipairs(missing_spells) do windower.add_to_chat(7, spell) @@ -226,12 +226,12 @@ function spells_by_job(job, level_cap) not spell.unlearnable then missing_spells[spell_level] = missing_spells[spell_level] or T{} - missing_spells[spell_level]:append(spell.en) + missing_spells[spell_level]:append(spell.english) spell_count = spell_count + 1 end end - if next(missing_spells) ~= nil then + if not missing_spells:empty() then if level_cap > 99 then windower.add_to_chat(7, string.format( 'Showing missing spells for %s up to %d spent job points.', @@ -281,9 +281,8 @@ function spells_by_job(job, level_cap) end -- Show missing spells for the current main and sub jobs. -function spells_by_current() +function spells_by_current(player) local missing_spells = T{} - local player = windower.ffxi.get_player() local player_spells = windower.ffxi.get_spells() local spell_count = 0 @@ -326,7 +325,7 @@ function spells_by_current() end end - if next(missing_spells) ~= nil then + if not missing_spells:empty() then if main_job_jp > 0 then windower.add_to_chat(7, string.format('Showing learnable spells for %s%d with %d spent job points and %s%d.', player.main_job, player.main_job_level, From 6240b2ee0c8f976c22816024d42337ddaa2c8b9c Mon Sep 17 00:00:00 2001 From: John Hobart Date: Fri, 20 Apr 2018 21:51:30 -0400 Subject: [PATCH 0096/1002] Reformat comments and make them more consistent --- addons/SpellBook/SpellBook.lua | 75 ++++++++++++++++++++++++---------- 1 file changed, 53 insertions(+), 22 deletions(-) diff --git a/addons/SpellBook/SpellBook.lua b/addons/SpellBook/SpellBook.lua index 14b70b4235..839736f395 100644 --- a/addons/SpellBook/SpellBook.lua +++ b/addons/SpellBook/SpellBook.lua @@ -81,10 +81,12 @@ windower.register_event('addon command', function (command, ...) end end) ---[[ -Builds a list of jobs with short name as the key and id as the value, for -reading in user input. ---]] +-------------------------------------------------------------------------------- +--Name: build_job_list +-------------------------------------------------------------------------------- +--Returns: +---- (table) list of jobs with short name as the key and id as the value +-------------------------------------------------------------------------------- function build_job_list() local jobs = {} for id,val in pairs(res.jobs) do @@ -93,12 +95,18 @@ function build_job_list() return jobs end --- Display an error message for invalid input. +-------------------------------------------------------------------------------- +--Name: invalid_input +---- Display an error message for invalid input. +-------------------------------------------------------------------------------- function invalid_input() windower.add_to_chat(7, 'Invalid input. See //spbk help.') end +-------------------------------------------------------------------------------- +--Name: display_help -- Display help text for the addon. +-------------------------------------------------------------------------------- function display_help() windower.add_to_chat(7, _addon.name .. ' version ' .. _addon.version) windower.add_to_chat(7, '//spbk help -- show this help text') @@ -110,10 +118,15 @@ function display_help() windower.add_to_chat(7, 'Note: A limit on spent job points can be specified for spells learned from Gifts by entering a level of 100-1500. Spells are never given as Gifts for less than 100 jp.') end ---[[ -Returns true if the player has any jobs which is high enough level to learn -the given spell. ---]] +-------------------------------------------------------------------------------- +--Name: is_learnable +--Args: +---- player (table): player object from windower.ffxi.get_player() +---- spell (table): a spell from resources.spells +-------------------------------------------------------------------------------- +--Returns: +---- (bool) true if player has a job that is high enough level to learn spell +-------------------------------------------------------------------------------- function is_learnable(player, spell) local player_levels = player.jobs for job,level in pairs(spell.levels) do @@ -124,10 +137,16 @@ function is_learnable(player, spell) return false end ---[[ -Formats a spell as the spell's name followed by a list of jobs and levels -which would qualify to learn that spell. ---]] +-------------------------------------------------------------------------------- +--Name: format_spell +-- Formats a spell as the spell's name followed by a list of jobs and levels +-- which would qualify to learn that spell. +--Args: +---- spell (table): a spell from resources.spells +-------------------------------------------------------------------------------- +--Returns: +---- (string) the formatted string +-------------------------------------------------------------------------------- function format_spell(spell) local format @@ -154,11 +173,15 @@ function format_spell(spell) return string.format('%-20s %s', spell.english, format) end ---[[ -Show missing spells of a given type. If learnable is true, then the -results will be limited to spells for which the player has a job at a -level required to learn the spell. ---]] +-------------------------------------------------------------------------------- +--Name: spells_by_type +-- List spells of a given type, i.e. white magic. +--Args: +---- player (T): player object from windower.ffxi.get_player() +---- spell_type (table): one of the types from spell_types global +---- learnable_only (bool): if true then the output is limited to spell for +---- which the player has a job that is high enough level +-------------------------------------------------------------------------------- function spells_by_type(player, spell_type, learnable_only) local missing_spells = T{} local player_spells = windower.ffxi.get_spells() @@ -210,10 +233,13 @@ function spells_by_type(player, spell_type, learnable_only) end end ---[[ -List unkown spells for a specific job (by id), up to an optional level. -If no level_cap is given then the maximum is used. ---]] +-------------------------------------------------------------------------------- +--Name: spells_by_job +-- List unknown spells by job. +--Args: +---- job (int): the job's id +---- level_cap (int): the max level/jp required by listed spells +-------------------------------------------------------------------------------- function spells_by_job(job, level_cap) local missing_spells = T{} local player_spells = windower.ffxi.get_spells() @@ -280,7 +306,12 @@ function spells_by_job(job, level_cap) end end +-------------------------------------------------------------------------------- +--Name: spells_by_current -- Show missing spells for the current main and sub jobs. +--Args: +---- player (T): player object from windower.ffxi.get_player() +-------------------------------------------------------------------------------- function spells_by_current(player) local missing_spells = T{} local player_spells = windower.ffxi.get_spells() From ad17e283df47756c521facbe19b5df6de2c77b66 Mon Sep 17 00:00:00 2001 From: John Hobart Date: Fri, 20 Apr 2018 21:52:48 -0400 Subject: [PATCH 0097/1002] Only call get_player() if used --- addons/SpellBook/SpellBook.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/addons/SpellBook/SpellBook.lua b/addons/SpellBook/SpellBook.lua index 839736f395..a009f5e121 100644 --- a/addons/SpellBook/SpellBook.lua +++ b/addons/SpellBook/SpellBook.lua @@ -20,7 +20,6 @@ spell_types = { windower.register_event('addon command', function (command, ...) local args = L{...} - local player = windower.ffxi.get_player() local jobs = build_job_list() command = command and command:lower() @@ -28,8 +27,10 @@ windower.register_event('addon command', function (command, ...) if command == 'help' then display_help() elseif command == nil or command == 'current' then + local player = windower.ffxi.get_player() spells_by_current(player) elseif command == 'main' then + local player = windower.ffxi.get_player() local level = player.main_job_level local job_points = player.job_points[player.main_job:lower()].jp_spent if job_points > 99 then @@ -46,6 +47,7 @@ windower.register_event('addon command', function (command, ...) invalid_input() end elseif command == 'sub' then + local player = windower.ffxi.get_player() local level = args[1] or player.sub_job_level if level == 'all' then level = 1500 @@ -58,14 +60,17 @@ windower.register_event('addon command', function (command, ...) end elseif spell_types[command] then if args[1] == 'all' then + local player = windower.ffxi.get_player() spells_by_type(player, spell_types[command], false) elseif args[1] == nil then + local player = windower.ffxi.get_player() spells_by_type(player, spell_types[command], true) else invalid_input() end elseif jobs[command] then local job = jobs[command] + local player = windower.ffxi.get_player() local level = args[1] or player.jobs[res.jobs[job].english_short] if level == 'all' then level = 1500 From adeb0c6f858ea185480a1bae01e5da689588fb72 Mon Sep 17 00:00:00 2001 From: John Hobart Date: Fri, 20 Apr 2018 22:13:19 -0400 Subject: [PATCH 0098/1002] Improve help output and readme --- addons/SpellBook/SpellBook.lua | 11 ++++++----- addons/SpellBook/readme.md | 31 ++++++++++++++++++++++++------- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/addons/SpellBook/SpellBook.lua b/addons/SpellBook/SpellBook.lua index a009f5e121..37765544fd 100644 --- a/addons/SpellBook/SpellBook.lua +++ b/addons/SpellBook/SpellBook.lua @@ -114,13 +114,14 @@ end -------------------------------------------------------------------------------- function display_help() windower.add_to_chat(7, _addon.name .. ' version ' .. _addon.version) - windower.add_to_chat(7, '//spbk help -- show this help text') - windower.add_to_chat(7, '//spbk [current] -- Shows learnable spells based on current main and sub job and level.') - windower.add_to_chat(7, '//spbk [] -- Show missing spells for current main or sub job. Defaults to the job\'s current level.') - windower.add_to_chat(7, '//spbk [] -- Show missings spells for specified job and level. Defaults to the job\'s level.') + windower.add_to_chat(7, 'Spent jp can be specified for spells learned from Gifts by entering a value of 100-1500.') + windower.add_to_chat(7, 'Spells are never given as Gifts for less than 100 jp and values under 100 are treated as level.') + windower.add_to_chat(7, '//spbk help -- Show this help text.') + windower.add_to_chat(7, '//spbk [current] -- Show learnable spells based on current main and sub job and level/jp.') + windower.add_to_chat(7, '//spbk [] -- Show missing spells for current main or sub job. Defaults to the job\'s current level/jp.') + windower.add_to_chat(7, '//spbk [] -- Show missings spells for specified job and level. Defaults to the job\'s level/jp.') windower.add_to_chat(7, '//spbk [all] -- Show learnable spells by category. Limited to spells which are learnable, unless all is added after the category.') windower.add_to_chat(7, 'Categories: whitemagic, blackmagic, songs, ninjustu, summoning, bluemagic, geomancy, trusts, all (Trusts are not included in all)') - windower.add_to_chat(7, 'Note: A limit on spent job points can be specified for spells learned from Gifts by entering a level of 100-1500. Spells are never given as Gifts for less than 100 jp.') end -------------------------------------------------------------------------------- diff --git a/addons/SpellBook/readme.md b/addons/SpellBook/readme.md index 667c260310..aef96a267d 100644 --- a/addons/SpellBook/readme.md +++ b/addons/SpellBook/readme.md @@ -4,16 +4,33 @@ This addon helps you find missing spells. You can search by job and level, or by category. ## Usage +Spent jp can be specified for spells learned from Gifts by entering a value of 100-1500. +Spells are never given as Gifts for less than 100 jp and values under 100 are treated as level. + ``` -//spbk help -- show this help text -//spbk [current] -- Shows learnable spells based on current main and sub job and level. -//spbk [] -- Show missing spells for current main or sub job. Defaults to the job's current level. -//spbk [] -- Show missings spells for specified job and level. Defaults to the job's level. -//spbk [all]-- Show learnable spells by category. Limited to spells which are learnable, unless all is added after the category. -Categories: whitemagic, blackmagic, songs, ninjustu, summoning, bluemagic, geomancy, trusts, all (Trusts are not included in all) -Note: A limit on spent job points can be specified for spells learned from Gifts by entering a level of 100-1500. Spells are never given as Gifts for less than 100 jp. +//spbk help +``` +Show help text. +``` +//spbk [current] +``` +Show learnable spells based on current main and sub job and level/jp. +``` +//spbk [] +``` +Show missing spells for current main or sub job. Defaults to the job\'s current level/jp. ``` +//spbk [] +``` +Show missings spells for specified job and level. Defaults to the job\'s level/jp. +``` +//spbk [all] +``` +Show learnable spells by category. Limited to spells which are learnable, unless all is added after the category. + +Categories: whitemagic, blackmagic, songs, ninjustu, summoning, bluemagic, geomancy, trusts, all (Trusts are not included in all) + ## Credits From 917654be312c7d78a345508e7157483627472da6 Mon Sep 17 00:00:00 2001 From: John Hobart Date: Fri, 20 Apr 2018 23:28:43 -0400 Subject: [PATCH 0099/1002] Explicitly set default command for readability --- addons/SpellBook/SpellBook.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/SpellBook/SpellBook.lua b/addons/SpellBook/SpellBook.lua index 37765544fd..95bd0d0359 100644 --- a/addons/SpellBook/SpellBook.lua +++ b/addons/SpellBook/SpellBook.lua @@ -22,11 +22,11 @@ windower.register_event('addon command', function (command, ...) local args = L{...} local jobs = build_job_list() - command = command and command:lower() + command = command and command:lower() or 'current' if command == 'help' then display_help() - elseif command == nil or command == 'current' then + elseif command == 'current' then local player = windower.ffxi.get_player() spells_by_current(player) elseif command == 'main' then From 23b6911218c94cbeec73679d60d0fc1e5e1d7b40 Mon Sep 17 00:00:00 2001 From: John Hobart Date: Fri, 20 Apr 2018 23:48:18 -0400 Subject: [PATCH 0100/1002] Update addons.xml --- addons/addons.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/addons/addons.xml b/addons/addons.xml index 5bc38003ff..527d0f0d74 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -543,6 +543,13 @@ https://github.com/DamienDennehy/Lua/issues http://www.ffxiah.com/player/Asura/Zubis + + SpellBook + Sigil Baram (Ravlyn@Asura) + List unknown spells by job or category. Can also limit results by level or spent jp required by the spell. + https://github.com/sigilbaram/SpellBook/issues + https://discord.gg/b275nMv + StaggerTrack Nitrous (Shiva) From 79e3fec37dd0899eef67e9a259cbb69a399f2a46 Mon Sep 17 00:00:00 2001 From: John Hobart Date: Sat, 21 Apr 2018 23:45:16 -0400 Subject: [PATCH 0101/1002] Make sure the player has a sub job --- addons/SpellBook/SpellBook.lua | 56 +++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/addons/SpellBook/SpellBook.lua b/addons/SpellBook/SpellBook.lua index 95bd0d0359..93f4702c93 100644 --- a/addons/SpellBook/SpellBook.lua +++ b/addons/SpellBook/SpellBook.lua @@ -48,6 +48,10 @@ windower.register_event('addon command', function (command, ...) end elseif command == 'sub' then local player = windower.ffxi.get_player() + if not player.sub_job then + windower.add_to_chat(7, "You don't have a subjob equipped.") + return + end local level = args[1] or player.sub_job_level if level == 'all' then level = 1500 @@ -195,7 +199,7 @@ function spells_by_type(player, spell_type, learnable_only) for spell_id,spell in pairs(res.spells) do if ((spell_type.type == 'all' and spell.type ~= 'Trust') or - spell.type == spell_type.type) and not spell.levels:empty() and + spell.type == spell_type.type) and not table.empty(spell.levels) and not player_spells[spell_id] and (is_learnable(player, spell) or not learnable_only) and not spell.unlearnable then @@ -364,28 +368,50 @@ function spells_by_current(player) if not missing_spells:empty() then if main_job_jp > 0 then - windower.add_to_chat(7, string.format('Showing learnable spells for %s%d with %d spent job points and %s%d.', - player.main_job, player.main_job_level, - player.job_points[player.main_job:lower()].jp_spent, - player.sub_job, player.sub_job_level)) + if player.sub_job then + windower.add_to_chat(7, string.format('Showing learnable spells for %s%d with %d spent job points and %s%d.', + player.main_job, player.main_job_level, + player.job_points[player.main_job:lower()].jp_spent, + player.sub_job, player.sub_job_level)) + else + windower.add_to_chat(7, string.format('Showing learnable spells for %s%d with %d spent job points.', + player.main_job, player.main_job_level, + player.job_points[player.main_job:lower()].jp_spent)) + end else - windower.add_to_chat(7, string.format('Showing learnable spells for %s%d/%s%d.', - player.main_job, player.main_job_level, - player.sub_job, player.sub_job_level)) + if player.sub_job then + windower.add_to_chat(7, string.format('Showing learnable spells for %s%d/%s%d.', + player.main_job, player.main_job_level, + player.sub_job, player.sub_job_level)) + else + windower.add_to_chat(7, string.format('Showing learnable spells for %s%d.', + player.main_job, player.main_job_level)) + end end missing_spells:sort() for _,spell in ipairs(missing_spells) do windower.add_to_chat(7, spell) end - windower.add_to_chat(7, string.format('List Complete. You are missing %d learnable spells for %s%d/%s%d.', - spell_count, - player.main_job, player.main_job_level, - player.sub_job, player.sub_job_level)) + if player.sub_job then + windower.add_to_chat(7, string.format('List Complete. You are missing %d learnable spells for %s%d/%s%d.', + spell_count, + player.main_job, player.main_job_level, + player.sub_job, player.sub_job_level)) + else + windower.add_to_chat(7, string.format('List Complete. You are missing %d learnable spells for %s%d.', + spell_count, + player.main_job, player.main_job_level)) + end else - windower.add_to_chat(7, string.format('Congratulations! You know all learnable spells for %s%d/%s%d!', - player.main_job, player.main_job_level, - player.sub_job, player.sub_job_level)) + if player.sub_job then + windower.add_to_chat(7, string.format('Congratulations! You know all learnable spells for %s%d/%s%d!', + player.main_job, player.main_job_level, + player.sub_job, player.sub_job_level)) + else + windower.add_to_chat(7, string.format('Congratulations! You know all learnable spells for %s%d!', + player.main_job, player.main_job_level)) + end end end From f4ca43708ad5a10fedf5a6586182d86bb3976567 Mon Sep 17 00:00:00 2001 From: Mark Date: Sun, 22 Apr 2018 19:06:43 -0400 Subject: [PATCH 0102/1002] Parrying rate extdata --- addons/libs/extdata.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/libs/extdata.lua b/addons/libs/extdata.lua index d0d8bbeced..f839778a75 100644 --- a/addons/libs/extdata.lua +++ b/addons/libs/extdata.lua @@ -760,6 +760,8 @@ augment_values = { [0x5AF] = {{stat='Enhances "Rayke" effect', offset=0,multiplier=0}}, [0x5B0] = {{stat='Enhances "Inspire" effect', offset=0,multiplier=0}}, [0x5B1] = {{stat='Enhances "Sleight of Sword" effect', offset=0,multiplier=0}}, + + [0x5C0] = {{stat="Parrying rate", offset=1,percent=true}}, [0x600] = {{stat="Backhand Blow:DMG:", offset=1,multiplier=5,percent=true}}, [0x601] = {{stat="Spinning Attack:DMG:", offset=1,multiplier=5,percent=true}}, From 759a7cdbe7f128b5b0ad97af8fe9ac2f15edfe54 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Sun, 29 Apr 2018 06:13:39 -0400 Subject: [PATCH 0103/1002] Update fields.lua --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 9742ae290e..53fa02149b 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1720,7 +1720,7 @@ func.incoming[0x028].action_base = L{ {ctype='bit[6]', label='Stagger'}, -- 02:5 {ctype='bit[17]', label='Param'}, -- 03:3 {ctype='bit[10]', label='Message'}, -- 06:2 - {ctype='bit[31]', label='_unknown'}, -- 07:4 + {ctype='bit[31]', label='_unknown'}, -- 07:4 --Message Modifier? If you get a complete (Resist!) this is set to 2 otherwise a regular Resist is 0. } func.incoming[0x028].add_effect_base = L{ From 508fb5a2878e7bcb7152efc647bc263ca81036d9 Mon Sep 17 00:00:00 2001 From: Nekseus Date: Thu, 3 May 2018 03:01:51 -0400 Subject: [PATCH 0104/1002] gearswap_disabled additions added gearswap_disabled for pet_status_change and pet_change calling equip_sets --- addons/GearSwap/gearswap.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/GearSwap/gearswap.lua b/addons/GearSwap/gearswap.lua index f395000e14..d0126f176d 100644 --- a/addons/GearSwap/gearswap.lua +++ b/addons/GearSwap/gearswap.lua @@ -285,15 +285,15 @@ function incoming_chunk(id,data,modified,injected,blocked) refresh_globals() next_packet_events.globals_update = data:unpack('H',3) end - if next_packet_events.pet_status_change then + if next_packet_events.pet_status_change and not gearswap_disable then equip_sets('pet_status_change',nil,next_packet_events.pet_status_change.newstatus,next_packet_events.pet_status_change.oldstatus) next_packet_events.pet_status_change = nil end if next_packet_events.pet_change then - if next_packet_events.pet_change.pet then -- Losing a pet + if next_packet_events.pet_change.pet and not gearswap_disabled then -- Losing a pet equip_sets('pet_change',nil,next_packet_events.pet_change.pet,false) next_packet_events.pet_change = nil - elseif pet.isvalid then -- Gaining a pet + elseif pet.isvalid and not gearswap_disabled then -- Gaining a pet equip_sets('pet_change',nil,pet,true) next_packet_events.pet_change = nil end @@ -331,4 +331,4 @@ windower.register_event('login',function(name) windower.debug('login '..name) initialize_globals() windower.send_command('@wait 2;lua i gearswap refresh_user_env;') -end) \ No newline at end of file +end) From ef03faf2c6b25cc64c926e33bb465371f0f29a42 Mon Sep 17 00:00:00 2001 From: zetaepyon Date: Fri, 4 May 2018 19:16:37 -0500 Subject: [PATCH 0105/1002] Update pointwatch message IDs --- addons/pointwatch/message_ids.lua | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/addons/pointwatch/message_ids.lua b/addons/pointwatch/message_ids.lua index 300dc2bd12..470990897c 100644 --- a/addons/pointwatch/message_ids.lua +++ b/addons/pointwatch/message_ids.lua @@ -33,7 +33,7 @@ local messages = { z15 = { name = 'Abyssea - Konschtat', - offset = 7305, + offset = 7312, pearl_ebon_gold_silvery = 0, azure_ruby_amber = 1, visitant_status_update = 9, @@ -50,7 +50,7 @@ local messages = { }, z132 = { name = 'Abyssea - La Theine', - offset = 7305, + offset = 7312, pearl_ebon_gold_silvery = 0, azure_ruby_amber = 1, visitant_status_update = 9, @@ -67,7 +67,7 @@ local messages = { }, z45 = { name = 'Abyssea - Tahrongi', - offset = 7305, + offset = 7312, pearl_ebon_gold_silvery = 0, azure_ruby_amber = 1, visitant_status_update = 9, @@ -84,7 +84,7 @@ local messages = { }, z215 = { name = 'Abyssea - Attohwa', - offset = 7210, + offset = 7212, pearl_ebon_gold_silvery = 0, azure_ruby_amber = 1, visitant_status_update = 9, @@ -101,7 +101,7 @@ local messages = { }, z216 = { name = 'Abyssea - Misareaux', - offset = 7305, + offset = 7312, pearl_ebon_gold_silvery = 0, azure_ruby_amber = 1, visitant_status_update = 9, @@ -118,7 +118,7 @@ local messages = { }, z217 = { name = 'Abyssea - Vunkerl', - offset = 7305, + offset = 7312, pearl_ebon_gold_silvery = 0, azure_ruby_amber = 1, visitant_status_update = 9, @@ -135,7 +135,7 @@ local messages = { }, z218 = { name = 'Abyssea - Altepa', - offset = 7305, + offset = 7312, pearl_ebon_gold_silvery = 0, azure_ruby_amber = 1, visitant_status_update = 9, @@ -152,7 +152,7 @@ local messages = { }, z254 = { name = 'Abyssea - Grauberg', - offset = 7305, + offset = 7312, pearl_ebon_gold_silvery = 0, azure_ruby_amber = 1, visitant_status_update = 9, @@ -169,7 +169,7 @@ local messages = { }, z253 = { name = 'Abyssea - Uleguerand', - offset = 7210, + offset = 7212, pearl_ebon_gold_silvery = 0, azure_ruby_amber = 1, visitant_status_update = 9, From efada316d3173c5e554414d2a905b26547790b06 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Mon, 7 May 2018 16:27:00 -0400 Subject: [PATCH 0106/1002] Update fields.lua --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 53fa02149b..c7039e64f3 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1419,7 +1419,7 @@ fields.incoming[0x00E] = L{ {ctype='unsigned char', label='Status', fn=statuses}, -- 1F Status used to be 0x20 {ctype='unsigned int', label='_unknown2', fn=bin+{4}}, -- 20 {ctype='unsigned int', label='_unknown3', fn=bin+{4}}, -- 24 - {ctype='unsigned int', label='_unknown4', fn=bin+{4}}, -- 28 + {ctype='unsigned int', label='_unknown4', fn=bin+{4}}, -- 28 In Dynamis - Divergence statue's eye colors {ctype='unsigned int', label='Claimer', fn=id}, -- 2C {ctype='unsigned short', label='_unknown5'}, -- 30 {ctype='unsigned short', label='Model'}, -- 32 From 65bc92d12f194d6abecc5ac88a863d43c481f931 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Tue, 8 May 2018 22:32:25 -0400 Subject: [PATCH 0107/1002] Update export.lua --- addons/GearSwap/export.lua | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/addons/GearSwap/export.lua b/addons/GearSwap/export.lua index faccde247d..4ad8b96e51 100644 --- a/addons/GearSwap/export.lua +++ b/addons/GearSwap/export.lua @@ -26,7 +26,7 @@ function export_set(options) local item_list = T{} - local targinv,all_items,xml,all_sets,use_job_in_filename,use_subjob_in_filename,overwrite_existing + local targinv,all_items,xml,all_sets,use_job_in_filename,use_subjob_in_filename,overwrite_existing,named_file if #options > 0 then for _,v in ipairs(options) do if S{'inventory','inv','i'}:contains(v:lower()) then @@ -47,13 +47,19 @@ function export_set(options) use_subjob_in_filename = true elseif v:lower() == 'overwrite' then overwrite_existing = true + elseif S{'filename','file','f'}:contains(v:lower()) then + named_file = true + else + if named_file then + filename = v + end end end end local buildmsg = 'Exporting ' if all_items then - buildmsg = buildmsg..'your all items' + buildmsg = buildmsg..'all your items' elseif targinv then buildmsg = buildmsg..'your current inventory' elseif all_sets then @@ -61,6 +67,7 @@ function export_set(options) else buildmsg = buildmsg..'your currently equipped gear' end + if xml then buildmsg = buildmsg..' as an xml file.' else @@ -71,6 +78,8 @@ function export_set(options) buildmsg = buildmsg..' (Naming format: Character_JOB)' elseif use_subjob_in_filename then buildmsg = buildmsg..' (Naming format: Character_JOB_SUB)' + elseif named_file then + buildmsg = buildmsg..' (Named: Character_'..filename..')' end if overwrite_existing then @@ -158,6 +167,8 @@ function export_set(options) path = path..'_'..windower.ffxi.get_player().main_job elseif use_subjob_in_filename then path = path..'_'..windower.ffxi.get_player().main_job..'_'..windower.ffxi.get_player().sub_job + elseif named_file then + path = path..'_'..filename else path = path..os.date(' %Y-%m-%d %H-%M-%S') end From aea43b7dc4ff81cad86ab70c5fe390b36946a1a4 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Tue, 8 May 2018 22:38:50 -0400 Subject: [PATCH 0108/1002] Update version_history.txt --- addons/GearSwap/version_history.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/addons/GearSwap/version_history.txt b/addons/GearSwap/version_history.txt index 299312960e..9ae2c4c67f 100644 --- a/addons/GearSwap/version_history.txt +++ b/addons/GearSwap/version_history.txt @@ -1,4 +1,6 @@ ------------------------------------------------- +GearSwap 0.931 - Added support to exporting with custom file names. +------------------------------------------------- GearSwap 0.930 - Fixed a problem with player[bag][item_name].count in the user environment. ------------------------------------------------- GearSwap 0.929 - Adjusted the print_set function to give preference and order to slot name keys. @@ -223,4 +225,4 @@ GearSwap 0.502 - Require unmasked and documented. GearSwap 0.501 - File_unload user function added. ------------------------------------------------- GearSwap 0.500 - Initial beta release -------------------------------------------------- \ No newline at end of file +------------------------------------------------- From d82766da3ea8725a52dd2c0a61343fc5825d5e8d Mon Sep 17 00:00:00 2001 From: Chiaia Date: Tue, 8 May 2018 22:39:27 -0400 Subject: [PATCH 0109/1002] Update gearswap.lua --- addons/GearSwap/gearswap.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/GearSwap/gearswap.lua b/addons/GearSwap/gearswap.lua index f395000e14..159130fc9a 100644 --- a/addons/GearSwap/gearswap.lua +++ b/addons/GearSwap/gearswap.lua @@ -25,7 +25,7 @@ --SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'GearSwap' -_addon.version = '0.930' +_addon.version = '0.931' _addon.author = 'Byrth' _addon.commands = {'gs','gearswap'} @@ -331,4 +331,4 @@ windower.register_event('login',function(name) windower.debug('login '..name) initialize_globals() windower.send_command('@wait 2;lua i gearswap refresh_user_env;') -end) \ No newline at end of file +end) From c3440cea203a0b3e83e39568134e4e6e46c8b751 Mon Sep 17 00:00:00 2001 From: Snapsmojo Date: Thu, 10 May 2018 12:55:09 -0700 Subject: [PATCH 0110/1002] Updated craft addon create_recipes script to parse new bg-wiki Escutcheons page format. Updated craft addon recipes list with new recipes. Updated craft addon to handle spirit sphere recipes using emblem cards. --- addons/craft/craft.lua | 7 ++ addons/craft/create_recipes.py | 84 +++++++++++++---- addons/craft/recipes.lua | 161 ++++++++++++++++++++++----------- 3 files changed, 181 insertions(+), 71 deletions(-) diff --git a/addons/craft/craft.lua b/addons/craft/craft.lua index 3081a64f9e..a16488ce08 100644 --- a/addons/craft/craft.lua +++ b/addons/craft/craft.lua @@ -100,6 +100,13 @@ local support_npcs = { local exceptions = { ['Geo Crystal'] = 6509, + ['Fire Card'] : 9764, + ['Ice Card'] : 9765, + ['Wind Card'] : 9766, + ['Earth Card'] : 9767, + ['Water Card'] : 9769, + ['Light Card']: 9770, + ['Dark Card']: 9771, } local clusters = { diff --git a/addons/craft/create_recipes.py b/addons/craft/create_recipes.py index e1ba0b92f5..9a424ff667 100644 --- a/addons/craft/create_recipes.py +++ b/addons/craft/create_recipes.py @@ -2,8 +2,20 @@ from bs4 import BeautifulSoup from slpp import slpp as lua import os +import platform +hdr = { + 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11', + 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', + 'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3', + 'Accept-Encoding': 'none', + 'Accept-Language': 'en-US,en;q=0.8', + 'Connection': 'keep-alive', +} + +sphere = None + def get_recipe(row): crystals = [ 'Dark Crystal', @@ -40,35 +52,54 @@ def get_recipe(row): ingredients.append(english) else: ingredients.append(english) - return name, crystal, ingredients + return [(name, crystal, ingredients)] def get_sphere_recipe(row): - c, i, r = [ - td for td in row.findAll('td') + spheres = [ + 'Liquefaction Sphere', + 'Transfixion Sphere', + 'Detonation Sphere', + 'Impaction Sphere', + 'Induration Sphere', + 'Reverberation Sphere', + 'Scission Sphere', + 'Compression Sphere', ] - name = str(r.findAll('a')[0]['title']) + global sphere + cells = [td for td in row.findAll('td')] + if len(cells) > 4: + rare_ex, rare, ex, c, s = cells[:5] + if str(s.findAll('a')[0]['title']) in spheres: + sphere = str(s.findAll('a')[0]['title']) + else: + rare_ex, rare, ex, c = cells[:4] + recipes = [] crystal = str(c.findAll('img')[0]['alt']).rstrip(' icon.png') - ingredients = [str(i.findAll('a')[0]['title'])] - return name, crystal, ingredients + ingredients = [] + for cell in cells[:3]: + for a in cell.findAll('a'): + recipes.append((sphere, crystal, [str(a['title'])])) + return recipes def get_recipes_from_rows(rows, spheres=False): recipes = {} for row in rows: if spheres: - name, crystal, ingredients = get_sphere_recipe(row) + subrecipes = get_sphere_recipe(row) else: - name, crystal, ingredients = get_recipe(row) - while name in recipes.keys(): - if name[-1].isdigit(): - name = name[:-2] + (" %d" % (int(name[-1]) + 1)) - else: - name = name + " 2" - recipes[name] = [crystal, ingredients] + subrecipes = get_recipe(row) + for (name, crystal, ingredients) in subrecipes: + while name in recipes.keys(): + if name[-1].isdigit(): + name = name[:-2] + (" %d" % (int(name[-1]) + 1)) + else: + name = name + " 2" + recipes[name] = [crystal, ingredients] return recipes def get_recipes_from_soup(soup, spheres=False): - string = "Sphere Results" if spheres else "Synthesis Information" - count = 3 if spheres else 4 + string = "Sphere Obtained" if spheres else "Synthesis Information" + lengths = [4, 5, 6, 7] if spheres else [4] subtables = [ descendant.parent.parent.parent for descendant in soup.descendants @@ -80,13 +111,16 @@ def get_recipes_from_soup(soup, spheres=False): row for row in subtable.children if (hasattr(row, 'findAll') and - len(row.findAll('td')) == count) + len(row.findAll('td')) in lengths) ] rows.extend(children) return get_recipes_from_rows(rows, spheres) def get_items_dictionary(): - path = 'C:\\Program Files (x86)\\Windower4\\res\\items.lua' + if platform.system() == 'Windows': + path = 'C:\\Program Files (x86)\\Windower4\\res\\items.lua' + else: + path = os.path.join(os.path.expanduser("~"), 'Resources/lua/items.lua') with open(path) as fd: data = fd.read().replace('return', '', 1) return lua.decode(data) @@ -108,6 +142,14 @@ def get_items(): 'broken mithran rod' : 483, 'broken tarutaru rod' : 484, "broken lu shang's rod" : 489, + 'fire emblem card' : 9764, + 'ice emblem card' : 9765, + 'wind emblem card' : 9766, + 'earth emblem card' : 9767, + 'lightning emblem card': 9768, + 'water emblem card' : 9769, + 'light emblem card': 9770, + 'dark emblem card': 9771, } items = get_items_dictionary() inverted = {} @@ -171,7 +213,11 @@ def get_recipes(craft, spheres=False): base = "https://www.bg-wiki.com/bg/" name = "%s.html" % craft if not os.path.exists(name): - page = urllib2.urlopen(base + craft).read() + req = urllib2.Request(base + craft, headers=hdr) + try: + page = urllib2.urlopen(req).read() + except urllib2.HTTPError, e: + return with open(name, 'w') as fd: fd.write(page) with open(name, 'r') as fd: diff --git a/addons/craft/recipes.lua b/addons/craft/recipes.lua index cea2f6f7d0..cc844d626c 100644 --- a/addons/craft/recipes.lua +++ b/addons/craft/recipes.lua @@ -1073,13 +1073,6 @@ return { "Scintillant Ingot", }, }, - ["Amored Ring"] = { - ["crystal"] = "Wind Crystal", - ["ingredients"] = { - "Tgh. Dhal. Lth.", - "Leather Ring", - }, - }, ["Amphiptere Leather"] = { ["crystal"] = "Dark Crystal", ["ingredients"] = { @@ -1958,6 +1951,13 @@ return { "Shagreen File", }, }, + ["Armored Ring"] = { + ["crystal"] = "Wind Crystal", + ["ingredients"] = { + "Tgh. Dhal. Lth.", + "Leather Ring", + }, + }, ["Army Biscuit"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -6239,7 +6239,7 @@ return { }, }, ["Bronze Leggings 2"] = { - ["crystal"] = "Fire Crystal", + ["crystal"] = "Earth Crystal", ["ingredients"] = { "Bronze Sheet", "Bronze Sheet", @@ -8372,13 +8372,13 @@ return { ["Compression Sphere"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Colorful Hair", + "Demon Pen", }, }, ["Compression Sphere 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Demon Pen", + "Tonberry Board", }, }, ["Compression Sphere 3"] = { @@ -8390,7 +8390,13 @@ return { ["Compression Sphere 4"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Tonberry Board", + "Colorful Hair", + }, + }, + ["Compression Sphere 5"] = { + ["crystal"] = "Wind Crystal", + ["ingredients"] = { + "Dark Card", }, }, ["Console"] = { @@ -8977,6 +8983,14 @@ return { "Distilled Water", }, }, + ["Crayfish Ball 3"] = { + ["crystal"] = "Earth Crystal", + ["ingredients"] = { + "San d'Or. Flour", + "Distilled Water", + "Istakoz", + }, + }, ["Cream Puff"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -10652,13 +10666,31 @@ return { ["Detonation Sphere"] = { ["crystal"] = "Lightng. Crystal", ["ingredients"] = { - "Fetich Legs", + "Shoalweed", }, }, ["Detonation Sphere 2"] = { ["crystal"] = "Lightng. Crystal", ["ingredients"] = { - "Shoalweed", + "Fetich Legs", + }, + }, + ["Detonation Sphere 3"] = { + ["crystal"] = "Wind Crystal", + ["ingredients"] = { + "Soiled Letter", + }, + }, + ["Detonation Sphere 4"] = { + ["crystal"] = "Wind Crystal", + ["ingredients"] = { + "Beryl Memosphere", + }, + }, + ["Detonation Sphere 5"] = { + ["crystal"] = "Wind Crystal", + ["ingredients"] = { + "Wind Card", }, }, ["Devotee's Mitts"] = { @@ -15459,8 +15491,7 @@ return { ["ingredients"] = { "Bronze Ingot", "Bronze Ingot", - "Ash Lumber", - "Grass Cloth", + "Maple Lumber", }, }, ["Hatzoaar Sword"] = { @@ -17117,33 +17148,33 @@ return { }, }, ["Impaction Sphere"] = { - ["crystal"] = "Wind Crystal", + ["crystal"] = "Lightng. Crystal", ["ingredients"] = { - "Ancient Papyrus", + "Frayed Arrow", }, }, ["Impaction Sphere 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Beryl Memosphere", + "Ancient Papyrus", }, }, ["Impaction Sphere 3"] = { - ["crystal"] = "Lightng. Crystal", + ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Frayed Arrow", + "Star Spinel", }, }, ["Impaction Sphere 4"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Star Spinel", + "Test Answers", }, }, ["Impaction Sphere 5"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Test Answers", + "Lightning Card", }, }, ["Imperial Cermet"] = { @@ -17231,7 +17262,7 @@ return { ["Induration Sphere"] = { ["crystal"] = "Lightng. Crystal", ["ingredients"] = { - "Exoray Mold", + "Rusty Key", }, }, ["Induration Sphere 2"] = { @@ -17243,10 +17274,16 @@ return { ["Induration Sphere 3"] = { ["crystal"] = "Lightng. Crystal", ["ingredients"] = { - "Rusty Key", + "Exoray Mold", }, }, ["Induration Sphere 4"] = { + ["crystal"] = "Lightng. Crystal", + ["ingredients"] = { + "Ice Card", + }, + }, + ["Induration Sphere 5"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { "Teal Memosphere", @@ -19256,7 +19293,7 @@ return { "Distilled Water", }, }, - ["Leucos Voulge"] = { + ["Leucous Voulge"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { "Holly Lumber", @@ -19565,13 +19602,13 @@ return { ["Liquefaction Sphere"] = { ["crystal"] = "Lightng. Crystal", ["ingredients"] = { - "Ancient Salt", + "Bomb Coal", }, }, ["Liquefaction Sphere 2"] = { ["crystal"] = "Lightng. Crystal", ["ingredients"] = { - "Bomb Coal", + "Ancient Salt", }, }, ["Liquefaction Sphere 3"] = { @@ -19586,6 +19623,12 @@ return { "Rusty Medal", }, }, + ["Liquefaction Sphere 5"] = { + ["crystal"] = "Lightng. Crystal", + ["ingredients"] = { + "Fire Card", + }, + }, ["Lithic Wyvern Scale"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { @@ -22204,8 +22247,8 @@ return { ["Mythril Grip"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { - "Silver Ingot", - "Silver Ingot", + "Mythril Ingot", + "Mythril Ingot", "Mandrel", }, }, @@ -23994,6 +24037,12 @@ return { "Gold Lobster", }, }, + ["Peeled Lobster 2"] = { + ["crystal"] = "Wind Crystal", + ["ingredients"] = { + "Istakoz", + }, + }, ["Peiste Belt"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { @@ -24625,7 +24674,6 @@ return { ["Plastron"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { - "Iron Sheet", "Darksteel Sheet", "Darksteel Sheet", "Darksteel Chain", @@ -24633,6 +24681,7 @@ return { "Tiger Leather", "Tiger Leather", "Kunwu Iron", + "Kunwu Sheet", }, }, ["Plate Leggings"] = { @@ -25679,16 +25728,6 @@ return { "Rune Staff", }, }, - ["Raetic Staff 2"] = { - ["crystal"] = "Fire Crystal", - ["ingredients"] = { - "Fulfillment Crystal", - "Cypress Lumber", - "Cypress Lumber", - "Cypress Lumber", - "Rune Staff", - }, - }, ["Rainbow Cape"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -26532,16 +26571,22 @@ return { ["Reverberation Sphere 2"] = { ["crystal"] = "Lightng. Crystal", ["ingredients"] = { - "Desert Venom", + "Fetich Torso", }, }, ["Reverberation Sphere 3"] = { ["crystal"] = "Lightng. Crystal", ["ingredients"] = { - "Fetich Torso", + "Desert Venom", }, }, ["Reverberation Sphere 4"] = { + ["crystal"] = "Lightng. Crystal", + ["ingredients"] = { + "Water Card", + }, + }, + ["Reverberation Sphere 5"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { "Indigo Memosphere", @@ -28062,27 +28107,33 @@ return { }, }, ["Scission Sphere"] = { - ["crystal"] = "Wind Crystal", + ["crystal"] = "Lightng. Crystal", ["ingredients"] = { - "Elshimo Marble", + "Scorpion Stinger", }, }, ["Scission Sphere 2"] = { ["crystal"] = "Lightng. Crystal", ["ingredients"] = { - "Fetich Head", + "Magicked Steel", }, }, ["Scission Sphere 3"] = { ["crystal"] = "Lightng. Crystal", ["ingredients"] = { - "Magicked Steel", + "Fetich Head", }, }, ["Scission Sphere 4"] = { - ["crystal"] = "Lightng. Crystal", + ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Scorpion Stinger", + "Elshimo Marble", + }, + }, + ["Scission Sphere 5"] = { + ["crystal"] = "Wind Crystal", + ["ingredients"] = { + "Earth Card", }, }, ["Scope"] = { @@ -32782,7 +32833,7 @@ return { ["Transfixion Sphere"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Bruised Starfruit", + "Lucky Egg", }, }, ["Transfixion Sphere 2"] = { @@ -32794,13 +32845,19 @@ return { ["Transfixion Sphere 3"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Lucky Egg", + "White Memosphere", }, }, ["Transfixion Sphere 4"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "White Memosphere", + "Bruised Starfruit", + }, + }, + ["Transfixion Sphere 5"] = { + ["crystal"] = "Wind Crystal", + ["ingredients"] = { + "Light Card", }, }, ["Translucent Rock"] = { @@ -33269,7 +33326,7 @@ return { "Scintillant Ingot", }, }, - ["Ugol Solerets"] = { + ["Ugol Sollerets"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { "P. Brass Sheet", From 38ae6c7619ccda6ed2e1eae461c7022418deb529 Mon Sep 17 00:00:00 2001 From: Sjshovan Date: Tue, 22 May 2018 19:31:20 -0400 Subject: [PATCH 0111/1002] Add MountMuzzle addon --- addons/MountMuzzle/LICENSE | 25 ++++ addons/MountMuzzle/README.md | 94 ++++++++++++ addons/MountMuzzle/constants.lua | 98 ++++++++++++ addons/MountMuzzle/data/settings.xml | 6 + addons/MountMuzzle/helpers.lua | 80 ++++++++++ addons/MountMuzzle/mountmuzzle.lua | 213 +++++++++++++++++++++++++++ 6 files changed, 516 insertions(+) create mode 100644 addons/MountMuzzle/LICENSE create mode 100644 addons/MountMuzzle/README.md create mode 100644 addons/MountMuzzle/constants.lua create mode 100644 addons/MountMuzzle/data/settings.xml create mode 100644 addons/MountMuzzle/helpers.lua create mode 100644 addons/MountMuzzle/mountmuzzle.lua diff --git a/addons/MountMuzzle/LICENSE b/addons/MountMuzzle/LICENSE new file mode 100644 index 0000000000..a66131fcae --- /dev/null +++ b/addons/MountMuzzle/LICENSE @@ -0,0 +1,25 @@ +Copyright © 2018, Sjshovan (Apogee) +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 MountMuzzle 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 Patrick Finnigan 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. \ No newline at end of file diff --git a/addons/MountMuzzle/README.md b/addons/MountMuzzle/README.md new file mode 100644 index 0000000000..c4440bec6b --- /dev/null +++ b/addons/MountMuzzle/README.md @@ -0,0 +1,94 @@ +**Author:** Sjshovan (Apogee) +**Version:** v0.9.1 + +# Mount Muzzle + +Allows the user to change or remove the default mount music. + +___ +### Usage + +**Manually load** the addon by using the following command: + + //lua load mountmuzzle or //lua l mountmuzzle + +**Automatically load** this addon by adding one the above commands to the bottom of your `Windower4/scripts/init.txt` file. +___ +### Commands + +**help** + +Displays available Mount Muzzle commands. Below are the equivalent ways of calling the command: + + //mountmuzzle help + //muzzle help + //mm help + //mountmuzzle h + //muzzle h + //mm h + +**list** + +Displays the available muzzle types. Below are the equivalent ways of calling the command: + + //mountmuzzle list + //muzzle list + //mm list + +**set _\_** + +Sets the current muzzle to the given muzzle type. This command takes a single argument represented by ``. Below are the equivalent ways of calling the command: + + //mountmuzzle set + //muzzle set + //mm set + +Here are some usage examples for the **set _\_** command: `mm set silent` and `muzzle set zone` etc... + +**get** + +Displays the current muzzle that is set. Below are the equivalent ways of calling the command: + + //mountmuzzle get + //muzzle get + //mm get + +**default** + +Sets the current muzzle to the default muzzle type: `Silent`. Below are the equivalent ways of calling the command: + + //mountmuzzle default + //muzzle default + //mm default + +**reload** + +Reloads the Mount Muzzle addon. Below are the equivalent ways of calling the command: + + //mountmuzzle reload + //muzzle reload + //mm reload + +___ +### Change Log + +**v0.9.1** +- **Fix:** Chosen music does not start upon login if mounted. +- **Fix:** Chosen music does not persist upon changing zones. +- **Add:** Known issues added to README. +- **Add:** TODOS added to README. + +**v0.9.0** +- Initial release + +___ +### Known Issues + +**v0.9.1** +- **Issue:** If Mount Muzzle is selected to automatically load and the player is mounted upon login, there is a significant delay before the chosen music will begin to play. +- **Issue:** Upon changing zones the default music can be heard for a moment before the chosen music begins to play. + +___ +### TODOS + +- **Todo:** Investigate alternative methods for music change as packet injection/swap allows the player to hear the default music upon zone change and login, regardless of chosen music. \ No newline at end of file diff --git a/addons/MountMuzzle/constants.lua b/addons/MountMuzzle/constants.lua new file mode 100644 index 0000000000..0a646636a7 --- /dev/null +++ b/addons/MountMuzzle/constants.lua @@ -0,0 +1,98 @@ +--[[ +Copyright © 2018, Sjshovan (Apogee) +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 MountMuzzle 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 Patrick Finnigan 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. +]] + +packets = { + inbound = { + music_change = { + id = 0x05F + } + }, + outbound = { + action = { + id = 0x1A, + categories = { + mount = 0x1A, + unmount = 0x12 + }, + params = { + mount = 0x04, + unmount = 0x00 + } + } + }, +} + +player = { + statuses = { + mounted = 85 + } +} + +music = { + songs = { + silent = 90, + normal = 84, + choco = 212, + zone = 0, + }, + types = { + mount = 4 + } +} + +colors = { + primary = 200, + secondary = 207, + info = 0, + warn = 140, + danger = 167, + success = 158 +} + +muzzles = { + silent = { + name = 'silent', + song = music.songs.silent, + description = '' + }, + normal = { + name = 'normal', + song = music.songs.normal, + description = '' + }, + choco = { + name = 'choco', + song = music.songs.choco, + description = '' + }, + zone = { + name = 'zone', + song = music.songs.zone, + description = '' + } +} \ No newline at end of file diff --git a/addons/MountMuzzle/data/settings.xml b/addons/MountMuzzle/data/settings.xml new file mode 100644 index 0000000000..d71ef1b48d --- /dev/null +++ b/addons/MountMuzzle/data/settings.xml @@ -0,0 +1,6 @@ + + + + silent + + diff --git a/addons/MountMuzzle/helpers.lua b/addons/MountMuzzle/helpers.lua new file mode 100644 index 0000000000..9f25e727e8 --- /dev/null +++ b/addons/MountMuzzle/helpers.lua @@ -0,0 +1,80 @@ +--[[ +Copyright © 2018, Sjshovan (Apogee) +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 MountMuzzle 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 Patrick Finnigan 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. +]] + +require("constants") + +function ucFirst(str) + return (str:gsub("^%l", string.upper)) +end + +function buildHelpCommandEntry(command, description) + local short_name = "mm":color(colors.primary) + local command = command:color(colors.secondary) + local sep = "=>":color(colors.primary) + local description = description:color(colors.info) + return "%s %s %s %s":format(short_name, command, sep, description) +end + +function buildHelpTypeEntry(name, description) + local name = name:color(colors.secondary) + local sep = "=>":color(colors.primary) + local description = description:color(colors.info) + return "%s %s %s":format(name, sep, description) +end + +function buildHelpTitle(context) + local context = context:color(colors.danger) + return "%s Help: %s":color(colors.primary):format(_addon.name, context) +end + +function buildHelpSeperator(character, count) + local sep = '' + for i = 1, count do + sep = sep .. character + end + return sep:color(colors.warn) +end + +function buildCommandResponse(message, success) + local response_template = '%s: %s' + local response_color = colors.success + local response_type = 'Success' + + if not success then + response_type = 'Error' + response_color = colors.danger + end + return response_template:format(response_type:color(response_color), message) +end + +function displayResponse(response, color) + color = color or colors.info + windower.add_to_chat(color, response) + windower.console.write(response:strip_colors()) +end + diff --git a/addons/MountMuzzle/mountmuzzle.lua b/addons/MountMuzzle/mountmuzzle.lua new file mode 100644 index 0000000000..cbdf01a9fe --- /dev/null +++ b/addons/MountMuzzle/mountmuzzle.lua @@ -0,0 +1,213 @@ +--[[ +Copyright © 2018, Sjshovan (Apogee) +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 MountMuzzle 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 Patrick Finnigan 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.name = 'Mount Muzzle' +_addon.author = 'Sjshovan (Apogee) sjshovan@gmail.com' +_addon.version = '0.9.1' +_addon.commands = {'mountmuzzle', 'muzzle', 'mm'} + +local _logger = require('logger') +local _config = require('config') +local _packets = require('packets') + +require('helpers') + +local mounted = false +local needs_inject = false + +local defaults = { + muzzle = muzzles.silent.name +} + +local settings = _config.load(defaults) + +local help = { + commands = { + buildHelpSeperator('=', 26), + buildHelpTitle('Commands'), + buildHelpSeperator('=', 26), + buildHelpCommandEntry('list', 'Display the available muzzle types.'), + buildHelpCommandEntry('set ', 'Set the current muzzle to the given muzzle type.'), + buildHelpCommandEntry('get', 'Display the current muzzle.'), + buildHelpCommandEntry('default', 'Set the current muzzle to the default (Silent).'), + buildHelpCommandEntry('reload', 'Reload Mount Muzzle.'), + buildHelpCommandEntry('help', 'Display Mount Muzzle commands.'), + buildHelpSeperator('=', 26), + }, + + types = { + buildHelpSeperator('=', 23), + buildHelpTitle('Types'), + buildHelpSeperator('=', 23), + buildHelpTypeEntry(ucFirst(muzzles.silent.name), 'No Music (Default)'), + buildHelpTypeEntry(ucFirst(muzzles.normal.name), 'Original Music'), + buildHelpTypeEntry(ucFirst(muzzles.choco.name), 'Chocobo Music'), + buildHelpTypeEntry(ucFirst(muzzles.zone.name), 'Current Zone Music'), + buildHelpSeperator('=', 23), + }, +} + +function display_help(table_help) + for index, command in pairs(table_help) do + displayResponse(command) + end +end + +function getMuzzle() + return settings.muzzle +end + +function setMuzzle(muzzle) + settings.muzzle = muzzle + settings:save() +end + +function muzzleValid(muzzle) + return muzzles[muzzle] ~= nil +end + +function resolveCurrentMuzzle() + local current_muzzle = getMuzzle() + if not muzzleValid(current_muzzle) then + current_muzzle = muzzles.silent.name + setMuzzle(current_muzzle) + displayResponse( + 'Note: Muzzle found in settings was not valid and is now set to the default (%s).':format('Silent':color(colors.secondary)), + colors.warn + ) + end + return muzzles[current_muzzle] +end + +function requestInject() + needs_inject = true +end + +function injectMuzzleMusic() + windower.packets.inject_incoming( + packets.inbound.music_change.id, + 'IHH':pack(packets.inbound.music_change.id, + music.types.mount, + resolveCurrentMuzzle().song + ) + ) +end + +function handleInjectionNeeds() + if needs_inject and playerIsMounted() then + injectMuzzleMusic() + needs_inject = false; + end +end + +function playerIsMounted() + local _player = windower.ffxi.get_player() + if _player then + return mounted or _player.status == player.statuses.mounted + end + return false +end + +windower.register_event('login', requestInject) +windower.register_event('load', requestInject) +windower.register_event('zone change', requestInject) + +windower.register_event('addon command', function(command, ...) + local command = command:lower() + local command_args = {...} + + local respond = false + local response_message = '' + local success = true + + if command == 'list' then + display_help(help.types) + + elseif command == 'set' then + respond = true + + local muzzle = tostring (command_args[1]):lower() + + if not muzzleValid(muzzle) then + success = false + response_message = 'Muzzle type not recognized.' + else + needs_inject = true + setMuzzle(muzzle) + response_message = 'Updated current muzzle to %s.':format(ucFirst(muzzle):color(colors.secondary)) + end + + elseif command == 'get' then + respond = true + response_message = 'Current muzzle is %s.':format(ucFirst(getMuzzle()):color(colors.secondary)) + + elseif command == 'default' then + respond = true + needs_inject = true + + setMuzzle(muzzles.silent.name) + response_message = 'Updated current muzzle to the default (%s).':format('Silent':color(colors.secondary)) + + elseif command == 'reload' then + windower.send_command('lua r mountmuzzle') + + elseif command == 'help' or command == 'h' then + display_help(help.commands) + else + display_help(help.commands) + end + + if respond then + displayResponse( + buildCommandResponse(response_message, success) + ) + end + + handleInjectionNeeds() +end) + +windower.register_event('outgoing chunk', function(id, data) + if id == packets.outbound.action.id then + local packet = _packets.parse('outgoing', data) + if packet.Category == packets.outbound.action.categories.mount then + mounted = true + elseif packet.Category == packets.outbound.action.categories.unmount then + mounted = false + end + end +end) + +windower.register_event('incoming chunk', function(id, data) + if id == packets.inbound.music_change.id and playerIsMounted() then + local packet = _packets.parse('incoming', data) + packet['Song ID'] = resolveCurrentMuzzle().song + return _packets.build(packet) + end + + handleInjectionNeeds() +end) \ No newline at end of file From 173a8d90f53ae52d289dc7e8c0d1e374998088ac Mon Sep 17 00:00:00 2001 From: Byrth Date: Tue, 22 May 2018 22:14:54 -0400 Subject: [PATCH 0112/1002] GearSwap v0.932 Should fix a problem identifying worn gear by bag. --- addons/GearSwap/equip_processing.lua | 4 ++-- addons/GearSwap/gearswap.lua | 2 +- addons/GearSwap/version_history.txt | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/addons/GearSwap/equip_processing.lua b/addons/GearSwap/equip_processing.lua index 39c75beb70..bb6b861559 100644 --- a/addons/GearSwap/equip_processing.lua +++ b/addons/GearSwap/equip_processing.lua @@ -126,7 +126,7 @@ function unpack_equip_list(equip_list,cur_equip) local item_tab = items[to_windower_bag_api(res.bags[cur_equip[slot_name].bag_id].en)][cur_equip[slot_name].slot] if name_match(item_tab.id,name) and (not augments or (#augments ~= 0 and extdata.compare_augments(augments,extdata.decode(item_tab).augments))) and - (not bag or bag == cur_equip[slot_name].bag_id) then + (not designated_bag or designated_bag == cur_equip[slot_name].bag_id) then equip_list[slot_name] = nil used_list[slot_id] = {bag_id=cur_equip[slot_name].bag_id,slot=cur_equip[slot_name].slot} end @@ -154,7 +154,7 @@ function unpack_equip_list(equip_list,cur_equip) local name,priority,augments,designated_bag = expand_entry(equip_list[slot_name]) if (not designated_bag or designated_bag == bag.id) and name and name_match(item_tab.id,name) then - if augments and #augments ~=0 then + if augments and #augments ~= 0 then if res.items[item_tab.id].flags.Rare or extdata.compare_augments(augments,extdata.decode(item_tab).augments) then -- Check if the augments are right -- If the item is Rare, then even if the augments are wrong try to equip it anyway because you only have one diff --git a/addons/GearSwap/gearswap.lua b/addons/GearSwap/gearswap.lua index 159130fc9a..fc4e5f0f09 100644 --- a/addons/GearSwap/gearswap.lua +++ b/addons/GearSwap/gearswap.lua @@ -25,7 +25,7 @@ --SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'GearSwap' -_addon.version = '0.931' +_addon.version = '0.932' _addon.author = 'Byrth' _addon.commands = {'gs','gearswap'} diff --git a/addons/GearSwap/version_history.txt b/addons/GearSwap/version_history.txt index 9ae2c4c67f..715f56d31c 100644 --- a/addons/GearSwap/version_history.txt +++ b/addons/GearSwap/version_history.txt @@ -1,4 +1,6 @@ ------------------------------------------------- +GearSwap 0.932 - Fixed bug that prevented gearswap from identifying items by their bag when worn. +------------------------------------------------- GearSwap 0.931 - Added support to exporting with custom file names. ------------------------------------------------- GearSwap 0.930 - Fixed a problem with player[bag][item_name].count in the user environment. From dbb7d01f4fb932b6645760bd80261744d31b884a Mon Sep 17 00:00:00 2001 From: Ivaar <7287342+Ivaar@users.noreply.github.com> Date: Tue, 22 May 2018 23:10:58 -0700 Subject: [PATCH 0113/1002] Boxdestroyer: updated message ids --- addons/boxdestroyer/messages.lua | 116 +++++++++++++++---------------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/addons/boxdestroyer/messages.lua b/addons/boxdestroyer/messages.lua index 968133f33f..8bf36ffe49 100644 --- a/addons/boxdestroyer/messages.lua +++ b/addons/boxdestroyer/messages.lua @@ -1,61 +1,61 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination" for the associated zone IDs - [100] = 8057, - [101] = 7503, - [102] = 7908, - [103] = 8083, - [104] = 8648, - [105] = 7699, - [106] = 8073, - [107] = 7534, - [108] = 7603, - [109] = 8466, - [110] = 7590, - [111] = 8567, - [112] = 8169, - [113] = 7926, - [114] = 7768, - [115] = 7864, - [116] = 7560, - [117] = 7567, - [118] = 8109, - [119] = 8346, - [120] = 7506, - [121] = 8086, - [122] = 7432, - [123] = 7869, - [124] = 7820, - [125] = 7630, - [126] = 8053, - [127] = 7349, - [128] = 7504, - [130] = 7567, - [153] = 11393, - [158] = 7379, - [159] = 8442, - [160] = 7406, - [166] = 10576, - [167] = 10590, - [169] = 7536, - [172] = 7410, - [173] = 10515, - [174] = 11392, - [176] = 7601, - [177] = 11216, - [178] = 11397, - [190] = 8250, - [191] = 8370, - [192] = 7406, - [193] = 8382, - [194] = 8262, - [195] = 7593, - [196] = 8302, - [197] = 7347, - [198] = 8268, - [200] = 7524, - [204] = 7512, - [205] = 11479, - [208] = 8281, - [212] = 10636, - [213] = 10445, + [100] = 8058, + [101] = 7504, + [102] = 7909, + [103] = 8084, + [104] = 8649, + [105] = 7700, + [106] = 8074, + [107] = 7535, + [108] = 7604, + [109] = 8467, + [110] = 7591, + [111] = 8568, + [112] = 8170, + [113] = 7927, + [114] = 7769, + [115] = 7865, + [116] = 7561, + [117] = 7568, + [118] = 8110, + [119] = 8347, + [120] = 7507, + [121] = 8087, + [122] = 7433, + [123] = 7870, + [124] = 7821, + [125] = 7631, + [126] = 8054, + [127] = 7350, + [128] = 7505, + [130] = 7568, + [153] = 11394, + [158] = 7380, + [159] = 8443, + [160] = 7407, + [166] = 10577, + [167] = 10591, + [169] = 7537, + [172] = 7411, + [173] = 10516, + [174] = 11393, + [176] = 7602, + [177] = 11217, + [178] = 11398, + [190] = 8251, + [191] = 8371, + [192] = 7407, + [193] = 8383, + [194] = 8263, + [195] = 7594, + [196] = 8303, + [197] = 7348, + [198] = 8269, + [200] = 7525, + [204] = 7513, + [205] = 11480, + [208] = 8282, + [212] = 10637, + [213] = 10446, } offsets = {greater_less=1, failure=2, success=4, second_even_odd=5, first_even_odd=6, range=7, less=8, greater=9, equal=10, second_multiple=11, first_multiple=12} From 58629d4f2d864304bee22c9d99fa93236e9ce728 Mon Sep 17 00:00:00 2001 From: Byrth Date: Wed, 23 May 2018 06:22:45 -0400 Subject: [PATCH 0114/1002] spelling fix --- addons/GearSwap/gearswap.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/GearSwap/gearswap.lua b/addons/GearSwap/gearswap.lua index bd2f15147c..a14dcd971f 100644 --- a/addons/GearSwap/gearswap.lua +++ b/addons/GearSwap/gearswap.lua @@ -285,7 +285,7 @@ function incoming_chunk(id,data,modified,injected,blocked) refresh_globals() next_packet_events.globals_update = data:unpack('H',3) end - if next_packet_events.pet_status_change and not gearswap_disable then + if next_packet_events.pet_status_change and not gearswap_disabled then equip_sets('pet_status_change',nil,next_packet_events.pet_status_change.newstatus,next_packet_events.pet_status_change.oldstatus) next_packet_events.pet_status_change = nil end From ddb12b8387097bd5285d846c914d22c8dcb5c09c Mon Sep 17 00:00:00 2001 From: Sjshovan Date: Thu, 24 May 2018 14:27:49 -0400 Subject: [PATCH 0115/1002] Fix: Zone music gets silenced if player enters reive on mount with zone muzzle selected. Fix: Player reaches error if no arguments are given upon invoking the addon. Update: Convert tab characters to spaces, simplify code. Update: README Usage instructions updated. Update: README Known Issues updated. Add: Table of Contents added to README. Add: Prerequisites added to README. Add: Installation added to README. Add: Support added to README. Add: License added to README. --- addons/MountMuzzle/README.md | 81 ++++++++++++++++++++++++++---- addons/MountMuzzle/constants.lua | 18 +++---- addons/MountMuzzle/mountmuzzle.lua | 53 +++++++++++-------- 3 files changed, 109 insertions(+), 43 deletions(-) diff --git a/addons/MountMuzzle/README.md b/addons/MountMuzzle/README.md index c4440bec6b..901d5252b1 100644 --- a/addons/MountMuzzle/README.md +++ b/addons/MountMuzzle/README.md @@ -1,18 +1,46 @@ -**Author:** Sjshovan (Apogee) -**Version:** v0.9.1 +**Author:** [Sjshovan (Apogee)](https://github.com/Ap0gee) +**Version:** v0.9.2 + # Mount Muzzle -Allows the user to change or remove the default mount music. +> A Windower 4 addon that allows the user to change or remove the default mount music in Final Fantasy 11 Online. + + +### Table of Contents + +- [Prerequisites](#prerequisites) +- [Installation](#installation) +- [Usage](#usage) +- [Commands](#commands) +- [Support](#support) +- [Change Log](#change-log) +- [Known Issues](#known-issues) +- [TODOs](#todos) +- [License](#license) +___ +### Prerequisites +1. [Final Fantasy 11 Online](http://www.playonline.com/ff11us/index.shtml) +2. [Windower 4](http://windower.net/) + +___ +### Installation +1. Navigate to . +2. Click on `Releases`. +3. Click on the `Source code (zip)` link within the latest release to download. +4. Extract the zipped folder to `Windower4/addons/`. +5. Rename the folder to remove the version tag (`-v0.9.2`). The folder should be named `MountMuzzle`. + ___ ### Usage -**Manually load** the addon by using the following command: +**Manually load** the addon by using one of the following commands: - //lua load mountmuzzle or //lua l mountmuzzle + //lua load mountmuzzle + //lua l mountmuzzle -**Automatically load** this addon by adding one the above commands to the bottom of your `Windower4/scripts/init.txt` file. +**Automatically load** this addon by adding `lua load mountmuzzle` or `lua l mountmuzzle` to the bottom of your `Windower4/scripts/init.txt` file. ___ ### Commands @@ -69,26 +97,59 @@ Reloads the Mount Muzzle addon. Below are the equivalent ways of calling the com //muzzle reload //mm reload +___ +### Support +**Having Issues with this addon?** +* Please let me know [here.](https://github.com/Ap0gee/MountMuzzle/issues/new) + +**Have something to say?** +* Send me some feedback here: + +**Want to stay in the loop with my work?** +* You can follow me at: + +**Want to show your love and help me make more awesome stuff?** +* You can do so here: + ___ ### Change Log -**v0.9.1** +**v0.9.2** - 5/24/2018 +- **Fix:** Zone music gets silenced if player enters reive on mount with zone muzzle selected. +- **Fix:** Player reaches error if no arguments are given upon invoking the addon. +- **Update:** Convert tab characters to spaces, simplify code. +- **Update:** README Usage instructions updated. +- **Update:** README Known Issues updated. +- **Add:** Table of Contents added to README. +- **Add:** Prerequisites added to README. +- **Add:** Installation added to README. +- **Add:** Support added to README. +- **Add:** License added to README. + +**v0.9.1** - 5/22/2018 - **Fix:** Chosen music does not start upon login if mounted. - **Fix:** Chosen music does not persist upon changing zones. - **Add:** Known issues added to README. - **Add:** TODOS added to README. -**v0.9.0** +**v0.9.0** - 5/21/2018 - Initial release ___ ### Known Issues -**v0.9.1** - **Issue:** If Mount Muzzle is selected to automatically load and the player is mounted upon login, there is a significant delay before the chosen music will begin to play. - **Issue:** Upon changing zones the default music can be heard for a moment before the chosen music begins to play. ___ ### TODOS -- **Todo:** Investigate alternative methods for music change as packet injection/swap allows the player to hear the default music upon zone change and login, regardless of chosen music. \ No newline at end of file +- **Todo:** Investigate alternative methods for music change as packet injection/swap allows the player to hear the default music upon zone change and login, regardless of chosen music. +___ + +### License + +Copyright © 2018, [Sjshovan (Apogee)](https://github.com/Ap0gee). +Released under the [BSD License](LICENSE). + +*** \ No newline at end of file diff --git a/addons/MountMuzzle/constants.lua b/addons/MountMuzzle/constants.lua index 0a646636a7..9aa9d35f3d 100644 --- a/addons/MountMuzzle/constants.lua +++ b/addons/MountMuzzle/constants.lua @@ -39,18 +39,14 @@ packets = { mount = 0x1A, unmount = 0x12 }, - params = { - mount = 0x04, - unmount = 0x00 - } } }, } player = { - statuses = { - mounted = 85 - } + statuses = { + mounted = 85 + } } music = { @@ -78,21 +74,21 @@ muzzles = { silent = { name = 'silent', song = music.songs.silent, - description = '' + description = 'No Music (Default)' }, normal = { name = 'normal', song = music.songs.normal, - description = '' + description = 'Original Music' }, choco = { name = 'choco', song = music.songs.choco, - description = '' + description = 'Chocobo Music' }, zone = { name = 'zone', song = music.songs.zone, - description = '' + description = 'Current Zone Music' } } \ No newline at end of file diff --git a/addons/MountMuzzle/mountmuzzle.lua b/addons/MountMuzzle/mountmuzzle.lua index cbdf01a9fe..de7a7dd764 100644 --- a/addons/MountMuzzle/mountmuzzle.lua +++ b/addons/MountMuzzle/mountmuzzle.lua @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'Mount Muzzle' _addon.author = 'Sjshovan (Apogee) sjshovan@gmail.com' -_addon.version = '0.9.1' +_addon.version = '0.9.2' _addon.commands = {'mountmuzzle', 'muzzle', 'mm'} local _logger = require('logger') @@ -64,10 +64,10 @@ local help = { buildHelpSeperator('=', 23), buildHelpTitle('Types'), buildHelpSeperator('=', 23), - buildHelpTypeEntry(ucFirst(muzzles.silent.name), 'No Music (Default)'), - buildHelpTypeEntry(ucFirst(muzzles.normal.name), 'Original Music'), - buildHelpTypeEntry(ucFirst(muzzles.choco.name), 'Chocobo Music'), - buildHelpTypeEntry(ucFirst(muzzles.zone.name), 'Current Zone Music'), + buildHelpTypeEntry(ucFirst(muzzles.silent.name), muzzles.silent.description), + buildHelpTypeEntry(ucFirst(muzzles.normal.name), muzzles.normal.description), + buildHelpTypeEntry(ucFirst(muzzles.choco.name), muzzles.choco.description), + buildHelpTypeEntry(ucFirst(muzzles.zone.name), muzzles.zone.description), buildHelpSeperator('=', 23), }, } @@ -119,18 +119,18 @@ function injectMuzzleMusic() end function handleInjectionNeeds() - if needs_inject and playerIsMounted() then - injectMuzzleMusic() - needs_inject = false; + if needs_inject and playerIsMounted() then + injectMuzzleMusic() + needs_inject = false; end end function playerIsMounted() - local _player = windower.ffxi.get_player() - if _player then - return mounted or _player.status == player.statuses.mounted - end - return false + local _player = windower.ffxi.get_player() + if _player then + return mounted or _player.status == player.statuses.mounted + end + return false end windower.register_event('login', requestInject) @@ -138,7 +138,13 @@ windower.register_event('load', requestInject) windower.register_event('zone change', requestInject) windower.register_event('addon command', function(command, ...) - local command = command:lower() + if command then + local command = command:lower() + else + display_help(help.commands) + return + end + local command_args = {...} local respond = false @@ -188,11 +194,11 @@ windower.register_event('addon command', function(command, ...) ) end - handleInjectionNeeds() + handleInjectionNeeds() end) windower.register_event('outgoing chunk', function(id, data) - if id == packets.outbound.action.id then + if id == packets.outbound.action.id then local packet = _packets.parse('outgoing', data) if packet.Category == packets.outbound.action.categories.mount then mounted = true @@ -202,12 +208,15 @@ windower.register_event('outgoing chunk', function(id, data) end end) -windower.register_event('incoming chunk', function(id, data) - if id == packets.inbound.music_change.id and playerIsMounted() then - local packet = _packets.parse('incoming', data) - packet['Song ID'] = resolveCurrentMuzzle().song - return _packets.build(packet) - end +windower.register_event('incoming chunk', function(id, data) + if id == packets.inbound.music_change.id and playerIsMounted() then + local packet = _packets.parse('incoming', data) + + if packet['BGM Type'] == music.types.mount then + packet['Song ID'] = resolveCurrentMuzzle().song + return _packets.build(packet) + end + end handleInjectionNeeds() end) \ No newline at end of file From 08e67294147767d28d70b2580627487011761ac9 Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 24 May 2018 20:03:50 -0400 Subject: [PATCH 0116/1002] Merge commit '4f0b024' into live --- addons/boxdestroyer/messages.lua | 116 +++++++++++++++---------------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/addons/boxdestroyer/messages.lua b/addons/boxdestroyer/messages.lua index 968133f33f..8bf36ffe49 100644 --- a/addons/boxdestroyer/messages.lua +++ b/addons/boxdestroyer/messages.lua @@ -1,61 +1,61 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination" for the associated zone IDs - [100] = 8057, - [101] = 7503, - [102] = 7908, - [103] = 8083, - [104] = 8648, - [105] = 7699, - [106] = 8073, - [107] = 7534, - [108] = 7603, - [109] = 8466, - [110] = 7590, - [111] = 8567, - [112] = 8169, - [113] = 7926, - [114] = 7768, - [115] = 7864, - [116] = 7560, - [117] = 7567, - [118] = 8109, - [119] = 8346, - [120] = 7506, - [121] = 8086, - [122] = 7432, - [123] = 7869, - [124] = 7820, - [125] = 7630, - [126] = 8053, - [127] = 7349, - [128] = 7504, - [130] = 7567, - [153] = 11393, - [158] = 7379, - [159] = 8442, - [160] = 7406, - [166] = 10576, - [167] = 10590, - [169] = 7536, - [172] = 7410, - [173] = 10515, - [174] = 11392, - [176] = 7601, - [177] = 11216, - [178] = 11397, - [190] = 8250, - [191] = 8370, - [192] = 7406, - [193] = 8382, - [194] = 8262, - [195] = 7593, - [196] = 8302, - [197] = 7347, - [198] = 8268, - [200] = 7524, - [204] = 7512, - [205] = 11479, - [208] = 8281, - [212] = 10636, - [213] = 10445, + [100] = 8058, + [101] = 7504, + [102] = 7909, + [103] = 8084, + [104] = 8649, + [105] = 7700, + [106] = 8074, + [107] = 7535, + [108] = 7604, + [109] = 8467, + [110] = 7591, + [111] = 8568, + [112] = 8170, + [113] = 7927, + [114] = 7769, + [115] = 7865, + [116] = 7561, + [117] = 7568, + [118] = 8110, + [119] = 8347, + [120] = 7507, + [121] = 8087, + [122] = 7433, + [123] = 7870, + [124] = 7821, + [125] = 7631, + [126] = 8054, + [127] = 7350, + [128] = 7505, + [130] = 7568, + [153] = 11394, + [158] = 7380, + [159] = 8443, + [160] = 7407, + [166] = 10577, + [167] = 10591, + [169] = 7537, + [172] = 7411, + [173] = 10516, + [174] = 11393, + [176] = 7602, + [177] = 11217, + [178] = 11398, + [190] = 8251, + [191] = 8371, + [192] = 7407, + [193] = 8383, + [194] = 8263, + [195] = 7594, + [196] = 8303, + [197] = 7348, + [198] = 8269, + [200] = 7525, + [204] = 7513, + [205] = 11480, + [208] = 8282, + [212] = 10637, + [213] = 10446, } offsets = {greater_less=1, failure=2, success=4, second_even_odd=5, first_even_odd=6, range=7, less=8, greater=9, equal=10, second_multiple=11, first_multiple=12} From ab3766d4d362b6c706672c0469e6e578f8333346 Mon Sep 17 00:00:00 2001 From: Byrth Date: Sun, 27 May 2018 06:14:22 -0400 Subject: [PATCH 0117/1002] Add to Shortcuts --- addons/shortcuts/statics.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/shortcuts/statics.lua b/addons/shortcuts/statics.lua index 52ae8c601f..f8c6b1791c 100644 --- a/addons/shortcuts/statics.lua +++ b/addons/shortcuts/statics.lua @@ -169,13 +169,13 @@ ignore_list = {['equip']=true,['raw']=true,['fish']=true,['dig']=true,['range']= -- Targets to ignore and just pass through pass_through_targs = T{'','','','','','','','','','','','','', - '','','','','','','','','','','','',''} + '','','','','','','','','','','','','',''} st_targs = T{'','','','',''} targ_reps = {t='',me='',ft='',scan='',bt='',lastst='',r='',pet='',p0='',p1='',p2='',p3='',p4='', p5='',a10='',a11='',a12='',a13='',a14='',a15='',a20='',a21='',a22='',a23='',a24='',a25='', - st='',stpc='',stal='',stnpc='',stpt=''} + st='',stpc='',stal='',stnpc='',stpt='',focust=''} language = 'english' -- windower.ffxi.get_info()['language']:lower() From c6221a909a569cae44b9ca59ab8b518dc6589bc6 Mon Sep 17 00:00:00 2001 From: Byrth Date: Sun, 27 May 2018 07:26:15 -0400 Subject: [PATCH 0118/1002] GearSwap v0.933 - Adjust item use packets. --- addons/GearSwap/flow.lua | 5 ++++- addons/GearSwap/gearswap.lua | 2 +- addons/GearSwap/triggers.lua | 7 +++++-- addons/GearSwap/version_history.txt | 2 ++ 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/addons/GearSwap/flow.lua b/addons/GearSwap/flow.lua index 45a0387e7c..1856e6cc6d 100644 --- a/addons/GearSwap/flow.lua +++ b/addons/GearSwap/flow.lua @@ -252,7 +252,10 @@ function equip_sets_exit(swap_type,ts,val1) if val1.target and val1.target.id and val1.target.index and val1.prefix and unify_prefix[val1.prefix] then if val1.prefix == '/item' then -- Item use packet handling here - if find_usable_item(val1.id,true) then --val1.target.id == player.id then + if val1.target.spawn_type == 2 then + --0x36 packet + command_registry[ts].proposed_packet = assemble_menu_item_packet(val1.target.id,val1.target.index,val1.id) + elseif find_usable_item(val1.id,true) then --val1.target.id == player.id then --0x37 packet command_registry[ts].proposed_packet = assemble_use_item_packet(val1.target.id,val1.target.index,val1.id) else diff --git a/addons/GearSwap/gearswap.lua b/addons/GearSwap/gearswap.lua index a14dcd971f..6cbf69c4ae 100644 --- a/addons/GearSwap/gearswap.lua +++ b/addons/GearSwap/gearswap.lua @@ -25,7 +25,7 @@ --SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'GearSwap' -_addon.version = '0.932' +_addon.version = '0.933' _addon.author = 'Byrth' _addon.commands = {'gs','gearswap'} diff --git a/addons/GearSwap/triggers.lua b/addons/GearSwap/triggers.lua index eecaf81ebe..b9b361adb7 100644 --- a/addons/GearSwap/triggers.lua +++ b/addons/GearSwap/triggers.lua @@ -96,7 +96,7 @@ windower.register_event('outgoing text',function(original,modified,blocked,ffxi, end return line end - + if unified_prefix == '/ma' then r_line = copy_entry(res.spells[validabils[language][unified_prefix][abil]]) storedcommand = command..' "'..windower.to_shift_jis(r_line[language])..'" ' @@ -135,7 +135,10 @@ windower.register_event('outgoing text',function(original,modified,blocked,ffxi, if spell.prefix == '/item' then -- Item use packet handling here - if find_usable_item(spell.id,true) then + if spell.target.spawn_type == 2 then + --0x36 packet + command_registry[ts].proposed_packet = assemble_menu_item_packet(spell.target.id,spell.target.index,spell.id) + elseif find_usable_item(spell.id,true) then --0x37 packet command_registry[ts].proposed_packet = assemble_use_item_packet(spell.target.id,spell.target.index,spell.id) else diff --git a/addons/GearSwap/version_history.txt b/addons/GearSwap/version_history.txt index 715f56d31c..623bfedc58 100644 --- a/addons/GearSwap/version_history.txt +++ b/addons/GearSwap/version_history.txt @@ -1,4 +1,6 @@ ------------------------------------------------- +GearSwap 0.933 - Adjusted how item use packets are chosen. +------------------------------------------------- GearSwap 0.932 - Fixed bug that prevented gearswap from identifying items by their bag when worn. ------------------------------------------------- GearSwap 0.931 - Added support to exporting with custom file names. From defce40bb909e5faa8277315136eb4725447584b Mon Sep 17 00:00:00 2001 From: Byrth Date: Mon, 28 May 2018 08:44:06 -0400 Subject: [PATCH 0119/1002] slips.lua - Updated slip 22, added 26 and 27 I think this makes it current. --- addons/libs/slips.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 00bc8d3018..a2ffbe3515 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,10 +34,12 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757}, -- 191 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453,}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454,}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678}, -- 38 + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725}, -- 69 : Cornelia Statue is the last [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25589, 25762, 25763, 25810, 25811, 25869, 25870, 25935, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, }, --160 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330,}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665,}, --115 + [slips.storages[26]] = L{23063, 23130, 23197, 23264, 23331, 23064, 23131, 23198, 23265, 23332, 23065, 23132, 23199, 23266, 23333, 23066, 23133, 23200, 23267, 23334, 23067, 23134, 23201, 23268, 23335, 23068, 23135, 23202, 23269, 23336, 23069, 23136, 23203, 23270, 23337, 23070, 23137, 23204, 23271, 23338, 23071, 23138, 23205, 23272, 23339, 23072, 23139, 23206, 23273, 23340, 23073, 23140, 23207, 23274, 23341, 23074, 23141, 23208, 23274, 23342, 23075, 23142, 23209, 23276, 23343, 23076, 23143, 23210, 23277, 23344, 23077, 23144, 23211, 23278, 23345, 23078, 23145, 23212, 23279, 23346, 23079, 23146, 23213, 23280, 23347, 23080, 23147, 23214, 23281, 23348, 23081, 23148, 23215, 23282, 23349, 23082, 23149, 23216, 23283, 23350, 23083, 23150, 23217, 23284, 23351, 23084, 23151, 23218, 23285, 23352,}, --110 + [slips.storages[27]] = L{23398, 23465, 23532, 23599, 23666, 23399, 23466, 23533, 23600, 23667, 23400, 23467, 23534, 23601, 23668, 23401, 23468, 23535, 23602, 23669, 23402, 23469, 23536, 23603, 23670, 23403, 23470, 23537, 23604, 23671, 23404, 23471, 23538, 23605, 23672, 23405, 23472, 23539, 23606, 23673, 23406, 23473, 23540, 23607, 23674, 23407, 23474, 23541, 23608, 23675, 23408, 23475, 23542, 23609, 23676, 23409, 23476, 23543, 23610, 23677, 23410, 23477, 23544, 23611, 23678, 23411, 23478, 23545, 23612, 23679, 23412, 23479, 23546, 23613, 23680, 23413, 23480, 23547, 23614, 23681, 23414, 23481, 23548, 23615, 23682, 23415, 23482, 23549, 23616, 23683, 23416, 23483, 23550, 23617, 23684, 23417, 23484, 23551, 23618, 23685, 23418, 23485, 23552, 23619, 23686, 23419, 23486, 23553, 23620, 23687,}, --110 } function slips.get_slip_id(n) From 05669059df15235f00ff4dac66852a6681b26e69 Mon Sep 17 00:00:00 2001 From: Mark Date: Tue, 29 May 2018 09:12:22 -0400 Subject: [PATCH 0120/1002] Slips: New slip IDs --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index a2ffbe3515..3135d79a1d 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -11,7 +11,7 @@ _libs.slips = slips slips.default_storages = {'inventory', 'safe', 'storage', 'locker', 'satchel', 'sack', 'case', 'wardrobe', 'safe2'} -slips.storages = L{29312, 29313, 29314, 29315, 29316, 29317, 29318, 29319, 29320, 29321, 29322, 29323, 29324, 29325, 29326, 29327, 29328, 29329, 29330, 29331, 29332, 29333, 29334, 29335, 29336,} +slips.storages = L{29312, 29313, 29314, 29315, 29316, 29317, 29318, 29319, 29320, 29321, 29322, 29323, 29324, 29325, 29326, 29327, 29328, 29329, 29330, 29331, 29332, 29333, 29334, 29335, 29336, 29337, 29338,} slips.items = { [slips.storages[1]] = L{16084, 14546, 14961, 15625, 15711, 16085, 14547, 14962, 15626, 15712, 16086, 14548, 14963, 15627, 15713, 16087, 14549, 14964, 15628, 15714, 16088, 14550, 14965, 15629, 15715, 16089, 14551, 14966, 15630, 15716, 16090, 14552, 14967, 15631, 15717, 16091, 14553, 14968, 15632, 15718, 16092, 14554, 14969, 15633, 15719, 16093, 14555, 14970, 15634, 15720, 16094, 14556, 14971, 15635, 15721, 16095, 14557, 14972, 15636, 15722, 16096, 14558, 14973, 15637, 15723, 16097, 14559, 14974, 15638, 15724, 16098, 14560, 14975, 15639, 15725, 16099, 14561, 14976, 15640, 15726, 16100, 14562, 14977, 15641, 15727, 16101, 14563, 14978, 15642, 15728, 16102, 14564, 14979, 15643, 15729, 16103, 14565, 14980, 15644, 15730, 16106, 14568, 14983, 15647, 15733, 16107, 14569, 14984, 15648, 15734, 16108, 14570, 14985, 15649, 15735, 16602, 17741, 18425, 18491, 18588, 18717, 18718, 18850, 18943, 16069, 14530, 14940, 15609, 15695, 16062, 14525, 14933, 15604, 15688, 16064, 14527, 14935, 15606, 15690, 18685, 18065, 17851, 18686, 18025, 18435, 18113, 17951, 17715, 18485, 18408, 18365, 18583, 18417, 18388, 16267, 16268, 16269, 16228, 16229, 15911, 15799, 15800, 15990, 17745, 18121, 16117, 14577, 17857}, -- 168 [slips.storages[2]] = L{12421, 12549, 12677, 12805, 12933, 13911, 14370, 14061, 14283, 14163, 12429, 12557, 12685, 12813, 12941, 13924, 14371, 14816, 14296, 14175, 13934, 14387, 14821, 14303, 14184, 13935, 14388, 14822, 14304, 14185, 13876, 13787, 14006, 14247, 14123, 13877, 13788, 14007, 14248, 14124, 13908, 14367, 14058, 14280, 14160, 13909, 14368, 14059, 14281, 14161, 16113, 14573, 14995, 15655, 15740, 16115, 14575, 14997, 15657, 15742, 16114, 14574, 14996, 15656, 15741, 16116, 14576, 14998, 15658, 15743, 12818, 18198, 12946, 18043, 12690, 17659, 12296, 12434, 15471, 15472, 15473, 15508, 15509, 15510, 15511, 15512, 15513, 15514, 17710, 17595, 18397, 18360, 18222, 17948, 18100, 15475, 15476, 15477, 15488, 15961, 14815, 14812, 14813, 15244, 15240, 14488, 14905, 15576, 15661, 15241, 14489, 14906, 15577, 15662, 13927, 14378, 14076, 14308, 14180, 13928, 14379, 14077, 14309, 14181, 10438, 10276, 10320, 10326, 10367, 10439, 10277, 10321, 10327, 10368, 10440, 10278, 10322, 10328, 10369, 10441, 10279, 10323, 10329, 10370}, -- 144 From f1ea7c1cc6399cd19fd3602d075befafbfde3627 Mon Sep 17 00:00:00 2001 From: from20020516 Date: Wed, 30 May 2018 04:08:30 +0900 Subject: [PATCH 0121/1002] update checkparam.lua --- addons/addons.xml | 9 +- addons/checkparam/README.md | 27 ++- addons/checkparam/checkparam.lua | 358 ++++++++++++++++------------ addons/checkparam/data/settings.xml | 26 -- 4 files changed, 234 insertions(+), 186 deletions(-) delete mode 100644 addons/checkparam/data/settings.xml diff --git a/addons/addons.xml b/addons/addons.xml index 5bc38003ff..77daf0a798 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -697,4 +697,11 @@ https://github.com/Snapsmojo/Lua/issues http://www.ffxiah.com/player/Fenrir/Snaps - + + Checkparam + Centurio a.k.a. from20020516 + Displays the total of property of current equipments. + https://github.com/from20020516/Lua/issues + https://twitter.com/from20020516 + + \ No newline at end of file diff --git a/addons/checkparam/README.md b/addons/checkparam/README.md index 2eee217d40..7e67284f02 100644 --- a/addons/checkparam/README.md +++ b/addons/checkparam/README.md @@ -1,11 +1,18 @@ # checkparam - - //cp - - 装備中アイテムの任意のプロパティを合計して表示します。 - - displays the total of optional properties of the item being equipped. - - //cp debug - - 装備中アイテムの全てのプロパティを装備ごとに表示します。 - - displays all the properties of the item being equipped for each equipment. -## settings.xml - - 表示させるプロパティをジョブごとに定義します。 - - define the properties to be displayed for each job. - - || 改行/new line starts \ No newline at end of file + +- `/check` OR `/c` (in-game command) + - 「調べる」したとき、対象が装備しているアイテムのうち任意のプロパティを合計して表示します。 + - whenever you /check any player, displays the total of property of current equipments.(defined in `setting.xml`) + +## data/settings.xml (auto-generated) +- 表示させるプロパティをジョブごとに定義します。 + - `|` 区切り記号 divide each property + - `NON`は/anon時に使用 + - 召喚獣: 飛竜: オートマトン: 羅盤: などペットに関するプロパティは全て`pet: `で指定します。 + + +- Checkparam uses `setting.xml` to define the properties you want to be displayed. + - You can define the properties for each job. + - `NON` means target status is /anon + - `pet: ` define properties for all pets, which means avatar,wyvern,automaton,luopan. +- If there’s something wrong,or something strange,please tell me on Twitter [@from20020516](https://twitter.com/from20020516) **with simple English**. Thank you! diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua index 34f0b2bb26..c72673932b 100644 --- a/addons/checkparam/checkparam.lua +++ b/addons/checkparam/checkparam.lua @@ -1,150 +1,3 @@ -_addon.name = 'checkparam' -_addon.author = 'from20020516' -_addon.version = '1.0' -_addon.commands = {'cp','checkparam'} -res,extdata,config = require('resources'),require('extdata'),require('config') -settings = config.load('data/settings.xml') -function key_define() - job_define = settings[windower.ffxi.get_player().main_job:lower()] - return job_define and windower.regex.split(job_define,'[|]') - or {'store tp','quadruple attack','triple attack','double attack','', - 'magic accuracy','fast cast','haste','dual wield','', - 'magic attack bonus','magic burst damage','magic damage','', - 'enmity','cure potency'} -end -function split_text(txt,id,arg) - for key,value in string.gmatch(txt,"/?([%D]-):?([%+%-]?[0-9]+)%%?%s?") do - local key = windower.regex.replace(string.lower(key),'(\\"|\\.|\\s$)','') - local key = integrate[key] or key - local key = arg and arg..key or key - tbl[key] = tonumber(value) + (tbl[key] or 0) - if debug then - local color = windower.regex.match(key,'enhanced') and 170 - windower.add_to_chat(color or 72,'['..id..']'..res.items[id].en..'['..key..'] '..value..' '..tbl[key]) - end - end -end -function checkparam(arg1) - debug = arg1=='debug' - tbl,txt={}, - windower.send_command('input /checkparam ') - for slot,bag in pairs(windower.ffxi.get_items().equipment) do - gtbl = windower.ffxi.get_items().equipment - if not string.find(slot,'_bag') then - gear = windower.ffxi.get_items(gtbl[slot..'_bag'],gtbl[slot]) - if gtbl[slot] > 0 and gear.id < 65535 then - if res.item_descriptions[gear.id] then - local txt = windower.regex.split(res.item_descriptions[gear.id].en,"(Pet|Avatar|Automaton|Wyvern|Luopan): ") - for i,v in pairs(windower.regex.split(txt[1],"\n")) do - split_text(v,gear.id) - end - if txt[2] then - local txt = windower.regex.replace(txt[2],'\n',' ') - split_text(txt,gear.id,'pet: ') - end - end - if gear.extdata and extdata.decode(gear).type == 'Augmented Equipment' then - for slot,augment in pairs(extdata.decode(gear).augments) do - split_text(augment,gear.id) - end - end - if enhanced[res.items[gear.id].en] then - local txt = string.split(string.gsub(enhanced[res.items[gear.id].en], "([+-:][0-9]+)",",%1"),",") - tbl[txt[1]] = tonumber(txt[2]) + (tbl[txt[1]] or 0) - if debug then - windower.add_to_chat(170,'['..gear.id..']'..res.items[gear.id].en..'['..txt[1]..'] '..txt[2]..' '..tbl[txt[1]]) - end - end - end - end - end - windower.add_to_chat(69, '//checkparam') - for index,key in pairs(key_define()) do - txt = key == '' and txt..'\n' or (txt or '')..'['..key..'] '..(tbl[string.lower(key)] or 0)..' ' - end - windower.add_to_chat(70, txt) - collectgarbage() -end -integrate={ ---[[integrate same property.information needed for development. @from20020516]] -['quad atk']='quadruple attack', -['triple atk']='triple attack', -['double atk']='double attack', -['dblatk']='double attack', -['blood pact ability delay']='blood pact delay', -['blood pact ability delay ii']='blood pact delay ii', -['blood pact ab. del. ii']='blood pact delay ii', -['blood pact recast time ii']='blood pact delay ii', -['blood pact dmg']='blood pact damage', -['enhancing magic duration']='enhancing magic effect duration', -['eva']='evasion', -['indicolure spell duration']='indicolure effect duration', -['mag eva']='magic evasion', -['magic atk bonus']='magic attack bonus', -['magatkbns']='magic attack bonus', -['mag atk bonus']='magic attack bonus', -['mag acc']='magic accuracy', -['magic burst dmg']='magic burst damage', -['mag dmg']='magic damage', -['crithit rate']='critical hit rate', -} -enhanced={ -['Anhur Robe']='fast cast+10', -['Atinian Staff +1']='fast cast+2', -['Brutal Earring']='double attack+5', -['Charis Necklace']='dual wield+3', -['Cirque Necklace']='martial arts+10', -['Cizin Helm']='fast cast+5', -['Conveyance Cape']='elemental siphon+30', -['Debilis Medallion']='cursna+15', -['Earthcry Earring']='stoneskin+10', -['Eirene\'s Manteel']='fast cast+10', -['Emphatikos Rope']='aquaveil+1', -['Ephedra Ring']='cursna+10', -['Estq. Earring']='fast cast+2', -['Excelsis Ring']='drain and aspir potency+5', -['Ferine Earring']='rewards+2', -['Gende. Galoshes']='cursna+10', -['Gendewitha Gages']='fast cast+7', -['Geomancy Pants']='fast cast+10', -['Haoma\'s Ring']='cursna+15', -['Hearty Earring']='increases resistance to all status ailments+5', -['Iga Mimikazari']='dual wield+1', -['Impulse Belt']='snapshot+3', -['Kenkonken']='martial arts+55', -['Lifestream Cape']='fast cast+7', -['Locus Ring']='magic burst damage+5', -['Loquac. Earring']='fast cast+2', -['Majorelle Shield']='fast cast+5', -['Malison Medallion']='cursna+10', -['Manibozho Gloves']='snapshot+4', -['Mending Cape']='cursna+15', -['Nahtirah Hat']='fast cast+10', -['Nahtirah Trousers']='snapshot+9', -['Navarch\'s Mantle']='snapshot+5', -['Nusku\'s Sash']='dual wield+5', -['Oneiros Rope']='occult acumen+20', -['Orison Locket']='fast cast+5', -['Orunmila\'s Torque']='fast cast+5', -['Orvail Pants +1']='fast cast+5', -['Patentia Sash']='dual wield+5', -['Prolix Ring']='fast cast+2', -['Raider\'s Bmrng.']='dual wield+3', -['Static Earring']='magic burst damage+5', -['Savant\'s Earring']='sublimation+1', -['Shaolin Belt']='martial arts+10', -['Siegel Sash']='stoneskin+20', -['Spharai']='counter+14', -['Stone Gorget']='stoneskin+30', -['Suppanomimi']='dual wield+5', -['Swith Cape +1']='fast cast+4', -['Swith Cape']='fast cast+3', -['Veela Cape']='fast cast+1', -['Witful Belt']='fast cast+3', -['Yagrush']='divine benison+3', -} -windower.register_event('addon command', checkparam) -windower.send_command('cp') --[[ Copyright © 2018, from20020516 All rights reserved. @@ -170,5 +23,212 @@ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 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. -]] \ No newline at end of file +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.]] + +_addon.name = 'Checkparam' +_addon.author = 'from20020516' +_addon.version = '1.1' +_addon.commands = {'cp','checkparam'} + +require('logger') +res = require('resources') +extdata = require('extdata') +config = require('config') +packets = require('packets') + +defaults = { + NON = 'fast cast', + WAR = 'store tp|double attack|triple attack|quadruple attack|weapon skill damage', + MNK = 'store tp|double attack|triple attack|quadruple attack|martial arts|subtle blow', + WHM = 'cure potency|cure potency ii|fast cast|cure spellcasting time|enmity|healing magic casting time|divine benison|damage taken|physical damage taken|magic damage taken', + BLM = 'magic attack bonus|magic burst damage|magic burst damage ii|int|magic accuracy|magic damage|fast cast|elemental magic casting time', + RDM = 'magic attack bonus|magic burst damage|magic burst damage ii|magic accuracy|fast cast|enfeebling magic skill|enhancing magic skill|store tp|dual wield', + THF = 'store tp|double attack|triple attack|quadruple attack|dual wield', + PLD = 'enmity|damage taken|physical damage taken|magic damage taken|spell inturruption rate|pharanx|cure potency|fastcast', + DRK = 'store tp|double attack|triple attack|quadruple attack|weapon skill damage', + BST = 'pet: double attack|pet: magic attack bonus|pet: damage taken', + BRD = 'all songs|song effect duration|fast cast|song spellcasting time', + RNG = 'store tp|snapshot|rapid shot|weapon skill damage', + SAM = 'store tp|double attack|triple attack|quadruple attack|weapon skill damage', + NIN = 'store tp|double attack|triple attack|quadruple attack|subtle blow', + DRG = 'store tp|double attack|triple attack|quadruple attack|weapon skill damage', + SMN = 'blood pact delay|blood pact delay ii|blood pact damage|avatar perpetuation cost|pet: magic attack bonus|pet: str|pet: double attack', + BLU = 'store tp|double attack|triple attack|quadruple attack|critical hit rate|critical hit damage|weapon skill damage|fast cast|magic attack bonus|magic accuracy|cure potency', + COR = 'store tp|snapshot|rapid shot|fast cast|cure potency|magic accuracy|magic attack bonus|magic damage|weapon skill damage', + PUP = 'pet: hp|pet: damage taken|pet: regen|martial arts|store tp|double attack|triple attack|quadruple attack', + DNC = 'store tp|double attack|triple attack|quadruple attack', + SCH = 'magic attack bonus|magic burst damage|magic burst damage ii|magic accuracy|magic damage|fast cast|elemental magic casting time|cure potency|enh mag eff dur|enhancing magic effect duration', + GEO = 'pet: regen|pet: damage taken|indicolure effect duration|indi eff dur|fast cast|magic evasion', + RUN = 'enmity|damage taken|physical damage taken|magic damage taken|spell inturruption rate|pharanx|inquartata|fastcast', + debugmode = false, +} +settings = config.load(defaults) + +tbl = {} + +windower.register_event('incoming chunk',function(id,data) + if id == 0x0C9 then + local p = packets.parse('incoming',data) + if p['Type'] == 3 then + local count = p['Count'] + if count == 1 then + get_text(p['Item'],p['ExtData']) + else + for i=1,count do + get_text(p['Item '..i],p['ExtData '..i]) + end + end + elseif p['Type'] == 1 then --metadata + local t = windower.ffxi.get_mob_by_id(p['Target ID']) + local mjob = res.jobs[p['Main Job']].ens + local sjob = res.jobs[p['Sub Job']].ens + show_results(t.name,mjob,sjob) + end + end +end) + +function get_text(id,data) + config.reload(settings) + local descriptions = res.item_descriptions[id] + local helptext = descriptions and descriptions.english or '' --for 'vanilla' items. e.g. Moonshade Earring + local stats = windower.regex.split(helptext,'(Pet|Avatar|Automaton|Wyvern|Luopan): ') + for i,v in ipairs(windower.regex.split(stats[1],'\n')) do + split_text(id,v) + end + if stats[2] then + local pet_text = windower.regex.replace(stats[2],'\n',' ') + split_text(id,pet_text,'pet: ') + end + local ext = extdata.decode({id=id,extdata=data}) + if ext.augments then + for i,v in ipairs(ext.augments) do + split_text(id,v) + end + end + if enhanced[id] then + local stats = enhanced[id]:gsub('([+-:][0-9]+)',',%1'):split(',') + tbl[stats[1]] = tonumber(stats[2]) + (tbl[stats[1]] or 0) + if settings.debugmode then + log(id,res.items[id].english,stats[1],stats[2],tbl[stats[1]]) + end + end +end + +function split_text(id,text,arg) + for key,value in string.gmatch(text,'/?([%D]-):?([%+%-]?[0-9]+)%%?%s?') do + local key = windower.regex.replace(string.lower(key),'(\\"|\\.|\\s$)','') + local key = integrate[key] or key + local key = arg and arg..key or key + tbl[key] = tonumber(value) + (tbl[key] or 0) + if settings.debugmode then + log(id,res.items[id].english,key,value,tbl[key]) + end + end +end + +function show_results(name,mjob,sjob) + local stats = settings[mjob] + local head = '<'..mjob..'/'..sjob..'>' + windower.add_to_chat(160,string.color(name,1,160)..': '..string.color(head,160,160)) + if mjob == 'NON' then + notice('Unknown job because /anon state. instead display .') + end + for index,key in ipairs(windower.regex.split(stats,'[|]')) do + local value = tbl[string.lower(key)] + local color = {value and 1 or 160,value and 166 or 160} + windower.add_to_chat(160,' ['..string.color(key,color[1],160)..'] '..string.color(tostring(value),color[2],160)) + end + tbl = {} + collectgarbage() +end + +windower.register_event('load',function() + print('Checkparam: Activate with in-game /check command.') +end) + +integrate = { + --[[integrate same property.information needed for development. @from20020516]] + ['quad atk'] = 'quadruple attack', + ['triple atk'] = 'triple attack', + ['double atk'] = 'double attack', + ['dblatk'] = 'double attack', + ['blood pact ability delay'] = 'blood pact delay', + ['blood pact ability delay ii'] = 'blood pact delay ii', + ['blood pact ab. del. ii'] = 'blood pact delay ii', + ['blood pact recast time ii'] = 'blood pact delay ii', + ['blood pact dmg'] = 'blood pact damage', + ['enhancing magic duration'] = 'enhancing magic effect duration', + ['eva'] = 'evasion', + ['indicolure spell duration'] = 'indicolure effect duration', + ['mag eva'] = 'magic evasion', + ['magic atk bonus'] = 'magic attack bonus', + ['magatkbns'] = 'magic attack bonus', + ['mag atk bonus'] = 'magic attack bonus', + ['mag acc'] = 'magic accuracy', + ['magic burst dmg'] = 'magic burst damage', + ['mag dmg'] = 'magic damage', + ['crithit rate'] = 'critical hit rate', +} +enhanced = { + [10392] = 'cursna+10', --Malison Medallion + [10393] = 'cursna+15', --Debilis Medallion + [10394] = 'fast cast+5', --Orunmila's Torque + [10469] = 'fast cast+10', --Eirene's Manteel + [10752] = 'fast cast+2', --Prolix Ring + [10790] = 'cursna+10', --Ephedra Ring + [10791] = 'cursna+15', --Haoma's Ring + [10802] = 'fast cast+5', --Majorelle Shield + [10826] = 'fast cast+3', --Witful Belt + [10838] = 'dual wield+5', --Patentia Sash + [11000] = 'fast cast+3', --Swith Cape + [11001] = 'fast cast+4', --Swith Cape +1 + [11037] = 'stoneskin+10', --Earthcry Earring + [11051] = 'increases resistance to all status ailments+5', ----Hearty Earring + [11544] = 'fast cast+1', --Veela Cape + [11602] = 'martial arts+10', --Cirque Necklace + [11603] = 'dual wield+3', --Charis Necklace + [11615] = 'fast cast+5', --Orison Locket + [11707] = 'fast cast+2', --Estq. Earring + [11711] = 'rewards+2', --Ferine Earring + [11715] = 'dual wield+1', --Iga Mimikazari + [11722] = 'sublimation+1', --Savant's Earring + [11732] = 'dual wield+5', --Nusku's Sash + [11734] = 'martial arts+10', --Shaolin Belt + [11735] = 'snapshot+3', --Impulse Belt + [11753] = 'aquaveil+1', --Emphatikos Rope + [11775] = 'occult acumen+20', --Oneiros Rope + [11856] = 'fast cast+10', --Anhur Robe + [13177] = 'stoneskin+30', --Stone Gorget + [14739] = 'dual wield+5', --Suppanomimi + [14812] = 'fast cast+2', --Loquac. Earring + [14813] = 'double attack+5', --Brutal Earring + [15857] = 'drain and aspir potency+5', --Excelsis Ring + [15960] = 'stoneskin+20', --Siegel Sash + [15962] = 'magic burst damage+5', --Static Earring + [16209] = 'snapshot+5', --Navarch's Mantle + [19062] = 'divine benison+1', --Yagrush80 + [19082] = 'divine benison+2', --Yagrush85 + [19260] = 'dual wield+3', --Raider's Bmrng. + [19614] = 'divine benison+3', --Yagrush90 + [19712] = 'divine benison+3', --Yagrush95 + [19821] = 'divine benison+3', --Yagrush99 + [19950] = 'divine benison+3', --Yagrush99+ + [20509] = 'counter+14', --Spharai119AG + [20511] = 'martial arts+55', --Kenkonken119AG + [21062] = 'divine benison+3', --Yagrush119 + [21063] = 'divine benison+3', --Yagrush119+ + [21078] = 'divine benison+3', --Yagrush119AG + [21201] = 'fast cast+2', --Atinian Staff +1 + [27768] = 'fast cast+5', --Cizin Helm + [27775] = 'fast cast+10', --Nahtirah Hat + [28054] = 'fast cast+7', --Gendewitha Gages + [28058] = 'snapshot+4', --Manibozho Gloves + [28184] = 'fast cast+5', --Orvail Pants +1 + [28197] = 'snapshot+9', --Nahtirah Trousers + [28206] = 'fast cast+10', --Geomancy Pants + [28335] = 'cursna+10', --Gende. Galoshes + [28582] = 'magic burst damage+5', --Locus Ring + [28619] = 'cursna+15', --Mending Cape + [28631] = 'elemental siphon+30', --Conveyance Cape + [28637] = 'fast cast+7', --Lifestream Cape +} diff --git a/addons/checkparam/data/settings.xml b/addons/checkparam/data/settings.xml deleted file mode 100644 index d22453ebed..0000000000 --- a/addons/checkparam/data/settings.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - store tp|double attack|triple attack|quadruple attack||weapon skill damage - store tp|double attack|triple attack|quadruple attack||martial arts|subtle blow - cure potency|cure potency ii|fast cast|cure spellcasting time||enmity|healing magic casting time|divine benison||damage taken|physical damage taken|magic damage taken - magic attack bonus|magic burst damage|magic burst damage ii||int|magic accuracy|magic damage||fast cast|elemental magic casting time - store tp|double attack|triple attack|quadruple attack||dual wield - enmity|damage taken|physical damage taken|magic damage taken||spell inturruption rate|pharanx|cure potency|fastcast - store tp|double attack|triple attack|quadruple attack||weapon skill damage - pet: double attack|pet: magic attack bonus|pet: damage taken - all songs|song effect duration|fast cast|song spellcasting time - store tp|snapshot|rapid shot|weapon skill damage - store tp|double attack|triple attack|quadruple attack||weapon skill damage - store tp|double attack|triple attack|quadruple attack||subtle blow - store tp|double attack|triple attack|quadruple attack||weapon skill damage - blood pact delay|blood pact delay ii|blood pact damage||avatar perpetuation cost|pet: magic attack bonus|pet: str|pet: double attack - store tp|double attack|triple attack|quadruple attack||critical hit rate|critical hit damage|weapon skill damage||fast cast|magic attack bonus|magic accuracy|cure potency - store tp|snapshot|rapid shot|fast cast|cure potency||magic accuracy|magic attack bonus|magic damage|weapon skill damage - pet: hp|pet: damage taken|pet: regen|martial arts||store tp|double attack|triple attack|quadruple attack - store tp|double attack|triple attack|quadruple attack|| - magic attack bonus|magic burst damage|magic burst damage ii||magic accuracy|magic damage|fast cast|elemental magic casting time||cure potency|enh mag eff dur|enhancing magic effect duration - pet: regen|pet: damage taken|indicolure effect duration|indi eff dur||fast cast|magic evasion - enmity|damage taken|physical damage taken|magic damage taken||spell inturruption rate|pharanx|inquartata|fastcast - - \ No newline at end of file From 0950dec32d872123775aa93988563c919f500d38 Mon Sep 17 00:00:00 2001 From: from20020516 Date: Wed, 30 May 2018 13:06:00 +0900 Subject: [PATCH 0122/1002] initial commit --- addons/Bonanza/Bonanza.lua | 195 +++++++++++++++++++++++++++++++++++++ addons/Bonanza/README.md | 27 +++++ addons/addons.xml | 9 +- 3 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 addons/Bonanza/Bonanza.lua create mode 100644 addons/Bonanza/README.md diff --git a/addons/Bonanza/Bonanza.lua b/addons/Bonanza/Bonanza.lua new file mode 100644 index 0000000000..46086d5158 --- /dev/null +++ b/addons/Bonanza/Bonanza.lua @@ -0,0 +1,195 @@ +--[[ +Copyright © 2018, from20020516 +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 checkparam 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 from20020516 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.name = 'Bonanza' +_addon.author = 'from20020516' +_addon.version = '1.1' +_addon.command = 'bonanza' + +extdata = require('extdata') +packets = require('packets') +require('logger') + +marble = {id=2559,price=2000,limit=10} --general settings + +win_numbers = {} +math.randomseed(os.time()) + +--search your bags for bonanza marble and get number then add prefix 0 +function search_marbles() + local marbles = {} + local bags = {0,1,2,4,5,6,7,9} + for bag_ind=1,#bags do + for index=1,windower.ffxi.get_bag_info(bags[bag_ind]).max do + local item = windower.ffxi.get_items(bags[bag_ind],index) + if item.id == marble.id then --bonanza marble + local five_digits = string.format("%05s",extdata.decode(item).number) + table.insert(marbles,{bags[bag_ind],index,five_digits}) + end + end + end + return marbles; +end + +windower.register_event('addon command',function(...) + moogle = windower.ffxi.get_mob_by_name('Bonanza Moogle') + decides = {} + local cmd={...} + local count = marble.limit-#search_marbles() + + for i=1,#cmd do + math.random() --shuffle rand + cmd[i] = tonumber(cmd[i]) and cmd[i]*1 or cmd[i] + end + + if cmd[1] == 'judge' then + windower.send_command('input /smes') + elseif count == 0 then + error('you have already '..marble.limit..' marbles.') + elseif cmd[1] == 'random' then + for i=1,count do + table.insert(decides,math.random(0,99999)) + end + elseif cmd[1] == 'sequence' then + local n = math.min(cmd[2],10000-count) + for i=n,n+count-1 do + table.insert(decides,i) + end + elseif cmd[1] == 'last' and 10 > cmd[2] then + for i=1,count do + table.insert(decides,tonumber(math.random(0,9999)..cmd[2])) + end + elseif 100000 > cmd[2] and not cmd[marble.limit+1] then + decides = cmd + end + + if #decides > 0 then + talk_moogle() + end +end) + +function talk_moogle() + --print(unpack(decides)) + if #decides > 0 then + hide_ui = true + local packet = packets.new('outgoing',0x01A,{ + ["Target"]=moogle.id, + ["Target Index"]=moogle.index, + ["Category"]=0, + ["Param"]=0, + ["_unknown1"]=0}) + packets.inject(packet) + end +end + +windower.register_event('incoming chunk',function(id,data) + --got a marble. + if id == 0x020 and hide_ui and data:unpack('H',0x0D) == marble.id and data:unpack('C',0x0F) == 0 then + local item = windower.ffxi.get_items(0,data:unpack('C',0x10)) + if extdata.decode(item).number == decides[1] then + hide_ui = false + table.remove(decides,1) + talk_moogle() + end + --responced to talk. + elseif id == 0x034 and hide_ui and data:unpack('I',0x05) == moogle.id then + if moogle.distance > 36 then + error('not close enough to Bonanza Moogle.') + elseif marble.price > windower.ffxi.get_items().gil then + error('not have enough gils.') + else + local packet = packets.new('outgoing',0x05B) + local i = decides[1] + log('Purchase a Bonanza Marble #'..string.format("%05s",i)) + --packet part 1 + packet["Target"]=moogle.id + packet["Option Index"]=2+i%256*256 + packet["Target Index"]=moogle.index + packet["Automated Message"]=true + packet["_unknown1"]=(i-i%256)/256 + packet["_unknown2"]=0 + packet["Zone"]=data:unpack('H',0x2B) + packet["Menu ID"]=data:unpack('H',0x2D) + packets.inject(packet) + --packet part 2 + packet["Option Index"]=3 + packet["_unknown1"]=0 + packet["Automated Message"]=false + packets.inject(packet) + return true; --hide ui + end + end +end) + +--get winning numbers(str) from /smes. +windower.register_event('incoming text',function(original,modified,mode) + local jis = windower.from_shift_jis(original) --valid in english environment + if mode == 200 and windower.regex.match(jis,'digit|けた') then + local numbers = windower.regex.match(jis,'["「]([0-9]+)[」"]')[1][1] + table.insert(win_numbers,6-string.len(numbers),numbers) + if #win_numbers == 5 then + scan_marbles() + end + end +end) + +function scan_marbles() + log('Winning numbers is..',unpack(win_numbers)) + local marbles = search_marbles() + local colors = {51,18,166,207,208,161} + for m=1,#marbles do + local number = marbles[m][3] + if S{1,2,4,9}[marbles[m][1]] and windower.ffxi.get_info().mog_house + or S{5,6,7}[marbles[m][1]] then + windower.ffxi.get_item(marbles[m][1],marbles[m][2]) + end + for r=1,5 do + local text = _addon.name..': #'..string.format("%02s",m)..' '..number..' ') + break; + elseif r == 5 then + windower.add_to_chat(colors[6],text..'6'..'>') + end + end + end +end + +--[[ +windower.add_to_chat(200,windower.to_shift_jis('5等 下1けた「3」 当せん個数「83,350」個')) +windower.add_to_chat(200,windower.to_shift_jis('4等 下2けた「08」 当せん個数「8,287」個')) +windower.add_to_chat(200,windower.to_shift_jis('3等 下3けた「723」 当せん個数「914」個')) +windower.add_to_chat(200,windower.to_shift_jis('2等 下4けた「8940」 当せん個数「71」個')) +windower.add_to_chat(200,windower.to_shift_jis('1等 全5けた「66621」 当せん個数「7」個')) +]] +--[[ +windower.add_to_chat(200,'Rank 5 prize: "3" (last digit)-- 83,350 winners.') +windower.add_to_chat(200,'Rank 4 prize: "08" (last two digits)-- 8,287 winners.') +windower.add_to_chat(200,'Rank 3 prize: "723" (last three digits)-- 914 winners.') +windower.add_to_chat(200,'Rank 2 prize: "8940" (last four digits)-- 71 winners.') +windower.add_to_chat(200,'Rank 1 prize: "66621" (all five digits)-- 7 winners.') +]] diff --git a/addons/Bonanza/README.md b/addons/Bonanza/README.md new file mode 100644 index 0000000000..b4be251662 --- /dev/null +++ b/addons/Bonanza/README.md @@ -0,0 +1,27 @@ +# Bonanza + +- Judge your Bonanza Marbles. activate with when you recive system message (/smes) with winning numbers. +- Purchase Bonanza Marbles with any combination of numbers. + +#### Japanese + +- モグボナンザの当せんを判定。当せん番号を含むシステムメッセージ (/smes) を受信するとボナンザマーブルを鑑定し、結果を出力します。 +- 任意の数字の組み合わせでボナンザマーブルを購入します。 + +## Commands + +- //bonanza judge + - same as in-game /smes. + +### Purchase marble (inject packets) + +- //bonanza `` `[number]`... + - purchase specified marble(s). +- //bonanza random + - purchase up to 10 marbles with at random. +- //bonanza sequence `` + - purchase up to 10 marbles with consecutive number. + - e.g. `15250` then buying 15250 to 15259. +- //bonanza last `` + - purchase up to 10 random marbles with tail of specified `0-9`. + - e.g. `0` then 2224**0**, 6231**0**, 4586**0**, 9078**0**... diff --git a/addons/addons.xml b/addons/addons.xml index 5bc38003ff..4af0135282 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -697,4 +697,11 @@ https://github.com/Snapsmojo/Lua/issues http://www.ffxiah.com/player/Fenrir/Snaps - + + Bonanza + Centurio a.k.a. from20020516 + Judge your Bonanza Marble. + https://github.com/from20020516/Lua/issues + https://twitter.com/from20020516 + + \ No newline at end of file From 7fd9eefd7791c95415fba86ef3231d0669f74a98 Mon Sep 17 00:00:00 2001 From: from20020516 Date: Wed, 30 May 2018 13:09:50 +0900 Subject: [PATCH 0123/1002] update addons.xml --- addons/addons.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/addons.xml b/addons/addons.xml index 77daf0a798..6d39253fc3 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -700,8 +700,8 @@ Checkparam Centurio a.k.a. from20020516 - Displays the total of property of current equipments. + Displays the total of property of target player's current equipments. https://github.com/from20020516/Lua/issues https://twitter.com/from20020516 - \ No newline at end of file + From 3aab4c0a90f3ee85e082d3b8d408dc0400c26b84 Mon Sep 17 00:00:00 2001 From: from20020516 Date: Wed, 30 May 2018 13:16:49 +0900 Subject: [PATCH 0124/1002] initial commit --- addons/Trusts/README.md | 33 ++++ addons/Trusts/Trusts.lua | 338 +++++++++++++++++++++++++++++++++++++++ addons/addons.xml | 7 + 3 files changed, 378 insertions(+) create mode 100644 addons/Trusts/README.md create mode 100644 addons/Trusts/Trusts.lua diff --git a/addons/Trusts/README.md b/addons/Trusts/README.md new file mode 100644 index 0000000000..a6e7765fa3 --- /dev/null +++ b/addons/Trusts/README.md @@ -0,0 +1,33 @@ +# Trusts + +- //tru save `` : Save trusts in current party. +- //tru `` : Calls trusts you saved. +- //tru random : What's your fortune today? +- //tru check : List of unlearned trusts. gotta catch 'em all! + +### 使い方 + +- //tru save `` + - 呼び出し中のフェイスをセットに保存(セット名は半角英字) +- //tru `` + - 保存したセットのフェイスを召喚 + - 呼び出し先と"同枠"のフェイスは戻す + - 既にPTにいる場合は戻さない = 倒れたフェイスの補充が可能 + - リキャストが不足している場合は戻さない +- //tru random + - フェイスガチャ。PT枠上限までランダムで召喚 +- //tru check + - 未習得フェイスを表示 + +### data/settings.xml (auto-generated) +- language : `` OR `` +- auto : `true` OR `false` + - 登録フェイスを全て自動で呼び出すか、1体ごとに1クリックするか選択 +- wait + - ユーザーのPC環境に応じて長くする。ファストキャストは無関係 + - aftercast : `number` + - 詠唱完了から次の詠唱までの待機時間。初期値3秒 + - retr : `number` + - フェイスを戻したあと次の詠唱までの待機時間。初期値1.25秒 + - retrall : `number` + - フェイスを全て戻したあと次の詠唱までの待機時間。初期値3秒 diff --git a/addons/Trusts/Trusts.lua b/addons/Trusts/Trusts.lua new file mode 100644 index 0000000000..d840698cd5 --- /dev/null +++ b/addons/Trusts/Trusts.lua @@ -0,0 +1,338 @@ +--[[ +Copyright © 2018, from20020516 +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 checkparam 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 from20020516 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.name='Trusts' +_addon.author='from20020516' +_addon.version='1.1' +_addon.commands={'trusts','tru'} + +config = require('config') +math = require('math') +math.randomseed(os.clock()) +require('logger') + +windower.register_event('load',function() + defaults = { + auto=true, + language=windower.ffxi.get_info().language, + sets={ + ['default']={ + English={ + ['1']='Valaineral', + ['2']='Mihli Aliapoh', + ['3']='Tenzen', + ['4']='Adelheid', + ['5']='Joachim'}, + Japanese={ + ['1']='ヴァレンラール', + ['2']='ミリ・アリアポー', + ['3']='テンゼン', + ['4']='アーデルハイト', + ['5']='ヨアヒム'}}[windower.ffxi.get_info().language]}, + wait={ + ['aftercast']=3, + ['retr']=1.25, + ['retrall']=3},} + settings = config.load(defaults) + lang = string.lower(settings.language) +end) + +windower.register_event('addon command',function(...) + cmd = {...} + if S{'save','s'}[cmd[1]] then + save_set(cmd[2]) + elseif S{'check','c'}[cmd[1]] then + check_learned() + else + call_set(cmd[1] or 'default') + end +end) + +function save_set(set) + settings.sets[set] = {} + local trust_ind = 0 + for i=1,5 do + local trust = windower.ffxi.get_party()['p'..i] + if trust and trust.mob.spawn_type == 14 then + trust_ind = trust_ind + 1 + settings.sets[set][tostring(trust_ind)]=trusts:with('models',trust.mob.models[1])[lang] + end + end + settings:save('all') + log('set '..set..' saved.') +end + +function check_lang(entity) + return {japanese=entity.japanese,english=entity.english}[lang]; +end + +function check_limit() + for i,v in pairs(windower.ffxi.get_key_items()) do + --Trust permit,Rhapsody in.. + limit = S{2497,2499,2501}[v] and 3 or v==2884 and 4 or v==2886 and 5 or limit or 0 + end + return limit; +end + +function call_trust() + if #queue > 0 then + windower.send_command('input /ma "'..windower.to_shift_jis(check_lang(queue[1]))..'" ') + end +end + +function check_exist() + local party = {} --include only trusts. --['name']=models + local party_ind = {} -- index of trust's name in current party. {'name1','name2',...,'name5'} + for i=1,5 do + local member = windower.ffxi.get_party()['p'..i] + if member then + if member.mob.spawn_type == 14 then + party[member.name]= member.mob.models[1] + table.insert(party_ind,member.name) + end + end + end + return {party,party_ind}; +end + +function call_set(set) + queue = {} --trusts to be cast. + settings = config.load() + local party,party_ind = unpack(check_exist()) + local limit = check_limit() --upper limit # of calls trust in current player. + local time = os.clock() --window open + + if set == 'random' then + local checked = {} + local others = windower.ffxi.get_party().party1_count - #party_ind - 1 --# of human in party exept . + + if limit == #party_ind then + windower.send_command('input /retr all') + calls = limit + coroutine.sleep(settings.wait.retrall) + else + calls = limit - #party_ind - others + end + + repeat + local index = trusts[math.random(1,#trusts)] + if not table.find(checked,index.name) then + table.insert(checked,index.name) + if windower.ffxi.get_spells()[index.id] and windower.ffxi.get_spell_recasts()[index.id] == 0 then + table.insert(queue,index) + end + end + until #queue >= calls or #checked >= 103 --# of unique names w/o Cornelia + + elseif settings.sets[set] then + retr = {unpack(party_ind)} + for i=1,limit do + if settings.sets[set][tostring(i)] then + local entity = trusts:with(lang,settings.sets[set][tostring(i)]) + if not party[entity.name] + or party[entity.name] ~= entity.models then + if windower.ffxi.get_spell_recasts()[entity.id] == 0 then + if windower.ffxi.get_spells()[entity.id] then + table.insert(queue,entity) + else + table.remove(retr,table.find(retr,party_ind[i])) + error('You aren\'t trusted by '..entity.english..'.') + end + else + table.remove(retr,table.find(retr,party_ind[i])) + local recast = math.floor(windower.ffxi.get_spell_recasts()[entity.id] / 6) / 10 + log(entity.english..' needs '..recast..' secs break.') + end + else + table.remove(retr,table.find(retr,entity.name)) + if settings.auto then + log(entity.english..' already exists.') + end + end + end + end + for index,name in pairs(retr) do + if #retr == #party_ind then + windower.send_command('input /retr all') + coroutine.sleep(settings.wait.retrall) + break; + else + windower.send_command('input /retr '..name) + coroutine.sleep(settings.wait.retr) + end + end + else + error('Unknown set name '..(set or '')) + end + --if /retr then wait at least 3secs. + local delay = (limit - #party_ind) == 0 and math.max(0,settings.wait.retrall + time - os.clock()) or 0 + coroutine.schedule(call_trust,delay) +end + +windower.register_event('action', function(act) + if settings.auto and act.actor_id == windower.ffxi.get_player().id and queue and #queue > 0 then + if act.category == 4 and act.param == table.remove(queue,1).id then + coroutine.schedule(call_trust,settings.wait.aftercast) + elseif act.category == 8 and act.param == 28787 and act.targets[1].actions[1].param == queue[1].id then + coroutine.schedule(call_trust,settings.wait.aftercast) + end + end +end) + +function check_learned() + local learned = {} + for i,value in ipairs(trusts) do + if windower.ffxi.get_spells()[value.id] == false and not value.english:endswith('(UC)') then + table.insert(learned,value.id) + log(check_lang(value)) + end + end + log('You haven\'t trusted yet from '..#learned..' trusts.') +end + +trusts = T{ + [1]={id=896,japanese="シャントット",english="Shantotto",name="Shantotto",models=3000}, + [2]={id=897,japanese="ナジ",english="Naji",name="Naji",models=3001}, + [3]={id=898,japanese="クピピ",english="Kupipi",name="Kupipi",models=3002}, + [4]={id=899,japanese="エグセニミル",english="Excenmille",name="Excenmille",models=3003}, + [5]={id=900,japanese="アヤメ",english="Ayame",name="Ayame",models=3004}, + [6]={id=901,japanese="ナナー・ミーゴ",english="Nanaa Mihgo",name="NanaaMihgo",models=3005}, + [7]={id=902,japanese="クリルラ",english="Curilla",name="Curilla",models=3006}, + [8]={id=903,japanese="フォルカー",english="Volker",name="Volker",models=3007}, + [9]={id=904,japanese="アジドマルジド",english="Ajido-Marujido",name="Ajido-Marujido",models=3008}, + [10]={id=905,japanese="トリオン",english="Trion",name="Trion",models=3009}, + [11]={id=906,japanese="ザイド",english="Zeid",name="Zeid",models=3010}, + [12]={id=907,japanese="ライオン",english="Lion",name="Lion",models=3011}, + [13]={id=908,japanese="テンゼン",english="Tenzen",name="Tenzen",models=3012}, + [14]={id=909,japanese="ミリ・アリアポー",english="Mihli Aliapoh",name="MihliAliapoh",models=3013}, + [15]={id=910,japanese="ヴァレンラール",english="Valaineral",name="Valaineral",models=3014}, + [16]={id=911,japanese="ヨアヒム",english="Joachim",name="Joachim",models=3015}, + [17]={id=912,japanese="ナジャ・サラヒム",english="Naja Salaheem",name="NajaSalaheem",models=3016}, + [18]={id=913,japanese="プリッシュ",english="Prishe",name="Prishe",models=3017}, + [19]={id=914,japanese="ウルミア",english="Ulmia",name="Ulmia",models=3018}, + [20]={id=915,japanese="スカリーZ",english="Shikaree Z",name="ShikareeZ",models=3019}, + [21]={id=916,japanese="チェルキキ",english="Cherukiki",name="Cherukiki",models=3020}, + [22]={id=917,japanese="アイアンイーター",english="Iron Eater",name="IronEater",models=3021}, + [23]={id=918,japanese="ゲッショー",english="Gessho",name="Gessho",models=3022}, + [24]={id=919,japanese="ガダラル",english="Gadalar",name="Gadalar",models=3023}, + [25]={id=920,japanese="ライニマード",english="Rainemard",name="Rainemard",models=3024}, + [26]={id=921,japanese="イングリッド",english="Ingrid",name="Ingrid",models=3025}, + [27]={id=922,japanese="レコ・ハボッカ",english="Lehko Habhoka",name="LehkoHabhoka",models=3026}, + [28]={id=923,japanese="ナシュメラ",english="Nashmeira",name="Nashmeira",models=3027}, + [29]={id=924,japanese="ザザーグ",english="Zazarg",name="Zazarg",models=3028}, + [30]={id=925,japanese="アヴゼン",english="Ovjang",name="Ovjang",models=3029}, + [31]={id=926,japanese="メネジン",english="Mnejing",name="Mnejing",models=3030}, + [32]={id=927,japanese="サクラ",english="Sakura",name="Sakura",models=3031}, + [33]={id=928,japanese="ルザフ",english="Luzaf",name="Luzaf",models=3032}, + [34]={id=929,japanese="ナジュリス",english="Najelith",name="Najelith",models=3033}, + [35]={id=930,japanese="アルド",english="Aldo",name="Aldo",models=3034}, + [36]={id=931,japanese="モーグリ",english="Moogle",name="Moogle",models=3035}, + [37]={id=932,japanese="ファブリニクス",english="Fablinix",name="Fablinix",models=3036}, + [38]={id=933,japanese="マート",english="Maat",name="Maat",models=3037}, + [39]={id=934,japanese="D.シャントット",english="D. Shantotto",name="D.Shantotto",models=3038}, + [40]={id=935,japanese="星の神子",english="Star Sibyl",name="StarSibyl",models=3039}, + [41]={id=936,japanese="カラハバルハ",english="Karaha-Baruha",name="Karaha-Baruha",models=3040}, + [42]={id=937,japanese="シド",english="Cid",name="Cid",models=3041}, + [43]={id=938,japanese="ギルガメッシュ",english="Gilgamesh",name="Gilgamesh",models=3042}, + [44]={id=939,japanese="アレヴァト",english="Areuhat",name="Areuhat",models=3043}, + [45]={id=940,japanese="セミ・ラフィーナ",english="Semih Lafihna",name="SemihLafihna",models=3044}, + [46]={id=941,japanese="エリヴィラ",english="Elivira",name="Elivira",models=3045}, + [47]={id=942,japanese="ノユリ",english="Noillurie",name="Noillurie",models=3046}, + [48]={id=943,japanese="ルー・マカラッカ",english="Lhu Mhakaracca",name="LhuMhakaracca",models=3047}, + [49]={id=944,japanese="フェリアスコフィン",english="Ferreous Coffin",name="FerreousCoffin",models=3048}, + [50]={id=945,japanese="リリゼット",english="Lilisette",name="Lilisette",models=3049}, + [51]={id=946,japanese="ミュモル",english="Mumor",name="Mumor",models=3050}, + [52]={id=947,japanese="ウカ・トトゥリン",english="Uka Totlihn",name="UkaTotlihn",models=3051}, + [53]={id=948,japanese="クララ",english="Klara",name="Klara",models=3053}, + [54]={id=949,japanese="ロマー・ミーゴ",english="Romaa Mihgo",name="RomaaMihgo",models=3054}, + [55]={id=950,japanese="クイン・ハスデンナ",english="Kuyin Hathdenna",name="KuyinHathdenna",models=3055}, + [56]={id=951,japanese="ラーアル",english="Rahal",name="Rahal",models=3056}, + [57]={id=952,japanese="コルモル",english="Koru-Moru",name="Koru-Moru",models=3057}, + [58]={id=953,japanese="ピエージェ(UC)",english="Pieuje (UC)",name="Pieuje",models=3058}, + [59]={id=954,japanese="I.シールド(UC)",english="I. Shield (UC)",name="InvincibleShld",models=3060}, + [60]={id=955,japanese="アプルル(UC)",english="Apururu (UC)",name="Apururu",models=3061}, + [61]={id=956,japanese="ジャコ(UC)",english="Jakoh (UC)",name="JakohWahcondalo",models=3062}, + [62]={id=957,japanese="フラヴィリア(UC)",english="Flaviria (UC)",name="Flaviria",models=3059}, + [63]={id=958,japanese="ウェイレア",english="Babban",name="Babban",models=3067}, + [64]={id=959,japanese="アベンツィオ",english="Abenzio",name="Abenzio",models=3068}, + [65]={id=960,japanese="ルガジーン",english="Rughadjeen",name="Rughadjeen",models=3069}, + [66]={id=961,japanese="クッキーチェブキー",english="Kukki-Chebukki",name="Kukki-Chebukki",models=3070}, + [67]={id=962,japanese="マルグレート",english="Margret",name="Margret",models=3071}, + [68]={id=963,japanese="チャチャルン",english="Chacharoon",name="Chacharoon",models=3072}, + [69]={id=964,japanese="レイ・ランガヴォ",english="Lhe Lhangavo",name="LheLhangavo",models=3073}, + [70]={id=965,japanese="アシェラ",english="Arciela",name="Arciela",models=3074}, + [71]={id=966,japanese="マヤコフ",english="Mayakov",name="Mayakov",models=3075}, + [72]={id=967,japanese="クルタダ",english="Qultada",name="Qultada",models=3076}, + [73]={id=968,japanese="アーデルハイト",english="Adelheid",name="Adelheid",models=3077}, + [74]={id=969,japanese="アムチュチュ",english="Amchuchu",name="Amchuchu",models=3078}, + [75]={id=970,japanese="ブリジッド",english="Brygid",name="Brygid",models=3079}, + [76]={id=971,japanese="ミルドリオン",english="Mildaurion",name="Mildaurion",models=3080}, + [77]={id=972,japanese="ハルヴァー",english="Halver",name="Halver",models=3087}, + [78]={id=973,japanese="ロンジェルツ",english="Rongelouts",name="Rongelouts",models=3088}, + [79]={id=974,japanese="レオノアーヌ",english="Leonoyne",name="Leonoyne",models=3089}, + [80]={id=975,japanese="マクシミリアン",english="Maximilian",name="Maximilian",models=3090}, + [81]={id=976,japanese="カイルパイル",english="Kayeel-Payeel",name="Kayeel-Payeel",models=3091}, + [82]={id=977,japanese="ロベルアクベル",english="Robel-Akbel",name="Robel-Akbel",models=3092}, + [83]={id=978,japanese="クポフリート",english="Kupofried",name="Kupofried",models=3093}, + [84]={id=979,japanese="セルテウス",english="Selh\'teus",name="Selh\'teus",models=3094}, + [85]={id=980,japanese="ヨランオラン(UC)",english="Yoran-Oran (UC)",name="Yoran-Oran",models=3095}, + [86]={id=981,japanese="シルヴィ(UC)",english="Sylvie (UC)",name="Sylvie",models=3096}, + [87]={id=982,japanese="アブクーバ",english="Abquhbah",name="Abquhbah",models=3098}, + [88]={id=983,japanese="バラモア",english="Balamor",name="Balamor",models=3099}, + [89]={id=984,japanese="オーグスト",english="August",name="August",models=3100}, + [90]={id=985,japanese="ロスレーシャ",english="Rosulatia",name="Rosulatia",models=3101}, + [91]={id=986,japanese="テオドール",english="Teodor",name="Teodor",models=3103}, + [92]={id=987,japanese="ウルゴア",english="Ullegore",name="Ullegore",models=3105}, + [93]={id=988,japanese="マッキーチェブキー",english="Makki-Chebukki",name="Makki-Chebukki",models=3106}, + [94]={id=989,japanese="キング・オブ・ハーツ",english="King of Hearts",name="KingOfHearts",models=3107}, + [95]={id=990,japanese="モリマー",english="Morimar",name="Morimar",models=3108}, + [96]={id=991,japanese="ダラクァルン",english="Darrcuiln",name="Darrcuiln",models=3109}, + [97]={id=992,japanese="アークHM",english="AAHM",name="ArkHM",models=3113}, + [98]={id=993,japanese="アークEV",english="AAEV",name="ArkEV",models=3114}, + [99]={id=994,japanese="アークMR",english="AAMR",name="ArkMR",models=3115}, + [100]={id=995,japanese="アークTT",english="AATT",name="ArkTT",models=3116}, + [101]={id=996,japanese="アークGK",english="AAGK",name="ArkGK",models=3117}, + [102]={id=997,japanese="イロハ",english="Iroha",name="Iroha",models=3111}, + [103]={id=998,japanese="ユグナス",english="Ygnas",name="Ygnas",models=3118}, + [104]={id=1004,japanese="エグセニミルII",english="Excenmille [S]",name="Excenmille",models=3052}, + [105]={id=1005,japanese="アヤメ(UC)",english="Ayame (UC)",name="Ayame",models=3063}, + [106]={id=1006,japanese="マート(UC)",english="Maat (UC)",name="Maat",models=3064}, --expected models + [107]={id=1007,japanese="アルド(UC)",english="Aldo (UC)",name="Aldo",models=3065}, --expected models + [108]={id=1008,japanese="ナジャ(UC)",english="Naja (UC)",name="NajaSalaheem",models=3066}, + [109]={id=1009,japanese="ライオンII",english="Lion II",name="Lion",models=3081}, + [110]={id=1010,japanese="ザイドII",english="Zeid II",name="Zeid",models=3086}, + [111]={id=1011,japanese="プリッシュII",english="Prishe II",name="Prishe",models=3082}, + [112]={id=1012,japanese="ナシュメラII",english="Nashmeira II",name="Nashmeira",models=3083}, + [113]={id=1013,japanese="リリゼットII",english="Lilisette II",name="Lilisette",models=3084}, + [114]={id=1014,japanese="テンゼンII",english="Tenzen II",name="Tenzen",models=3097}, + [115]={id=1015,japanese="ミュモルII",english="Mumor II",name="Mumor",models=3104}, + [116]={id=1016,japanese="イングリッドII",english="Ingrid II",name="Ingrid",models=3102}, + [117]={id=1017,japanese="アシェラII",english="Arciela II",name="Arciela",models=3085}, + [118]={id=1018,japanese="イロハII",english="Iroha II",name="Iroha",models=3112}, + [119]={id=1019,japanese="シャントットII",english="Shantotto II",name="Shantotto",models=3110}, +--[120]={id=1003,japanese="コーネリア",english="Cornelia",name="Cornelia",models=3119}, --goodbye, my love +} diff --git a/addons/addons.xml b/addons/addons.xml index 5bc38003ff..940690048c 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -697,4 +697,11 @@ https://github.com/Snapsmojo/Lua/issues http://www.ffxiah.com/player/Fenrir/Snaps + + Trusts + Centurio a.k.a. from20020516 + Save/Summon Trust set. + https://github.com/from20020516/Lua/issues + https://twitter.com/from20020516 + From 327b7d965e2d518602e8c816446d5e8929ce84f2 Mon Sep 17 00:00:00 2001 From: from20020516 Date: Thu, 31 May 2018 22:53:55 +0900 Subject: [PATCH 0125/1002] following 'Sets:' stats with AF119+, ambuscade and Abjuration gears. --- addons/checkparam/README.md | 24 ++++---- addons/checkparam/checkparam.lua | 99 +++++++++++++++++++++++++++----- 2 files changed, 98 insertions(+), 25 deletions(-) diff --git a/addons/checkparam/README.md b/addons/checkparam/README.md index 7e67284f02..64cb2ddd6a 100644 --- a/addons/checkparam/README.md +++ b/addons/checkparam/README.md @@ -1,18 +1,20 @@ # checkparam - `/check` OR `/c` (in-game command) - - 「調べる」したとき、対象が装備しているアイテムのうち任意のプロパティを合計して表示します。 - - whenever you /check any player, displays the total of property of current equipments.(defined in `setting.xml`) + - Whenever you `/check` any player, displays the total of property of that players current equipments.(defined in `settings.xml`) + - プレイヤーを「調べる」したとき、そのプレイヤーが装備しているアイテムの任意のプロパティを合計して表示します。(`settings.xml`で定義) +- `//checkparam` OR `//cp` (addon command) + - same as /check . you can use this command in equipment menu. + - /check と同様ですが、装備変更画面でも使用できます。 ## data/settings.xml (auto-generated) -- 表示させるプロパティをジョブごとに定義します。 - - `|` 区切り記号 divide each property - - `NON`は/anon時に使用 - - 召喚獣: 飛竜: オートマトン: 羅盤: などペットに関するプロパティは全て`pet: `で指定します。 +- Define the properties you want to be displayed for each job. + - `|` divide each property + - `pet: ` define properties for all pets, which means avatar: wyvern: automaton: luopan: +- 表示させたいプロパティをジョブごとに定義します。 + - `|` 区切り記号 + - `pet: ` 召喚獣: 飛竜: オートマトン: 羅盤: は代わりに`pet:`で指定します。 -- Checkparam uses `setting.xml` to define the properties you want to be displayed. - - You can define the properties for each job. - - `NON` means target status is /anon - - `pet: ` define properties for all pets, which means avatar,wyvern,automaton,luopan. -- If there’s something wrong,or something strange,please tell me on Twitter [@from20020516](https://twitter.com/from20020516) **with simple English**. Thank you! +- If there’s something wrong,or something strange, +please tell me on Twitter [@from20020516](https://twitter.com/from20020516) **with simple English**. Thank you! diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua index c72673932b..d4e990cba8 100644 --- a/addons/checkparam/checkparam.lua +++ b/addons/checkparam/checkparam.lua @@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.]] _addon.name = 'Checkparam' _addon.author = 'from20020516' -_addon.version = '1.1' +_addon.version = '1.2' _addon.commands = {'cp','checkparam'} require('logger') @@ -37,7 +37,6 @@ config = require('config') packets = require('packets') defaults = { - NON = 'fast cast', WAR = 'store tp|double attack|triple attack|quadruple attack|weapon skill damage', MNK = 'store tp|double attack|triple attack|quadruple attack|martial arts|subtle blow', WHM = 'cure potency|cure potency ii|fast cast|cure spellcasting time|enmity|healing magic casting time|divine benison|damage taken|physical damage taken|magic damage taken', @@ -60,12 +59,31 @@ defaults = { SCH = 'magic attack bonus|magic burst damage|magic burst damage ii|magic accuracy|magic damage|fast cast|elemental magic casting time|cure potency|enh mag eff dur|enhancing magic effect duration', GEO = 'pet: regen|pet: damage taken|indicolure effect duration|indi eff dur|fast cast|magic evasion', RUN = 'enmity|damage taken|physical damage taken|magic damage taken|spell inturruption rate|pharanx|inquartata|fastcast', + levelfilter = 99, debugmode = false, } settings = config.load(defaults) tbl = {} +windower.register_event('addon command',function(arg) + if arg == 'debugmode' then + settings.debugmode = not settings.debugmode + settings:save('all') + else + for i=0,#res.slots do + local slot = windower.regex.replace(string.lower(res.slots[i].en),' ','_') + local gear_set = windower.ffxi.get_items().equipment + local gear = windower.ffxi.get_items(gear_set[slot..'_bag'],gear_set[slot]) + if gear_set[slot] > 0 then + get_text(gear.id,gear.extdata) + end + end + local my = windower.ffxi.get_player() + show_results(my.name,my.main_job,my.sub_job) + end +end) + windower.register_event('incoming chunk',function(id,data) if id == 0x0C9 then local p = packets.parse('incoming',data) @@ -78,11 +96,18 @@ windower.register_event('incoming chunk',function(id,data) get_text(p['Item '..i],p['ExtData '..i]) end end - elseif p['Type'] == 1 then --metadata + elseif p['Type'] == 1 then local t = windower.ffxi.get_mob_by_id(p['Target ID']) local mjob = res.jobs[p['Main Job']].ens local sjob = res.jobs[p['Sub Job']].ens - show_results(t.name,mjob,sjob) + if p['Main Job Level'] >= settings.levelfilter then + show_results(t.name,mjob,sjob) + else + tbl = {} + if mjob == 'NON' then + error('The target is in /anon state.') + end + end end end end) @@ -112,6 +137,8 @@ function get_text(id,data) log(id,res.items[id].english,stats[1],stats[2],tbl[stats[1]]) end end + tbl.sets = tbl.sets or {} + table.insert(tbl.sets,id) end function split_text(id,text,arg) @@ -119,7 +146,7 @@ function split_text(id,text,arg) local key = windower.regex.replace(string.lower(key),'(\\"|\\.|\\s$)','') local key = integrate[key] or key local key = arg and arg..key or key - tbl[key] = tonumber(value) + (tbl[key] or 0) + tbl[key] = tonumber(value)+(tbl[key] or 0) if settings.debugmode then log(id,res.items[id].english,key,value,tbl[key]) end @@ -127,25 +154,30 @@ function split_text(id,text,arg) end function show_results(name,mjob,sjob) + local count = {} + for key,value in pairs(combination) do + for _,id in pairs(tbl.sets) do + if value.item[id] then + count[key] = (count[key] or 0)+1 + end + end + if count[key] and count[key] > 1 then + for stat,multi in pairs(value.stats) do + tbl[stat] = (tbl[stat] or 0)+multi*math.min((count[key]+value.type),5) + end + end + end local stats = settings[mjob] local head = '<'..mjob..'/'..sjob..'>' windower.add_to_chat(160,string.color(name,1,160)..': '..string.color(head,160,160)) - if mjob == 'NON' then - notice('Unknown job because /anon state. instead display .') - end for index,key in ipairs(windower.regex.split(stats,'[|]')) do local value = tbl[string.lower(key)] local color = {value and 1 or 160,value and 166 or 160} windower.add_to_chat(160,' ['..string.color(key,color[1],160)..'] '..string.color(tostring(value),color[2],160)) end tbl = {} - collectgarbage() end -windower.register_event('load',function() - print('Checkparam: Activate with in-game /check command.') -end) - integrate = { --[[integrate same property.information needed for development. @from20020516]] ['quad atk'] = 'quadruple attack', @@ -165,6 +197,8 @@ integrate = { ['magatkbns'] = 'magic attack bonus', ['mag atk bonus'] = 'magic attack bonus', ['mag acc'] = 'magic accuracy', + ['m acc'] = 'magic accuracy', + ['r acc'] = 'ranged accuracy', ['magic burst dmg'] = 'magic burst damage', ['mag dmg'] = 'magic damage', ['crithit rate'] = 'critical hit rate', @@ -183,7 +217,7 @@ enhanced = { [11000] = 'fast cast+3', --Swith Cape [11001] = 'fast cast+4', --Swith Cape +1 [11037] = 'stoneskin+10', --Earthcry Earring - [11051] = 'increases resistance to all status ailments+5', ----Hearty Earring + [11051] = 'increases resistance to all status ailments+5', --Hearty Earring [11544] = 'fast cast+1', --Veela Cape [11602] = 'martial arts+10', --Cirque Necklace [11603] = 'dual wield+3', --Charis Necklace @@ -232,3 +266,40 @@ enhanced = { [28631] = 'elemental siphon+30', --Conveyance Cape [28637] = 'fast cast+7', --Lifestream Cape } +combination={ + ['af']={item=S{ + 23040,23041,23042,23043,23044,23045,23046,23047,23048,23049,23050,23051,23052,23053,23055,23056,23057,23058,23059,23060,23061,23062, + 23107,23108,23109,23110,23111,23112,23113,23114,23115,23116,23117,23118,23119,23120,23122,23123,23124,23125,23126,23127,23128,23129, + 23174,23175,23176,23177,23178,23179,23180,23181,23182,23183,23184,23185,23186,23187,23189,23190,23191,23192,23193,23194,23195,23196, + 23241,23242,23243,23244,23245,23246,23247,23248,23249,23250,23251,23252,23253,23254,23256,23257,23258,23259,23260,23261,23262,23263, + 23308,23309,23310,23311,23312,23313,23314,23315,23316,23317,23318,23319,23320,23321,23323,23324,23325,23326,23327,23328,23329,23330, + 23375,23376,23377,23378,23379,23380,23381,23382,23383,23384,23385,23386,23387,23388,23390,23391,23392,23393,23394,23395,23396,23397, + 23442,23443,23444,23445,23446,23447,23448,23449,23450,23451,23452,23453,23454,23455,23457,23458,23459,23460,23461,23462,23463,23464, + 23509,23510,23511,23512,23513,23514,23515,23516,23517,23518,23519,23520,23521,23522,23524,23525,23526,23527,23528,23529,23530,23531, + 23576,23577,23578,23579,23580,23581,23582,23583,23584,23585,23586,23587,23588,23589,23591,23592,23593,23594,23595,23596,23597,23598, + 23643,23644,23645,23646,23647,23648,23649,23650,23651,23652,23653,23654,23655,23656,23658,23659,23660,23661,23662,23663,23664,23665, + 26085,26191},stats={['accuracy']=15,['magic accuracy']=15,['ranged accuracy']=15},type=-1}, + ['af_smn']={item=S{23054,23121,23188,23255,23322,23389,23456,23523,23590,23657,26342}, + stats={['pet: accuracy']=15,['pet: magic accuracy']=15,['pet: ranged accuracy']=15},type=-1}, + ['adhemar']={item=S{25614,25687,27118,27303,27474},stats={['critical hit rate']=2},type=0}, + ['amalric']={item=S{25616,25689,27120,27305,27476},stats={['magic attack bonus']=10},type=0}, + ['apogee']={item=S{26677,26853,27029,27205,27381},stats={['blood pact damage']=2},type=0}, + ['argosy']={item=S{26673,26849,27025,27201,27377},stats={['double attack']=2},type=0}, + ['emicho']={item=S{25610,25683,27114,27299,27470},stats={['double attack']=2},type=0}, + ['carmine']={item=S{26679,26855,27031,27207,27383},stats={['accuracy']=10},type=0}, + ['kaykaus']={item=S{25618,25691,27122,27307,27478},stats={['cure potency ii']=2},type=0}, + ['lustratio']={item=S{26669,26845,27021,27197,27373},stats={['weapon skill damage']=2},type=0}, + ['rao']={item=S{26675,26851,27027,27203,27379},stats={['matial arts']=2},type=0}, + ['ryuo']={item=S{25612,25685,27116,27301,27472},stats={['attack']=10},type=0}, + ['souveran']={item=S{26671,26847,27023,27199,27375},stats={['damage taken']=2},type=0}, + ['ayanmo']={item=S{25572,25795,25833,25884,25951},stats={['str']=8,['vit']=8,['mnd']=8},type=-1}, + ['flamma']={item=S{25569,25797,25835,25886,25953},stats={['str']=8,['dex']=8,['vit']=8},type=-1}, + ['mallquis']={item=S{25571,25799,25837,25888,25955},stats={['vit']=8,['int']=8,['mnd']=8},type=-1}, + ['Mummu']={item=S{25570,25798,25836,25887,25954},stats={['dex']=8,['agi']=8,['chr']=8},type=-1}, + ['tali\'ah']={item=S{25573,25796,25834,25885,25952},stats={['vit']=8,['dex']=8,['chr']=8},type=-1}, + ['Hizamaru']={item=S{25576,25792,25830,25881,25948},stats={['counter']=2},type=-1}, + ['Inyanga']={item=S{25577,25793,25831,25882,25949},stats={['refresh']=1},type=-1}, + ['jhakri']={item=S{25578,25794,25832,25883,25950},stats={['fast cast']=3},type=-1}, + ['meghanada']={item=S{25575,25791,25829,25880,25947},stats={['regen']=3},type=-1}, + ['Sulevia\'s']={item=S{25574,25790,25828,25879,25946},stats={['subtle blow']=5},type=-1}, +} From 7a58a6af3f788af7a35dfe4ebf0fbf8915ca1efc Mon Sep 17 00:00:00 2001 From: from20020516 Date: Fri, 1 Jun 2018 03:12:45 +0900 Subject: [PATCH 0126/1002] done requested changes. --- addons/Bonanza/Bonanza.lua | 248 +++++++++++++++++-------------------- 1 file changed, 114 insertions(+), 134 deletions(-) diff --git a/addons/Bonanza/Bonanza.lua b/addons/Bonanza/Bonanza.lua index 46086d5158..5723a9e9eb 100644 --- a/addons/Bonanza/Bonanza.lua +++ b/addons/Bonanza/Bonanza.lua @@ -6,13 +6,13 @@ 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. + 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 checkparam nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Bonanza 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 @@ -41,155 +41,135 @@ math.randomseed(os.time()) --search your bags for bonanza marble and get number then add prefix 0 function search_marbles() - local marbles = {} - local bags = {0,1,2,4,5,6,7,9} - for bag_ind=1,#bags do - for index=1,windower.ffxi.get_bag_info(bags[bag_ind]).max do - local item = windower.ffxi.get_items(bags[bag_ind],index) - if item.id == marble.id then --bonanza marble - local five_digits = string.format("%05s",extdata.decode(item).number) - table.insert(marbles,{bags[bag_ind],index,five_digits}) - end + local marbles = {} + local bags = {0,1,2,4,5,6,7,9} + local items = windower.ffxi.get_items + for bag_ind=1,#bags do + for index=1,windower.ffxi.get_bag_info(bags[bag_ind]).max do + local item = items(bags[bag_ind],index) + if item.id == marble.id then --bonanza marble + local five_digits = string.format('%05s',extdata.decode(item).number) + table.insert(marbles,{bags[bag_ind],index,five_digits}) + end + end end - end - return marbles; + return marbles; end windower.register_event('addon command',function(...) - moogle = windower.ffxi.get_mob_by_name('Bonanza Moogle') - decides = {} - local cmd={...} - local count = marble.limit-#search_marbles() - - for i=1,#cmd do - math.random() --shuffle rand - cmd[i] = tonumber(cmd[i]) and cmd[i]*1 or cmd[i] - end - - if cmd[1] == 'judge' then - windower.send_command('input /smes') - elseif count == 0 then - error('you have already '..marble.limit..' marbles.') - elseif cmd[1] == 'random' then - for i=1,count do - table.insert(decides,math.random(0,99999)) - end - elseif cmd[1] == 'sequence' then - local n = math.min(cmd[2],10000-count) - for i=n,n+count-1 do - table.insert(decides,i) + moogle = windower.ffxi.get_mob_by_name('Bonanza Moogle') + decides = {} + local cmd={...} + local count = marble.limit-#search_marbles() + for i=1,#cmd do + math.random() --shuffle rand + cmd[i] = tonumber(cmd[i]) and cmd[i]*1 or cmd[i] end - elseif cmd[1] == 'last' and 10 > cmd[2] then - for i=1,count do - table.insert(decides,tonumber(math.random(0,9999)..cmd[2])) + + if cmd[1] == 'judge' then + windower.chat.input('/smes') + elseif count == 0 then + error('you have already '..marble.limit..' marbles.') + elseif cmd[1] == 'random' then + for i=1,count do + table.insert(decides,math.random(0,99)+math.random(0,99)*100+math.random(0,9)*10000) + end + elseif cmd[1] == 'sequence' then + local n = math.min(cmd[2],10000-count) + for i=n,n+count-1 do + table.insert(decides,i) + end + elseif cmd[1] == 'last' and 10 > cmd[2] then + for i=1,count do + table.insert(decides,tonumber(math.random(0,9999)..cmd[2])) + end + elseif 100000 > cmd[1] and not cmd[marble.limit+1] then + decides = cmd end - elseif 100000 > cmd[2] and not cmd[marble.limit+1] then - decides = cmd - end - if #decides > 0 then - talk_moogle() - end + if #decides > 0 then + talk_moogle() + end end) function talk_moogle() - --print(unpack(decides)) - if #decides > 0 then - hide_ui = true - local packet = packets.new('outgoing',0x01A,{ - ["Target"]=moogle.id, - ["Target Index"]=moogle.index, - ["Category"]=0, - ["Param"]=0, - ["_unknown1"]=0}) - packets.inject(packet) - end + if #decides > 0 then + hide_ui = true + local packet = packets.new('outgoing',0x01A,{ + ['Target']=moogle.id, + ['Target Index']=moogle.index}) + packets.inject(packet) + end end windower.register_event('incoming chunk',function(id,data) - --got a marble. - if id == 0x020 and hide_ui and data:unpack('H',0x0D) == marble.id and data:unpack('C',0x0F) == 0 then - local item = windower.ffxi.get_items(0,data:unpack('C',0x10)) - if extdata.decode(item).number == decides[1] then - hide_ui = false - table.remove(decides,1) - talk_moogle() + --got a marble. + local p = packets.parse('incoming',data) + if id == 0x020 and hide_ui and p['Item'] == marble.id and p['Bag'] == 0 then + local item = windower.ffxi.get_items(0,p['Index']) + if extdata.decode(item).number == decides[1] then + hide_ui = false + table.remove(decides,1) + talk_moogle() + end + --responced to talk. + elseif id == 0x034 and hide_ui and p['NPC'] == moogle.id then + if moogle.distance > 36 then + error('not close enough to Bonanza Moogle.') + elseif marble.price > windower.ffxi.get_items().gil then + error('not have enough gils.') + else + local packet = packets.new('outgoing',0x05B) + local i = decides[1] + log('Purchase a Bonanza Marble #'..string.format('%05s',i)) + --packet part 1 + packet['Target']=moogle.id + packet['Option Index']=2+i%256*256 + packet['Target Index']=moogle.index + packet['Automated Message']=true + packet['_unknown1']=(i-i%256)/256 + packet['Zone']=p['Zone'] + packet['Menu ID']=p['Menu ID'] + packets.inject(packet) + --packet part 2 + packet['Option Index']=3 + packet['Automated Message']=false + packets.inject(packet) + return true; --hide ui + end end - --responced to talk. - elseif id == 0x034 and hide_ui and data:unpack('I',0x05) == moogle.id then - if moogle.distance > 36 then - error('not close enough to Bonanza Moogle.') - elseif marble.price > windower.ffxi.get_items().gil then - error('not have enough gils.') - else - local packet = packets.new('outgoing',0x05B) - local i = decides[1] - log('Purchase a Bonanza Marble #'..string.format("%05s",i)) - --packet part 1 - packet["Target"]=moogle.id - packet["Option Index"]=2+i%256*256 - packet["Target Index"]=moogle.index - packet["Automated Message"]=true - packet["_unknown1"]=(i-i%256)/256 - packet["_unknown2"]=0 - packet["Zone"]=data:unpack('H',0x2B) - packet["Menu ID"]=data:unpack('H',0x2D) - packets.inject(packet) - --packet part 2 - packet["Option Index"]=3 - packet["_unknown1"]=0 - packet["Automated Message"]=false - packets.inject(packet) - return true; --hide ui - end - end end) --get winning numbers(str) from /smes. windower.register_event('incoming text',function(original,modified,mode) - local jis = windower.from_shift_jis(original) --valid in english environment - if mode == 200 and windower.regex.match(jis,'digit|けた') then - local numbers = windower.regex.match(jis,'["「]([0-9]+)[」"]')[1][1] - table.insert(win_numbers,6-string.len(numbers),numbers) - if #win_numbers == 5 then - scan_marbles() + local jis = windower.from_shift_jis(original) --valid in english environment + if mode == 200 and windower.regex.match(jis,'digit|けた') then + local numbers = windower.regex.match(jis,'["「]([0-9]+)[」"]')[1][1] + table.insert(win_numbers,6-string.len(numbers),numbers) + if #win_numbers == 5 then + scan_marbles() + end end - end end) function scan_marbles() - log('Winning numbers is..',unpack(win_numbers)) - local marbles = search_marbles() - local colors = {51,18,166,207,208,161} - for m=1,#marbles do - local number = marbles[m][3] - if S{1,2,4,9}[marbles[m][1]] and windower.ffxi.get_info().mog_house - or S{5,6,7}[marbles[m][1]] then - windower.ffxi.get_item(marbles[m][1],marbles[m][2]) - end - for r=1,5 do - local text = _addon.name..': #'..string.format("%02s",m)..' '..number..' ') - break; - elseif r == 5 then - windower.add_to_chat(colors[6],text..'6'..'>') - end + log('Winning numbers is..',unpack(win_numbers)) + local marbles = search_marbles() + local colors = {51,18,166,207,208,161} + for m=1,#marbles do + local number = marbles[m][3] + if S{1,2,4,9}[marbles[m][1]] and windower.ffxi.get_info().mog_house + or S{5,6,7}[marbles[m][1]] then + windower.ffxi.get_item(marbles[m][1],marbles[m][2]) + end + for r=1,5 do + local text = _addon.name..': #'..string.format("%02s",m)..' '..number..' ') + break; + elseif r == 5 then + windower.add_to_chat(colors[6],text..'6'..'>') + end + end end - end end - ---[[ -windower.add_to_chat(200,windower.to_shift_jis('5等 下1けた「3」 当せん個数「83,350」個')) -windower.add_to_chat(200,windower.to_shift_jis('4等 下2けた「08」 当せん個数「8,287」個')) -windower.add_to_chat(200,windower.to_shift_jis('3等 下3けた「723」 当せん個数「914」個')) -windower.add_to_chat(200,windower.to_shift_jis('2等 下4けた「8940」 当せん個数「71」個')) -windower.add_to_chat(200,windower.to_shift_jis('1等 全5けた「66621」 当せん個数「7」個')) -]] ---[[ -windower.add_to_chat(200,'Rank 5 prize: "3" (last digit)-- 83,350 winners.') -windower.add_to_chat(200,'Rank 4 prize: "08" (last two digits)-- 8,287 winners.') -windower.add_to_chat(200,'Rank 3 prize: "723" (last three digits)-- 914 winners.') -windower.add_to_chat(200,'Rank 2 prize: "8940" (last four digits)-- 71 winners.') -windower.add_to_chat(200,'Rank 1 prize: "66621" (all five digits)-- 7 winners.') -]] From 434265ced75d4033a5d38edfd833fe062e2b5f43 Mon Sep 17 00:00:00 2001 From: from20020516 Date: Fri, 1 Jun 2018 03:31:03 +0900 Subject: [PATCH 0127/1002] done requested changes. --- addons/checkparam/checkparam.lua | 463 +++++++++++++++---------------- 1 file changed, 229 insertions(+), 234 deletions(-) diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua index d4e990cba8..083a5e4281 100644 --- a/addons/checkparam/checkparam.lua +++ b/addons/checkparam/checkparam.lua @@ -6,13 +6,13 @@ 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. + 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. + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. * Neither the name of checkparam nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. + 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 @@ -37,269 +37,264 @@ config = require('config') packets = require('packets') defaults = { - WAR = 'store tp|double attack|triple attack|quadruple attack|weapon skill damage', - MNK = 'store tp|double attack|triple attack|quadruple attack|martial arts|subtle blow', - WHM = 'cure potency|cure potency ii|fast cast|cure spellcasting time|enmity|healing magic casting time|divine benison|damage taken|physical damage taken|magic damage taken', - BLM = 'magic attack bonus|magic burst damage|magic burst damage ii|int|magic accuracy|magic damage|fast cast|elemental magic casting time', - RDM = 'magic attack bonus|magic burst damage|magic burst damage ii|magic accuracy|fast cast|enfeebling magic skill|enhancing magic skill|store tp|dual wield', - THF = 'store tp|double attack|triple attack|quadruple attack|dual wield', - PLD = 'enmity|damage taken|physical damage taken|magic damage taken|spell inturruption rate|pharanx|cure potency|fastcast', - DRK = 'store tp|double attack|triple attack|quadruple attack|weapon skill damage', - BST = 'pet: double attack|pet: magic attack bonus|pet: damage taken', - BRD = 'all songs|song effect duration|fast cast|song spellcasting time', - RNG = 'store tp|snapshot|rapid shot|weapon skill damage', - SAM = 'store tp|double attack|triple attack|quadruple attack|weapon skill damage', - NIN = 'store tp|double attack|triple attack|quadruple attack|subtle blow', - DRG = 'store tp|double attack|triple attack|quadruple attack|weapon skill damage', - SMN = 'blood pact delay|blood pact delay ii|blood pact damage|avatar perpetuation cost|pet: magic attack bonus|pet: str|pet: double attack', - BLU = 'store tp|double attack|triple attack|quadruple attack|critical hit rate|critical hit damage|weapon skill damage|fast cast|magic attack bonus|magic accuracy|cure potency', - COR = 'store tp|snapshot|rapid shot|fast cast|cure potency|magic accuracy|magic attack bonus|magic damage|weapon skill damage', - PUP = 'pet: hp|pet: damage taken|pet: regen|martial arts|store tp|double attack|triple attack|quadruple attack', - DNC = 'store tp|double attack|triple attack|quadruple attack', - SCH = 'magic attack bonus|magic burst damage|magic burst damage ii|magic accuracy|magic damage|fast cast|elemental magic casting time|cure potency|enh mag eff dur|enhancing magic effect duration', - GEO = 'pet: regen|pet: damage taken|indicolure effect duration|indi eff dur|fast cast|magic evasion', - RUN = 'enmity|damage taken|physical damage taken|magic damage taken|spell inturruption rate|pharanx|inquartata|fastcast', - levelfilter = 99, - debugmode = false, + WAR = 'store tp|double attack|triple attack|quadruple attack|weapon skill damage', + MNK = 'store tp|double attack|triple attack|quadruple attack|martial arts|subtle blow', + WHM = 'cure potency|cure potency ii|fast cast|cure spellcasting time|enmity|healing magic casting time|divine benison|damage taken|physical damage taken|magic damage taken', + BLM = 'magic attack bonus|magic burst damage|magic burst damage ii|int|magic accuracy|magic damage|fast cast|elemental magic casting time', + RDM = 'magic attack bonus|magic burst damage|magic burst damage ii|magic accuracy|fast cast|enfeebling magic skill|enhancing magic skill|store tp|dual wield', + THF = 'store tp|double attack|triple attack|quadruple attack|dual wield', + PLD = 'enmity|damage taken|physical damage taken|magic damage taken|spell inturruption rate|pharanx|cure potency|fastcast', + DRK = 'store tp|double attack|triple attack|quadruple attack|weapon skill damage', + BST = 'pet: double attack|pet: magic attack bonus|pet: damage taken', + BRD = 'all songs|song effect duration|fast cast|song spellcasting time', + RNG = 'store tp|snapshot|rapid shot|weapon skill damage', + SAM = 'store tp|double attack|triple attack|quadruple attack|weapon skill damage', + NIN = 'store tp|double attack|triple attack|quadruple attack|subtle blow', + DRG = 'store tp|double attack|triple attack|quadruple attack|weapon skill damage', + SMN = 'blood pact delay|blood pact delay ii|blood pact damage|avatar perpetuation cost|pet: magic attack bonus|pet: str|pet: double attack', + BLU = 'store tp|double attack|triple attack|quadruple attack|critical hit rate|critical hit damage|weapon skill damage|fast cast|magic attack bonus|magic accuracy|cure potency', + COR = 'store tp|snapshot|rapid shot|fast cast|cure potency|magic accuracy|magic attack bonus|magic damage|weapon skill damage', + PUP = 'pet: hp|pet: damage taken|pet: regen|martial arts|store tp|double attack|triple attack|quadruple attack', + DNC = 'store tp|double attack|triple attack|quadruple attack', + SCH = 'magic attack bonus|magic burst damage|magic burst damage ii|magic accuracy|magic damage|fast cast|elemental magic casting time|cure potency|enh mag eff dur|enhancing magic effect duration', + GEO = 'pet: regen|pet: damage taken|indicolure effect duration|indi eff dur|fast cast|magic evasion', + RUN = 'enmity|damage taken|physical damage taken|magic damage taken|spell inturruption rate|pharanx|inquartata|fastcast', + levelfilter = 99, } settings = config.load(defaults) tbl = {} windower.register_event('addon command',function(arg) - if arg == 'debugmode' then - settings.debugmode = not settings.debugmode - settings:save('all') - else + local items = windower.ffxi.get_items for i=0,#res.slots do - local slot = windower.regex.replace(string.lower(res.slots[i].en),' ','_') - local gear_set = windower.ffxi.get_items().equipment - local gear = windower.ffxi.get_items(gear_set[slot..'_bag'],gear_set[slot]) - if gear_set[slot] > 0 then - get_text(gear.id,gear.extdata) - end + local slot = windower.regex.replace(string.lower(res.slots[i].english),' ','_') + local gear_set = items().equipment + local gear = items(gear_set[slot..'_bag'],gear_set[slot]) + if gear_set[slot] > 0 then + get_text(gear.id,gear.extdata) + end end local my = windower.ffxi.get_player() show_results(my.name,my.main_job,my.sub_job) - end end) windower.register_event('incoming chunk',function(id,data) - if id == 0x0C9 then - local p = packets.parse('incoming',data) - if p['Type'] == 3 then - local count = p['Count'] - if count == 1 then - get_text(p['Item'],p['ExtData']) - else - for i=1,count do - get_text(p['Item '..i],p['ExtData '..i]) - end - end - elseif p['Type'] == 1 then - local t = windower.ffxi.get_mob_by_id(p['Target ID']) - local mjob = res.jobs[p['Main Job']].ens - local sjob = res.jobs[p['Sub Job']].ens - if p['Main Job Level'] >= settings.levelfilter then - show_results(t.name,mjob,sjob) - else - tbl = {} - if mjob == 'NON' then - error('The target is in /anon state.') + if id == 0x0C9 then + local p = packets.parse('incoming',data) + if p['Type'] == 3 then + local count = p['Count'] + if count == 1 then + get_text(p['Item'],p['ExtData']) + else + for i=1,count do + get_text(p['Item '..i],p['ExtData '..i]) + end + end + elseif p['Type'] == 1 then + local t = windower.ffxi.get_mob_by_index(p['Target Index']) + local mjob = res.jobs[p['Main Job']].english_short + local sjob = res.jobs[p['Sub Job']].english_short + if p['Main Job Level'] >= settings.levelfilter then + show_results(t.name,mjob,sjob) + else + tbl = {} + if mjob == 'NON' then + error('The target is in /anon state.') + end + end end - end end - end end) function get_text(id,data) - config.reload(settings) - local descriptions = res.item_descriptions[id] - local helptext = descriptions and descriptions.english or '' --for 'vanilla' items. e.g. Moonshade Earring - local stats = windower.regex.split(helptext,'(Pet|Avatar|Automaton|Wyvern|Luopan): ') - for i,v in ipairs(windower.regex.split(stats[1],'\n')) do - split_text(id,v) - end - if stats[2] then - local pet_text = windower.regex.replace(stats[2],'\n',' ') - split_text(id,pet_text,'pet: ') - end - local ext = extdata.decode({id=id,extdata=data}) - if ext.augments then - for i,v in ipairs(ext.augments) do - split_text(id,v) + config.reload(settings) + local descriptions = res.item_descriptions[id] + local helptext = descriptions and descriptions.english or '' --for 'vanilla' items. e.g. Moonshade Earring + local stats = windower.regex.split(helptext,'(Pet|Avatar|Automaton|Wyvern|Luopan): ') + for i,v in ipairs(windower.regex.split(stats[1],'\n')) do + split_text(id,v) end - end - if enhanced[id] then - local stats = enhanced[id]:gsub('([+-:][0-9]+)',',%1'):split(',') - tbl[stats[1]] = tonumber(stats[2]) + (tbl[stats[1]] or 0) - if settings.debugmode then - log(id,res.items[id].english,stats[1],stats[2],tbl[stats[1]]) + if stats[2] then + local pet_text = windower.regex.replace(stats[2],'\n',' ') + split_text(id,pet_text,'pet: ') end - end - tbl.sets = tbl.sets or {} - table.insert(tbl.sets,id) + local ext = extdata.decode({id=id,extdata=data}) + if ext.augments then + for i,v in ipairs(ext.augments) do + split_text(id,v) + end + end + if enhanced[id] then + local stats = enhanced[id]:gsub('([+-:][0-9]+)',',%1'):split(',') + tbl[stats[1]] = tonumber(stats[2]) + (tbl[stats[1]] or 0) + if settings.debugmode then + log(id,res.items[id].english,stats[1],stats[2],tbl[stats[1]]) + end + end + tbl.sets = tbl.sets or {} + table.insert(tbl.sets,id) end function split_text(id,text,arg) - for key,value in string.gmatch(text,'/?([%D]-):?([%+%-]?[0-9]+)%%?%s?') do - local key = windower.regex.replace(string.lower(key),'(\\"|\\.|\\s$)','') - local key = integrate[key] or key - local key = arg and arg..key or key - tbl[key] = tonumber(value)+(tbl[key] or 0) - if settings.debugmode then - log(id,res.items[id].english,key,value,tbl[key]) + for key,value in string.gmatch(text,'/?([%D]-):?([%+%-]?[0-9]+)%%?%s?') do + local key = windower.regex.replace(string.lower(key),'(\\"|\\.|\\s$)','') + local key = integrate[key] or key + local key = arg and arg..key or key + tbl[key] = tonumber(value)+(tbl[key] or 0) + if settings.debugmode then + log(id,res.items[id].english,key,value,tbl[key]) + end end - end end function show_results(name,mjob,sjob) - local count = {} - for key,value in pairs(combination) do - for _,id in pairs(tbl.sets) do - if value.item[id] then - count[key] = (count[key] or 0)+1 - end + local count = {} + for key,value in pairs(combination) do + for _,id in pairs(tbl.sets) do + if value.item[id] then + count[key] = (count[key] or 0)+1 + end + end + if count[key] and count[key] > 1 then + for stat,multi in pairs(value.stats) do + tbl[stat] = (tbl[stat] or 0)+multi*math.min((count[key]+value.type),5) + end + end end - if count[key] and count[key] > 1 then - for stat,multi in pairs(value.stats) do - tbl[stat] = (tbl[stat] or 0)+multi*math.min((count[key]+value.type),5) - end + local stats = settings[mjob] + local head = '<'..mjob..'/'..(sjob or '')..'>' + windower.add_to_chat(160,string.color(name,1,160)..': '..string.color(head,160,160)) + for index,key in ipairs(windower.regex.split(stats,'[|]')) do + local value = tbl[string.lower(key)] + local color = {value and 1 or 160,value and 166 or 160} + windower.add_to_chat(160,' ['..string.color(key,color[1],160)..'] '..string.color(tostring(value),color[2],160)) end - end - local stats = settings[mjob] - local head = '<'..mjob..'/'..sjob..'>' - windower.add_to_chat(160,string.color(name,1,160)..': '..string.color(head,160,160)) - for index,key in ipairs(windower.regex.split(stats,'[|]')) do - local value = tbl[string.lower(key)] - local color = {value and 1 or 160,value and 166 or 160} - windower.add_to_chat(160,' ['..string.color(key,color[1],160)..'] '..string.color(tostring(value),color[2],160)) - end - tbl = {} + tbl = {} end integrate = { - --[[integrate same property.information needed for development. @from20020516]] - ['quad atk'] = 'quadruple attack', - ['triple atk'] = 'triple attack', - ['double atk'] = 'double attack', - ['dblatk'] = 'double attack', - ['blood pact ability delay'] = 'blood pact delay', - ['blood pact ability delay ii'] = 'blood pact delay ii', - ['blood pact ab. del. ii'] = 'blood pact delay ii', - ['blood pact recast time ii'] = 'blood pact delay ii', - ['blood pact dmg'] = 'blood pact damage', - ['enhancing magic duration'] = 'enhancing magic effect duration', - ['eva'] = 'evasion', - ['indicolure spell duration'] = 'indicolure effect duration', - ['mag eva'] = 'magic evasion', - ['magic atk bonus'] = 'magic attack bonus', - ['magatkbns'] = 'magic attack bonus', - ['mag atk bonus'] = 'magic attack bonus', - ['mag acc'] = 'magic accuracy', - ['m acc'] = 'magic accuracy', - ['r acc'] = 'ranged accuracy', - ['magic burst dmg'] = 'magic burst damage', - ['mag dmg'] = 'magic damage', - ['crithit rate'] = 'critical hit rate', + --[[integrate same property.information needed for development. @from20020516]] + ['quad atk'] = 'quadruple attack', + ['triple atk'] = 'triple attack', + ['double atk'] = 'double attack', + ['dblatk'] = 'double attack', + ['blood pact ability delay'] = 'blood pact delay', + ['blood pact ability delay ii'] = 'blood pact delay ii', + ['blood pact ab. del. ii'] = 'blood pact delay ii', + ['blood pact recast time ii'] = 'blood pact delay ii', + ['blood pact dmg'] = 'blood pact damage', + ['enhancing magic duration'] = 'enhancing magic effect duration', + ['eva'] = 'evasion', + ['indicolure spell duration'] = 'indicolure effect duration', + ['mag eva'] = 'magic evasion', + ['magic atk bonus'] = 'magic attack bonus', + ['magatkbns'] = 'magic attack bonus', + ['mag atk bonus'] = 'magic attack bonus', + ['mag acc'] = 'magic accuracy', + ['m acc'] = 'magic accuracy', + ['r acc'] = 'ranged accuracy', + ['magic burst dmg'] = 'magic burst damage', + ['mag dmg'] = 'magic damage', + ['crithit rate'] = 'critical hit rate', } enhanced = { - [10392] = 'cursna+10', --Malison Medallion - [10393] = 'cursna+15', --Debilis Medallion - [10394] = 'fast cast+5', --Orunmila's Torque - [10469] = 'fast cast+10', --Eirene's Manteel - [10752] = 'fast cast+2', --Prolix Ring - [10790] = 'cursna+10', --Ephedra Ring - [10791] = 'cursna+15', --Haoma's Ring - [10802] = 'fast cast+5', --Majorelle Shield - [10826] = 'fast cast+3', --Witful Belt - [10838] = 'dual wield+5', --Patentia Sash - [11000] = 'fast cast+3', --Swith Cape - [11001] = 'fast cast+4', --Swith Cape +1 - [11037] = 'stoneskin+10', --Earthcry Earring - [11051] = 'increases resistance to all status ailments+5', --Hearty Earring - [11544] = 'fast cast+1', --Veela Cape - [11602] = 'martial arts+10', --Cirque Necklace - [11603] = 'dual wield+3', --Charis Necklace - [11615] = 'fast cast+5', --Orison Locket - [11707] = 'fast cast+2', --Estq. Earring - [11711] = 'rewards+2', --Ferine Earring - [11715] = 'dual wield+1', --Iga Mimikazari - [11722] = 'sublimation+1', --Savant's Earring - [11732] = 'dual wield+5', --Nusku's Sash - [11734] = 'martial arts+10', --Shaolin Belt - [11735] = 'snapshot+3', --Impulse Belt - [11753] = 'aquaveil+1', --Emphatikos Rope - [11775] = 'occult acumen+20', --Oneiros Rope - [11856] = 'fast cast+10', --Anhur Robe - [13177] = 'stoneskin+30', --Stone Gorget - [14739] = 'dual wield+5', --Suppanomimi - [14812] = 'fast cast+2', --Loquac. Earring - [14813] = 'double attack+5', --Brutal Earring - [15857] = 'drain and aspir potency+5', --Excelsis Ring - [15960] = 'stoneskin+20', --Siegel Sash - [15962] = 'magic burst damage+5', --Static Earring - [16209] = 'snapshot+5', --Navarch's Mantle - [19062] = 'divine benison+1', --Yagrush80 - [19082] = 'divine benison+2', --Yagrush85 - [19260] = 'dual wield+3', --Raider's Bmrng. - [19614] = 'divine benison+3', --Yagrush90 - [19712] = 'divine benison+3', --Yagrush95 - [19821] = 'divine benison+3', --Yagrush99 - [19950] = 'divine benison+3', --Yagrush99+ - [20509] = 'counter+14', --Spharai119AG - [20511] = 'martial arts+55', --Kenkonken119AG - [21062] = 'divine benison+3', --Yagrush119 - [21063] = 'divine benison+3', --Yagrush119+ - [21078] = 'divine benison+3', --Yagrush119AG - [21201] = 'fast cast+2', --Atinian Staff +1 - [27768] = 'fast cast+5', --Cizin Helm - [27775] = 'fast cast+10', --Nahtirah Hat - [28054] = 'fast cast+7', --Gendewitha Gages - [28058] = 'snapshot+4', --Manibozho Gloves - [28184] = 'fast cast+5', --Orvail Pants +1 - [28197] = 'snapshot+9', --Nahtirah Trousers - [28206] = 'fast cast+10', --Geomancy Pants - [28335] = 'cursna+10', --Gende. Galoshes - [28582] = 'magic burst damage+5', --Locus Ring - [28619] = 'cursna+15', --Mending Cape - [28631] = 'elemental siphon+30', --Conveyance Cape - [28637] = 'fast cast+7', --Lifestream Cape + [10392] = 'cursna+10', --Malison Medallion + [10393] = 'cursna+15', --Debilis Medallion + [10394] = 'fast cast+5', --Orunmila's Torque + [10469] = 'fast cast+10', --Eirene's Manteel + [10752] = 'fast cast+2', --Prolix Ring + [10790] = 'cursna+10', --Ephedra Ring + [10791] = 'cursna+15', --Haoma's Ring + [10802] = 'fast cast+5', --Majorelle Shield + [10826] = 'fast cast+3', --Witful Belt + [10838] = 'dual wield+5', --Patentia Sash + [11000] = 'fast cast+3', --Swith Cape + [11001] = 'fast cast+4', --Swith Cape +1 + [11037] = 'stoneskin+10', --Earthcry Earring + [11051] = 'increases resistance to all status ailments+5', --Hearty Earring + [11544] = 'fast cast+1', --Veela Cape + [11602] = 'martial arts+10', --Cirque Necklace + [11603] = 'dual wield+3', --Charis Necklace + [11615] = 'fast cast+5', --Orison Locket + [11707] = 'fast cast+2', --Estq. Earring + [11711] = 'rewards+2', --Ferine Earring + [11715] = 'dual wield+1', --Iga Mimikazari + [11722] = 'sublimation+1', --Savant's Earring + [11732] = 'dual wield+5', --Nusku's Sash + [11734] = 'martial arts+10', --Shaolin Belt + [11735] = 'snapshot+3', --Impulse Belt + [11753] = 'aquaveil+1', --Emphatikos Rope + [11775] = 'occult acumen+20', --Oneiros Rope + [11856] = 'fast cast+10', --Anhur Robe + [13177] = 'stoneskin+30', --Stone Gorget + [14739] = 'dual wield+5', --Suppanomimi + [14812] = 'fast cast+2', --Loquac. Earring + [14813] = 'double attack+5', --Brutal Earring + [15857] = 'drain and aspir potency+5', --Excelsis Ring + [15960] = 'stoneskin+20', --Siegel Sash + [15962] = 'magic burst damage+5', --Static Earring + [16209] = 'snapshot+5', --Navarch's Mantle + [19062] = 'divine benison+1', --Yagrush80 + [19082] = 'divine benison+2', --Yagrush85 + [19260] = 'dual wield+3', --Raider's Bmrng. + [19614] = 'divine benison+3', --Yagrush90 + [19712] = 'divine benison+3', --Yagrush95 + [19821] = 'divine benison+3', --Yagrush99 + [19950] = 'divine benison+3', --Yagrush99+ + [20509] = 'counter+14', --Spharai119AG + [20511] = 'martial arts+55', --Kenkonken119AG + [21062] = 'divine benison+3', --Yagrush119 + [21063] = 'divine benison+3', --Yagrush119+ + [21078] = 'divine benison+3', --Yagrush119AG + [21201] = 'fast cast+2', --Atinian Staff +1 + [27768] = 'fast cast+5', --Cizin Helm + [27775] = 'fast cast+10', --Nahtirah Hat + [28054] = 'fast cast+7', --Gendewitha Gages + [28058] = 'snapshot+4', --Manibozho Gloves + [28184] = 'fast cast+5', --Orvail Pants +1 + [28197] = 'snapshot+9', --Nahtirah Trousers + [28206] = 'fast cast+10', --Geomancy Pants + [28335] = 'cursna+10', --Gende. Galoshes + [28582] = 'magic burst damage+5', --Locus Ring + [28619] = 'cursna+15', --Mending Cape + [28631] = 'elemental siphon+30', --Conveyance Cape + [28637] = 'fast cast+7', --Lifestream Cape } combination={ - ['af']={item=S{ - 23040,23041,23042,23043,23044,23045,23046,23047,23048,23049,23050,23051,23052,23053,23055,23056,23057,23058,23059,23060,23061,23062, - 23107,23108,23109,23110,23111,23112,23113,23114,23115,23116,23117,23118,23119,23120,23122,23123,23124,23125,23126,23127,23128,23129, - 23174,23175,23176,23177,23178,23179,23180,23181,23182,23183,23184,23185,23186,23187,23189,23190,23191,23192,23193,23194,23195,23196, - 23241,23242,23243,23244,23245,23246,23247,23248,23249,23250,23251,23252,23253,23254,23256,23257,23258,23259,23260,23261,23262,23263, - 23308,23309,23310,23311,23312,23313,23314,23315,23316,23317,23318,23319,23320,23321,23323,23324,23325,23326,23327,23328,23329,23330, - 23375,23376,23377,23378,23379,23380,23381,23382,23383,23384,23385,23386,23387,23388,23390,23391,23392,23393,23394,23395,23396,23397, - 23442,23443,23444,23445,23446,23447,23448,23449,23450,23451,23452,23453,23454,23455,23457,23458,23459,23460,23461,23462,23463,23464, - 23509,23510,23511,23512,23513,23514,23515,23516,23517,23518,23519,23520,23521,23522,23524,23525,23526,23527,23528,23529,23530,23531, - 23576,23577,23578,23579,23580,23581,23582,23583,23584,23585,23586,23587,23588,23589,23591,23592,23593,23594,23595,23596,23597,23598, - 23643,23644,23645,23646,23647,23648,23649,23650,23651,23652,23653,23654,23655,23656,23658,23659,23660,23661,23662,23663,23664,23665, - 26085,26191},stats={['accuracy']=15,['magic accuracy']=15,['ranged accuracy']=15},type=-1}, - ['af_smn']={item=S{23054,23121,23188,23255,23322,23389,23456,23523,23590,23657,26342}, - stats={['pet: accuracy']=15,['pet: magic accuracy']=15,['pet: ranged accuracy']=15},type=-1}, - ['adhemar']={item=S{25614,25687,27118,27303,27474},stats={['critical hit rate']=2},type=0}, - ['amalric']={item=S{25616,25689,27120,27305,27476},stats={['magic attack bonus']=10},type=0}, - ['apogee']={item=S{26677,26853,27029,27205,27381},stats={['blood pact damage']=2},type=0}, - ['argosy']={item=S{26673,26849,27025,27201,27377},stats={['double attack']=2},type=0}, - ['emicho']={item=S{25610,25683,27114,27299,27470},stats={['double attack']=2},type=0}, - ['carmine']={item=S{26679,26855,27031,27207,27383},stats={['accuracy']=10},type=0}, - ['kaykaus']={item=S{25618,25691,27122,27307,27478},stats={['cure potency ii']=2},type=0}, - ['lustratio']={item=S{26669,26845,27021,27197,27373},stats={['weapon skill damage']=2},type=0}, - ['rao']={item=S{26675,26851,27027,27203,27379},stats={['matial arts']=2},type=0}, - ['ryuo']={item=S{25612,25685,27116,27301,27472},stats={['attack']=10},type=0}, - ['souveran']={item=S{26671,26847,27023,27199,27375},stats={['damage taken']=2},type=0}, - ['ayanmo']={item=S{25572,25795,25833,25884,25951},stats={['str']=8,['vit']=8,['mnd']=8},type=-1}, - ['flamma']={item=S{25569,25797,25835,25886,25953},stats={['str']=8,['dex']=8,['vit']=8},type=-1}, - ['mallquis']={item=S{25571,25799,25837,25888,25955},stats={['vit']=8,['int']=8,['mnd']=8},type=-1}, - ['Mummu']={item=S{25570,25798,25836,25887,25954},stats={['dex']=8,['agi']=8,['chr']=8},type=-1}, - ['tali\'ah']={item=S{25573,25796,25834,25885,25952},stats={['vit']=8,['dex']=8,['chr']=8},type=-1}, - ['Hizamaru']={item=S{25576,25792,25830,25881,25948},stats={['counter']=2},type=-1}, - ['Inyanga']={item=S{25577,25793,25831,25882,25949},stats={['refresh']=1},type=-1}, - ['jhakri']={item=S{25578,25794,25832,25883,25950},stats={['fast cast']=3},type=-1}, - ['meghanada']={item=S{25575,25791,25829,25880,25947},stats={['regen']=3},type=-1}, - ['Sulevia\'s']={item=S{25574,25790,25828,25879,25946},stats={['subtle blow']=5},type=-1}, + ['af']={item=S{ + 23040,23041,23042,23043,23044,23045,23046,23047,23048,23049,23050,23051,23052,23053,23055,23056,23057,23058,23059,23060,23061,23062, + 23107,23108,23109,23110,23111,23112,23113,23114,23115,23116,23117,23118,23119,23120,23122,23123,23124,23125,23126,23127,23128,23129, + 23174,23175,23176,23177,23178,23179,23180,23181,23182,23183,23184,23185,23186,23187,23189,23190,23191,23192,23193,23194,23195,23196, + 23241,23242,23243,23244,23245,23246,23247,23248,23249,23250,23251,23252,23253,23254,23256,23257,23258,23259,23260,23261,23262,23263, + 23308,23309,23310,23311,23312,23313,23314,23315,23316,23317,23318,23319,23320,23321,23323,23324,23325,23326,23327,23328,23329,23330, + 23375,23376,23377,23378,23379,23380,23381,23382,23383,23384,23385,23386,23387,23388,23390,23391,23392,23393,23394,23395,23396,23397, + 23442,23443,23444,23445,23446,23447,23448,23449,23450,23451,23452,23453,23454,23455,23457,23458,23459,23460,23461,23462,23463,23464, + 23509,23510,23511,23512,23513,23514,23515,23516,23517,23518,23519,23520,23521,23522,23524,23525,23526,23527,23528,23529,23530,23531, + 23576,23577,23578,23579,23580,23581,23582,23583,23584,23585,23586,23587,23588,23589,23591,23592,23593,23594,23595,23596,23597,23598, + 23643,23644,23645,23646,23647,23648,23649,23650,23651,23652,23653,23654,23655,23656,23658,23659,23660,23661,23662,23663,23664,23665, + 26085,26191},stats={['accuracy']=15,['magic accuracy']=15,['ranged accuracy']=15},type=-1}, + ['af_smn']={item=S{23054,23121,23188,23255,23322,23389,23456,23523,23590,23657,26342}, + stats={['pet: accuracy']=15,['pet: magic accuracy']=15,['pet: ranged accuracy']=15},type=-1}, + ['adhemar']={item=S{25614,25687,27118,27303,27474},stats={['critical hit rate']=2},type=0}, + ['amalric']={item=S{25616,25689,27120,27305,27476},stats={['magic attack bonus']=10},type=0}, + ['apogee']={item=S{26677,26853,27029,27205,27381},stats={['blood pact damage']=2},type=0}, + ['argosy']={item=S{26673,26849,27025,27201,27377},stats={['double attack']=2},type=0}, + ['emicho']={item=S{25610,25683,27114,27299,27470},stats={['double attack']=2},type=0}, + ['carmine']={item=S{26679,26855,27031,27207,27383},stats={['accuracy']=10},type=0}, + ['kaykaus']={item=S{25618,25691,27122,27307,27478},stats={['cure potency ii']=2},type=0}, + ['lustratio']={item=S{26669,26845,27021,27197,27373},stats={['weapon skill damage']=2},type=0}, + ['rao']={item=S{26675,26851,27027,27203,27379},stats={['matial arts']=2},type=0}, + ['ryuo']={item=S{25612,25685,27116,27301,27472},stats={['attack']=10},type=0}, + ['souveran']={item=S{26671,26847,27023,27199,27375},stats={['damage taken']=2},type=0}, + ['ayanmo']={item=S{25572,25795,25833,25884,25951},stats={['str']=8,['vit']=8,['mnd']=8},type=-1}, + ['flamma']={item=S{25569,25797,25835,25886,25953},stats={['str']=8,['dex']=8,['vit']=8},type=-1}, + ['mallquis']={item=S{25571,25799,25837,25888,25955},stats={['vit']=8,['int']=8,['mnd']=8},type=-1}, + ['Mummu']={item=S{25570,25798,25836,25887,25954},stats={['dex']=8,['agi']=8,['chr']=8},type=-1}, + ['tali\'ah']={item=S{25573,25796,25834,25885,25952},stats={['vit']=8,['dex']=8,['chr']=8},type=-1}, + ['Hizamaru']={item=S{25576,25792,25830,25881,25948},stats={['counter']=2},type=-1}, + ['Inyanga']={item=S{25577,25793,25831,25882,25949},stats={['refresh']=1},type=-1}, + ['jhakri']={item=S{25578,25794,25832,25883,25950},stats={['fast cast']=3},type=-1}, + ['meghanada']={item=S{25575,25791,25829,25880,25947},stats={['regen']=3},type=-1}, + ['Sulevia\'s']={item=S{25574,25790,25828,25879,25946},stats={['subtle blow']=5},type=-1}, } From 1717bfcbb0eab884e2ed5fcee8ab76e455f8bc05 Mon Sep 17 00:00:00 2001 From: Sjshovan Date: Thu, 31 May 2018 16:38:05 -0400 Subject: [PATCH 0128/1002] Remove: Removed /data/settings.xml file. Update: licences now display correct author name. Update: README refactored in attempt to meet merge criteria. Update: helpers.lua now requires only colors from constants.lua. Update: constants.lua now returns table of globals for modular support. Update: mountmuzzle.lua refactored in attempt to meet merge criteria. --- addons/MountMuzzle/LICENSE | 2 +- addons/MountMuzzle/README.md | 7 +++--- addons/MountMuzzle/constants.lua | 10 ++++++++- addons/MountMuzzle/data/settings.xml | 6 ------ addons/MountMuzzle/helpers.lua | 11 +++------- addons/MountMuzzle/mountmuzzle.lua | 32 +++++++++++++--------------- 6 files changed, 31 insertions(+), 37 deletions(-) delete mode 100644 addons/MountMuzzle/data/settings.xml diff --git a/addons/MountMuzzle/LICENSE b/addons/MountMuzzle/LICENSE index a66131fcae..99eebd69de 100644 --- a/addons/MountMuzzle/LICENSE +++ b/addons/MountMuzzle/LICENSE @@ -16,7 +16,7 @@ modification, are permitted provided that the following conditions are met: 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 Patrick Finnigan BE LIABLE FOR ANY +DISCLAIMED. IN NO EVENT SHALL Sjshovan (Apogee) 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 diff --git a/addons/MountMuzzle/README.md b/addons/MountMuzzle/README.md index 901d5252b1..cd55859ee2 100644 --- a/addons/MountMuzzle/README.md +++ b/addons/MountMuzzle/README.md @@ -35,12 +35,11 @@ ___ ___ ### Usage -**Manually load** the addon by using one of the following commands: +Manually load the addon by using one of the following commands: //lua load mountmuzzle //lua l mountmuzzle - -**Automatically load** this addon by adding `lua load mountmuzzle` or `lua l mountmuzzle` to the bottom of your `Windower4/scripts/init.txt` file. + ___ ### Commands @@ -100,7 +99,7 @@ Reloads the Mount Muzzle addon. Below are the equivalent ways of calling the com ___ ### Support **Having Issues with this addon?** -* Please let me know [here.](https://github.com/Ap0gee/MountMuzzle/issues/new) +* Please let me know [here](https://github.com/Ap0gee/MountMuzzle/issues/new). **Have something to say?** * Send me some feedback here: diff --git a/addons/MountMuzzle/constants.lua b/addons/MountMuzzle/constants.lua index 9aa9d35f3d..faab1affde 100644 --- a/addons/MountMuzzle/constants.lua +++ b/addons/MountMuzzle/constants.lua @@ -17,7 +17,7 @@ modification, are permitted provided that the following conditions are met: 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 Patrick Finnigan BE LIABLE FOR ANY +DISCLAIMED. IN NO EVENT SHALL Sjshovan (Apogee) 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 @@ -91,4 +91,12 @@ muzzles = { song = music.songs.zone, description = 'Current Zone Music' } +} + +return { + packets = packets, + player = player, + music = music, + colors = colors, + muzzles = muzzles } \ No newline at end of file diff --git a/addons/MountMuzzle/data/settings.xml b/addons/MountMuzzle/data/settings.xml deleted file mode 100644 index d71ef1b48d..0000000000 --- a/addons/MountMuzzle/data/settings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - silent - - diff --git a/addons/MountMuzzle/helpers.lua b/addons/MountMuzzle/helpers.lua index 9f25e727e8..682fec120f 100644 --- a/addons/MountMuzzle/helpers.lua +++ b/addons/MountMuzzle/helpers.lua @@ -17,7 +17,7 @@ modification, are permitted provided that the following conditions are met: 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 Patrick Finnigan BE LIABLE FOR ANY +DISCLAIMED. IN NO EVENT SHALL Sjshovan (Apogee) 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 @@ -26,11 +26,7 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] -require("constants") - -function ucFirst(str) - return (str:gsub("^%l", string.upper)) -end +local colors = require("constants").colors function buildHelpCommandEntry(command, description) local short_name = "mm":color(colors.primary) @@ -76,5 +72,4 @@ function displayResponse(response, color) color = color or colors.info windower.add_to_chat(color, response) windower.console.write(response:strip_colors()) -end - +end \ No newline at end of file diff --git a/addons/MountMuzzle/mountmuzzle.lua b/addons/MountMuzzle/mountmuzzle.lua index de7a7dd764..03aead5591 100644 --- a/addons/MountMuzzle/mountmuzzle.lua +++ b/addons/MountMuzzle/mountmuzzle.lua @@ -17,7 +17,7 @@ modification, are permitted provided that the following conditions are met: 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 Patrick Finnigan BE LIABLE FOR ANY +DISCLAIMED. IN NO EVENT SHALL Sjshovan (Apogee) 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 @@ -28,13 +28,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'Mount Muzzle' _addon.author = 'Sjshovan (Apogee) sjshovan@gmail.com' -_addon.version = '0.9.2' +_addon.version = '0.9.3' _addon.commands = {'mountmuzzle', 'muzzle', 'mm'} local _logger = require('logger') local _config = require('config') local _packets = require('packets') +require("constants") require('helpers') local mounted = false @@ -64,10 +65,10 @@ local help = { buildHelpSeperator('=', 23), buildHelpTitle('Types'), buildHelpSeperator('=', 23), - buildHelpTypeEntry(ucFirst(muzzles.silent.name), muzzles.silent.description), - buildHelpTypeEntry(ucFirst(muzzles.normal.name), muzzles.normal.description), - buildHelpTypeEntry(ucFirst(muzzles.choco.name), muzzles.choco.description), - buildHelpTypeEntry(ucFirst(muzzles.zone.name), muzzles.zone.description), + buildHelpTypeEntry(muzzles.silent.name:ucfirst(), muzzles.silent.description), + buildHelpTypeEntry(muzzles.normal.name:ucfirst(), muzzles.normal.description), + buildHelpTypeEntry(muzzles.choco.name:ucfirst(), muzzles.choco.description), + buildHelpTypeEntry(muzzles.zone.name:ucfirst(), muzzles.zone.description), buildHelpSeperator('=', 23), }, } @@ -109,19 +110,16 @@ function requestInject() end function injectMuzzleMusic() - windower.packets.inject_incoming( - packets.inbound.music_change.id, - 'IHH':pack(packets.inbound.music_change.id, - music.types.mount, - resolveCurrentMuzzle().song - ) - ) + _packets.inject(_packets.new('incoming', packets.inbound.music_change.id, { + ['BGM Type'] = music.types.mount, + ['Song ID'] = resolveCurrentMuzzle().song, + })) end function handleInjectionNeeds() if needs_inject and playerIsMounted() then injectMuzzleMusic() - needs_inject = false; + needs_inject = false; end end @@ -139,7 +137,7 @@ windower.register_event('zone change', requestInject) windower.register_event('addon command', function(command, ...) if command then - local command = command:lower() + command = command:lower() else display_help(help.commands) return @@ -165,12 +163,12 @@ windower.register_event('addon command', function(command, ...) else needs_inject = true setMuzzle(muzzle) - response_message = 'Updated current muzzle to %s.':format(ucFirst(muzzle):color(colors.secondary)) + response_message = 'Updated current muzzle to %s.':format(muzzle:ucfirst():color(colors.secondary)) end elseif command == 'get' then respond = true - response_message = 'Current muzzle is %s.':format(ucFirst(getMuzzle()):color(colors.secondary)) + response_message = 'Current muzzle is %s.':format(getMuzzle():ucfirst():color(colors.secondary)) elseif command == 'default' then respond = true From f5b4f70994174e8d95021cc1cdd879f73e49667b Mon Sep 17 00:00:00 2001 From: Sjshovan Date: Thu, 31 May 2018 16:54:40 -0400 Subject: [PATCH 0129/1002] Update: Readme updated in attempt to meet merge criteria. --- addons/MountMuzzle/README.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/addons/MountMuzzle/README.md b/addons/MountMuzzle/README.md index cd55859ee2..480b1b246b 100644 --- a/addons/MountMuzzle/README.md +++ b/addons/MountMuzzle/README.md @@ -1,5 +1,5 @@ **Author:** [Sjshovan (Apogee)](https://github.com/Ap0gee) -**Version:** v0.9.2 +**Version:** v0.9.3 # Mount Muzzle @@ -30,7 +30,7 @@ ___ 2. Click on `Releases`. 3. Click on the `Source code (zip)` link within the latest release to download. 4. Extract the zipped folder to `Windower4/addons/`. -5. Rename the folder to remove the version tag (`-v0.9.2`). The folder should be named `MountMuzzle`. +5. Rename the folder to remove the version tag (`-v0.9.3`). The folder should be named `MountMuzzle`. ___ ### Usage @@ -113,6 +113,14 @@ ___ ___ ### Change Log +**v0.9.3** - 5/31/2018 +- **Remove:** Removed /data/settings.xml file. +- **Update:** licences now display correct author name. +- **Update:** README refactored in attempt to meet merge criteria. +- **Update:** helpers.lua now requires only colors from constants.lua. +- **Update:** constants.lua now returns table of globals for modular support. +- **Update:** mountmuzzle.lua refactored in attempt to meet merge criteria. + **v0.9.2** - 5/24/2018 - **Fix:** Zone music gets silenced if player enters reive on mount with zone muzzle selected. - **Fix:** Player reaches error if no arguments are given upon invoking the addon. From 3e6e64249c639124da72ef197ff6a6bdaaf0e0c8 Mon Sep 17 00:00:00 2001 From: Sjshovan Date: Thu, 31 May 2018 17:05:10 -0400 Subject: [PATCH 0130/1002] Fix: incorrect spacing in changelog. --- addons/MountMuzzle/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/MountMuzzle/README.md b/addons/MountMuzzle/README.md index 480b1b246b..8006ca1624 100644 --- a/addons/MountMuzzle/README.md +++ b/addons/MountMuzzle/README.md @@ -116,7 +116,7 @@ ___ **v0.9.3** - 5/31/2018 - **Remove:** Removed /data/settings.xml file. - **Update:** licences now display correct author name. -- **Update:** README refactored in attempt to meet merge criteria. +- **Update:** README refactored in attempt to meet merge criteria. - **Update:** helpers.lua now requires only colors from constants.lua. - **Update:** constants.lua now returns table of globals for modular support. - **Update:** mountmuzzle.lua refactored in attempt to meet merge criteria. From 6323554270e9b293342bc9c77e3312c84ad43ee2 Mon Sep 17 00:00:00 2001 From: Sjshovan Date: Thu, 31 May 2018 17:33:14 -0400 Subject: [PATCH 0131/1002] Update: Add addon to addons.xml. --- addons/addons.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/addons/addons.xml b/addons/addons.xml index 5bc38003ff..5c673373b9 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -335,6 +335,13 @@ A compass to show your position relative to the target (not players) for geo and has a setup for Sneak attack https://discord.gg/b275nMv + + MountMuzzle + Sjshovan (Apogee) + Allows the user to change or remove the default mount music. + https://github.com/Windower/Lua/issues + https://discord.gg/b275nMv + Nostrum Creates a click-able on-screen macro to help avoid targeting problems while curing. From 90053b695770a5cb5f093862ca7c958a9479dd22 Mon Sep 17 00:00:00 2001 From: from20020516 Date: Fri, 1 Jun 2018 14:50:07 +0900 Subject: [PATCH 0132/1002] some fix before merge. --- addons/Trusts/Trusts.lua | 544 ++++++++++++++++++++------------------- 1 file changed, 281 insertions(+), 263 deletions(-) diff --git a/addons/Trusts/Trusts.lua b/addons/Trusts/Trusts.lua index d840698cd5..99800e75d8 100644 --- a/addons/Trusts/Trusts.lua +++ b/addons/Trusts/Trusts.lua @@ -6,13 +6,13 @@ 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. + 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 checkparam nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Trusts 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 @@ -36,303 +36,321 @@ math.randomseed(os.clock()) require('logger') windower.register_event('load',function() - defaults = { - auto=true, - language=windower.ffxi.get_info().language, - sets={ - ['default']={ - English={ - ['1']='Valaineral', - ['2']='Mihli Aliapoh', - ['3']='Tenzen', - ['4']='Adelheid', - ['5']='Joachim'}, - Japanese={ - ['1']='ヴァレンラール', - ['2']='ミリ・アリアポー', - ['3']='テンゼン', - ['4']='アーデルハイト', - ['5']='ヨアヒム'}}[windower.ffxi.get_info().language]}, - wait={ - ['aftercast']=3, - ['retr']=1.25, - ['retrall']=3},} - settings = config.load(defaults) - lang = string.lower(settings.language) + defaults = { + auto=true, + language=windower.ffxi.get_info().language, + sets={ + ['default']={ + English={ + ['1']='Valaineral', + ['2']='Mihli Aliapoh', + ['3']='Tenzen', + ['4']='Adelheid', + ['5']='Joachim'}, + Japanese={ + ['1']='ヴァレンラール', + ['2']='ミリ・アリアポー', + ['3']='テンゼン', + ['4']='アーデルハイト', + ['5']='ヨアヒム'}}[windower.ffxi.get_info().language]}, + wait={ + ['aftercast']=3, + ['retr']=1.25, + ['retrall']=3},} + settings = config.load(defaults) + lang = string.lower(settings.language) + player = windower.ffxi.get_player() +end) + +windower.register_event('login',function() + player = windower.ffxi.get_player() end) windower.register_event('addon command',function(...) - cmd = {...} - if S{'save','s'}[cmd[1]] then - save_set(cmd[2]) - elseif S{'check','c'}[cmd[1]] then - check_learned() - else - call_set(cmd[1] or 'default') - end + cmd = {...} + if cmd[1] == 'help' then + local chat = windower.add_to_chat + local color = string.color + chat(1,'Trusts - Command List:') + chat(207,'//tru '..color('save ',166,160)..' --Save trusts in current party.') + chat(207,'//tru '..color('',166,160)..' --Calls trusts you saved.') + chat(207,'//tru '..color('random',166,160)..' --What\'s your fortune today?') + chat(207,'//tru '..color('check',166,160)..' --List of unlearned trusts. gotta catch \'em all!') + elseif cmd[1] == 'save' then + save_set(cmd[2]) + elseif cmd[1] == 'check' then + check_learned() + else + call_set(cmd[1] or 'default') + end end) function save_set(set) - settings.sets[set] = {} - local trust_ind = 0 - for i=1,5 do - local trust = windower.ffxi.get_party()['p'..i] - if trust and trust.mob.spawn_type == 14 then - trust_ind = trust_ind + 1 - settings.sets[set][tostring(trust_ind)]=trusts:with('models',trust.mob.models[1])[lang] + settings.sets[set] = {} + local trust_ind = 0 + local get_party = windower.ffxi.get_party() + for i=1,5 do + local trust = get_party['p'..i] + if trust and trust.mob.spawn_type == 14 then + trust_ind = trust_ind + 1 + settings.sets[set][tostring(trust_ind)]=trusts:with('models',trust.mob.models[1])[lang] + end end - end - settings:save('all') - log('set '..set..' saved.') + settings:save('all') + log('set '..set..' saved.') end function check_lang(entity) - return {japanese=entity.japanese,english=entity.english}[lang]; + return {japanese=entity.japanese,english=entity.english}[lang]; end function check_limit() - for i,v in pairs(windower.ffxi.get_key_items()) do - --Trust permit,Rhapsody in.. - limit = S{2497,2499,2501}[v] and 3 or v==2884 and 4 or v==2886 and 5 or limit or 0 - end - return limit; + for i,v in pairs(windower.ffxi.get_key_items()) do + --Trust permit,Rhapsody in.. + limit = S{2497,2499,2501}[v] and 3 or v==2884 and 4 or v==2886 and 5 or limit or 0 + end + return limit; end function call_trust() - if #queue > 0 then - windower.send_command('input /ma "'..windower.to_shift_jis(check_lang(queue[1]))..'" ') - end + if #queue > 0 then + windower.chat.input('/ma "'..windower.to_shift_jis(check_lang(queue[1]))..'" ') + end end function check_exist() - local party = {} --include only trusts. --['name']=models - local party_ind = {} -- index of trust's name in current party. {'name1','name2',...,'name5'} - for i=1,5 do - local member = windower.ffxi.get_party()['p'..i] - if member then - if member.mob.spawn_type == 14 then - party[member.name]= member.mob.models[1] - table.insert(party_ind,member.name) - end + local party = {} --include only trusts. --['name']=models + local party_ind = {} -- index of trust's name in current party. {'name1','name2',...,'name5'} + local get_party = windower.ffxi.get_party() + for i=1,5 do + local member = get_party['p'..i] + if member then + if member.mob.spawn_type == 14 then + party[member.name] = member.mob.models[1] + table.insert(party_ind,member.name) + end + end end - end - return {party,party_ind}; + return {party,party_ind}; end function call_set(set) - queue = {} --trusts to be cast. - settings = config.load() - local party,party_ind = unpack(check_exist()) - local limit = check_limit() --upper limit # of calls trust in current player. - local time = os.clock() --window open + queue = {} --trusts to be cast. + settings = config.load() + local party,party_ind = unpack(check_exist()) + local limit = check_limit() --upper limit # of calls trust in current player. + local time = os.clock() --window open + local get_spells = windower.ffxi.get_spells() + local get_spell_recasts = windower.ffxi.get_spell_recasts() - if set == 'random' then - local checked = {} - local others = windower.ffxi.get_party().party1_count - #party_ind - 1 --# of human in party exept . - - if limit == #party_ind then - windower.send_command('input /retr all') - calls = limit - coroutine.sleep(settings.wait.retrall) - else - calls = limit - #party_ind - others - end + if set == 'random' then + local checked = {} + local others = windower.ffxi.get_party().party1_count - #party_ind - 1 --# of human in party exept . - repeat - local index = trusts[math.random(1,#trusts)] - if not table.find(checked,index.name) then - table.insert(checked,index.name) - if windower.ffxi.get_spells()[index.id] and windower.ffxi.get_spell_recasts()[index.id] == 0 then - table.insert(queue,index) + if limit == #party_ind then + windower.chat.input('/retr all') + calls = limit + coroutine.sleep(settings.wait.retrall) + else + calls = limit - #party_ind - others end - end - until #queue >= calls or #checked >= 103 --# of unique names w/o Cornelia - elseif settings.sets[set] then - retr = {unpack(party_ind)} - for i=1,limit do - if settings.sets[set][tostring(i)] then - local entity = trusts:with(lang,settings.sets[set][tostring(i)]) - if not party[entity.name] - or party[entity.name] ~= entity.models then - if windower.ffxi.get_spell_recasts()[entity.id] == 0 then - if windower.ffxi.get_spells()[entity.id] then - table.insert(queue,entity) + repeat + local index = trusts[math.random(1,#trusts)] + if not table.find(checked,index.name) then + table.insert(checked,index.name) + if get_spells[index.id] and get_spell_recasts[index.id] == 0 then + table.insert(queue,index) + end + end + until #queue >= calls or #checked >= 103 --# of unique names w/o Cornelia + + elseif settings.sets[set] then + retr = {unpack(party_ind)} + for i=1,limit do + if settings.sets[set][tostring(i)] then + local entity = trusts:with(lang,settings.sets[set][tostring(i)]) + if not party[entity.name] + or party[entity.name] ~= entity.models then + if get_spell_recasts[entity.id] == 0 then + if get_spells[entity.id] then + table.insert(queue,entity) + else + table.remove(retr,table.find(retr,party_ind[i])) + error('You aren\'t trusted by '..entity.english..'.') + end + else + table.remove(retr,table.find(retr,party_ind[i])) + local recast = math.floor(get_spell_recasts[entity.id] / 6) / 10 + log(entity.english..' needs '..recast..' secs break.') + end + else + table.remove(retr,table.find(retr,entity.name)) + if settings.auto then + log(entity.english..' already exists.') + end + end + end + end + for index,name in pairs(retr) do + if #retr == #party_ind then + windower.chat.input('/retr all') + coroutine.sleep(settings.wait.retrall) + break; else - table.remove(retr,table.find(retr,party_ind[i])) - error('You aren\'t trusted by '..entity.english..'.') + windower.chat.input('/retr '..name) + coroutine.sleep(settings.wait.retr) end - else - table.remove(retr,table.find(retr,party_ind[i])) - local recast = math.floor(windower.ffxi.get_spell_recasts()[entity.id] / 6) / 10 - log(entity.english..' needs '..recast..' secs break.') - end - else - table.remove(retr,table.find(retr,entity.name)) - if settings.auto then - log(entity.english..' already exists.') - end end - end - end - for index,name in pairs(retr) do - if #retr == #party_ind then - windower.send_command('input /retr all') - coroutine.sleep(settings.wait.retrall) - break; - else - windower.send_command('input /retr '..name) - coroutine.sleep(settings.wait.retr) - end + else + error('Unknown set name '..(set or '')) end - else - error('Unknown set name '..(set or '')) - end - --if /retr then wait at least 3secs. - local delay = (limit - #party_ind) == 0 and math.max(0,settings.wait.retrall + time - os.clock()) or 0 - coroutine.schedule(call_trust,delay) + --if /retr then wait at least 3secs. + local delay = (limit - #party_ind) == 0 and math.max(0,settings.wait.retrall + time - os.clock()) or 0 + coroutine.schedule(call_trust,delay) end windower.register_event('action', function(act) - if settings.auto and act.actor_id == windower.ffxi.get_player().id and queue and #queue > 0 then - if act.category == 4 and act.param == table.remove(queue,1).id then - coroutine.schedule(call_trust,settings.wait.aftercast) - elseif act.category == 8 and act.param == 28787 and act.targets[1].actions[1].param == queue[1].id then - coroutine.schedule(call_trust,settings.wait.aftercast) + if settings.auto and act.actor_id == player.id and queue and #queue > 0 then + if act.category == 4 and act.param == table.remove(queue,1).id then + coroutine.schedule(call_trust,settings.wait.aftercast) + elseif act.category == 8 and act.param == 28787 and act.targets[1].actions[1].param == queue[1].id then + coroutine.schedule(call_trust,settings.wait.aftercast) + end end - end end) function check_learned() - local learned = {} - for i,value in ipairs(trusts) do - if windower.ffxi.get_spells()[value.id] == false and not value.english:endswith('(UC)') then - table.insert(learned,value.id) - log(check_lang(value)) + local learned = {} + local get_spells = windower.ffxi.get_spells() + for i,value in ipairs(trusts) do + if get_spells[value.id] == false and not value.english:endswith('(UC)') then + table.insert(learned,value.id) + log(check_lang(value)) + end end - end - log('You haven\'t trusted yet from '..#learned..' trusts.') + log('You haven\'t trusted yet from '..#learned..' trusts.') end trusts = T{ - [1]={id=896,japanese="シャントット",english="Shantotto",name="Shantotto",models=3000}, - [2]={id=897,japanese="ナジ",english="Naji",name="Naji",models=3001}, - [3]={id=898,japanese="クピピ",english="Kupipi",name="Kupipi",models=3002}, - [4]={id=899,japanese="エグセニミル",english="Excenmille",name="Excenmille",models=3003}, - [5]={id=900,japanese="アヤメ",english="Ayame",name="Ayame",models=3004}, - [6]={id=901,japanese="ナナー・ミーゴ",english="Nanaa Mihgo",name="NanaaMihgo",models=3005}, - [7]={id=902,japanese="クリルラ",english="Curilla",name="Curilla",models=3006}, - [8]={id=903,japanese="フォルカー",english="Volker",name="Volker",models=3007}, - [9]={id=904,japanese="アジドマルジド",english="Ajido-Marujido",name="Ajido-Marujido",models=3008}, - [10]={id=905,japanese="トリオン",english="Trion",name="Trion",models=3009}, - [11]={id=906,japanese="ザイド",english="Zeid",name="Zeid",models=3010}, - [12]={id=907,japanese="ライオン",english="Lion",name="Lion",models=3011}, - [13]={id=908,japanese="テンゼン",english="Tenzen",name="Tenzen",models=3012}, - [14]={id=909,japanese="ミリ・アリアポー",english="Mihli Aliapoh",name="MihliAliapoh",models=3013}, - [15]={id=910,japanese="ヴァレンラール",english="Valaineral",name="Valaineral",models=3014}, - [16]={id=911,japanese="ヨアヒム",english="Joachim",name="Joachim",models=3015}, - [17]={id=912,japanese="ナジャ・サラヒム",english="Naja Salaheem",name="NajaSalaheem",models=3016}, - [18]={id=913,japanese="プリッシュ",english="Prishe",name="Prishe",models=3017}, - [19]={id=914,japanese="ウルミア",english="Ulmia",name="Ulmia",models=3018}, - [20]={id=915,japanese="スカリーZ",english="Shikaree Z",name="ShikareeZ",models=3019}, - [21]={id=916,japanese="チェルキキ",english="Cherukiki",name="Cherukiki",models=3020}, - [22]={id=917,japanese="アイアンイーター",english="Iron Eater",name="IronEater",models=3021}, - [23]={id=918,japanese="ゲッショー",english="Gessho",name="Gessho",models=3022}, - [24]={id=919,japanese="ガダラル",english="Gadalar",name="Gadalar",models=3023}, - [25]={id=920,japanese="ライニマード",english="Rainemard",name="Rainemard",models=3024}, - [26]={id=921,japanese="イングリッド",english="Ingrid",name="Ingrid",models=3025}, - [27]={id=922,japanese="レコ・ハボッカ",english="Lehko Habhoka",name="LehkoHabhoka",models=3026}, - [28]={id=923,japanese="ナシュメラ",english="Nashmeira",name="Nashmeira",models=3027}, - [29]={id=924,japanese="ザザーグ",english="Zazarg",name="Zazarg",models=3028}, - [30]={id=925,japanese="アヴゼン",english="Ovjang",name="Ovjang",models=3029}, - [31]={id=926,japanese="メネジン",english="Mnejing",name="Mnejing",models=3030}, - [32]={id=927,japanese="サクラ",english="Sakura",name="Sakura",models=3031}, - [33]={id=928,japanese="ルザフ",english="Luzaf",name="Luzaf",models=3032}, - [34]={id=929,japanese="ナジュリス",english="Najelith",name="Najelith",models=3033}, - [35]={id=930,japanese="アルド",english="Aldo",name="Aldo",models=3034}, - [36]={id=931,japanese="モーグリ",english="Moogle",name="Moogle",models=3035}, - [37]={id=932,japanese="ファブリニクス",english="Fablinix",name="Fablinix",models=3036}, - [38]={id=933,japanese="マート",english="Maat",name="Maat",models=3037}, - [39]={id=934,japanese="D.シャントット",english="D. Shantotto",name="D.Shantotto",models=3038}, - [40]={id=935,japanese="星の神子",english="Star Sibyl",name="StarSibyl",models=3039}, - [41]={id=936,japanese="カラハバルハ",english="Karaha-Baruha",name="Karaha-Baruha",models=3040}, - [42]={id=937,japanese="シド",english="Cid",name="Cid",models=3041}, - [43]={id=938,japanese="ギルガメッシュ",english="Gilgamesh",name="Gilgamesh",models=3042}, - [44]={id=939,japanese="アレヴァト",english="Areuhat",name="Areuhat",models=3043}, - [45]={id=940,japanese="セミ・ラフィーナ",english="Semih Lafihna",name="SemihLafihna",models=3044}, - [46]={id=941,japanese="エリヴィラ",english="Elivira",name="Elivira",models=3045}, - [47]={id=942,japanese="ノユリ",english="Noillurie",name="Noillurie",models=3046}, - [48]={id=943,japanese="ルー・マカラッカ",english="Lhu Mhakaracca",name="LhuMhakaracca",models=3047}, - [49]={id=944,japanese="フェリアスコフィン",english="Ferreous Coffin",name="FerreousCoffin",models=3048}, - [50]={id=945,japanese="リリゼット",english="Lilisette",name="Lilisette",models=3049}, - [51]={id=946,japanese="ミュモル",english="Mumor",name="Mumor",models=3050}, - [52]={id=947,japanese="ウカ・トトゥリン",english="Uka Totlihn",name="UkaTotlihn",models=3051}, - [53]={id=948,japanese="クララ",english="Klara",name="Klara",models=3053}, - [54]={id=949,japanese="ロマー・ミーゴ",english="Romaa Mihgo",name="RomaaMihgo",models=3054}, - [55]={id=950,japanese="クイン・ハスデンナ",english="Kuyin Hathdenna",name="KuyinHathdenna",models=3055}, - [56]={id=951,japanese="ラーアル",english="Rahal",name="Rahal",models=3056}, - [57]={id=952,japanese="コルモル",english="Koru-Moru",name="Koru-Moru",models=3057}, - [58]={id=953,japanese="ピエージェ(UC)",english="Pieuje (UC)",name="Pieuje",models=3058}, - [59]={id=954,japanese="I.シールド(UC)",english="I. Shield (UC)",name="InvincibleShld",models=3060}, - [60]={id=955,japanese="アプルル(UC)",english="Apururu (UC)",name="Apururu",models=3061}, - [61]={id=956,japanese="ジャコ(UC)",english="Jakoh (UC)",name="JakohWahcondalo",models=3062}, - [62]={id=957,japanese="フラヴィリア(UC)",english="Flaviria (UC)",name="Flaviria",models=3059}, - [63]={id=958,japanese="ウェイレア",english="Babban",name="Babban",models=3067}, - [64]={id=959,japanese="アベンツィオ",english="Abenzio",name="Abenzio",models=3068}, - [65]={id=960,japanese="ルガジーン",english="Rughadjeen",name="Rughadjeen",models=3069}, - [66]={id=961,japanese="クッキーチェブキー",english="Kukki-Chebukki",name="Kukki-Chebukki",models=3070}, - [67]={id=962,japanese="マルグレート",english="Margret",name="Margret",models=3071}, - [68]={id=963,japanese="チャチャルン",english="Chacharoon",name="Chacharoon",models=3072}, - [69]={id=964,japanese="レイ・ランガヴォ",english="Lhe Lhangavo",name="LheLhangavo",models=3073}, - [70]={id=965,japanese="アシェラ",english="Arciela",name="Arciela",models=3074}, - [71]={id=966,japanese="マヤコフ",english="Mayakov",name="Mayakov",models=3075}, - [72]={id=967,japanese="クルタダ",english="Qultada",name="Qultada",models=3076}, - [73]={id=968,japanese="アーデルハイト",english="Adelheid",name="Adelheid",models=3077}, - [74]={id=969,japanese="アムチュチュ",english="Amchuchu",name="Amchuchu",models=3078}, - [75]={id=970,japanese="ブリジッド",english="Brygid",name="Brygid",models=3079}, - [76]={id=971,japanese="ミルドリオン",english="Mildaurion",name="Mildaurion",models=3080}, - [77]={id=972,japanese="ハルヴァー",english="Halver",name="Halver",models=3087}, - [78]={id=973,japanese="ロンジェルツ",english="Rongelouts",name="Rongelouts",models=3088}, - [79]={id=974,japanese="レオノアーヌ",english="Leonoyne",name="Leonoyne",models=3089}, - [80]={id=975,japanese="マクシミリアン",english="Maximilian",name="Maximilian",models=3090}, - [81]={id=976,japanese="カイルパイル",english="Kayeel-Payeel",name="Kayeel-Payeel",models=3091}, - [82]={id=977,japanese="ロベルアクベル",english="Robel-Akbel",name="Robel-Akbel",models=3092}, - [83]={id=978,japanese="クポフリート",english="Kupofried",name="Kupofried",models=3093}, - [84]={id=979,japanese="セルテウス",english="Selh\'teus",name="Selh\'teus",models=3094}, - [85]={id=980,japanese="ヨランオラン(UC)",english="Yoran-Oran (UC)",name="Yoran-Oran",models=3095}, - [86]={id=981,japanese="シルヴィ(UC)",english="Sylvie (UC)",name="Sylvie",models=3096}, - [87]={id=982,japanese="アブクーバ",english="Abquhbah",name="Abquhbah",models=3098}, - [88]={id=983,japanese="バラモア",english="Balamor",name="Balamor",models=3099}, - [89]={id=984,japanese="オーグスト",english="August",name="August",models=3100}, - [90]={id=985,japanese="ロスレーシャ",english="Rosulatia",name="Rosulatia",models=3101}, - [91]={id=986,japanese="テオドール",english="Teodor",name="Teodor",models=3103}, - [92]={id=987,japanese="ウルゴア",english="Ullegore",name="Ullegore",models=3105}, - [93]={id=988,japanese="マッキーチェブキー",english="Makki-Chebukki",name="Makki-Chebukki",models=3106}, - [94]={id=989,japanese="キング・オブ・ハーツ",english="King of Hearts",name="KingOfHearts",models=3107}, - [95]={id=990,japanese="モリマー",english="Morimar",name="Morimar",models=3108}, - [96]={id=991,japanese="ダラクァルン",english="Darrcuiln",name="Darrcuiln",models=3109}, - [97]={id=992,japanese="アークHM",english="AAHM",name="ArkHM",models=3113}, - [98]={id=993,japanese="アークEV",english="AAEV",name="ArkEV",models=3114}, - [99]={id=994,japanese="アークMR",english="AAMR",name="ArkMR",models=3115}, - [100]={id=995,japanese="アークTT",english="AATT",name="ArkTT",models=3116}, - [101]={id=996,japanese="アークGK",english="AAGK",name="ArkGK",models=3117}, - [102]={id=997,japanese="イロハ",english="Iroha",name="Iroha",models=3111}, - [103]={id=998,japanese="ユグナス",english="Ygnas",name="Ygnas",models=3118}, - [104]={id=1004,japanese="エグセニミルII",english="Excenmille [S]",name="Excenmille",models=3052}, - [105]={id=1005,japanese="アヤメ(UC)",english="Ayame (UC)",name="Ayame",models=3063}, - [106]={id=1006,japanese="マート(UC)",english="Maat (UC)",name="Maat",models=3064}, --expected models - [107]={id=1007,japanese="アルド(UC)",english="Aldo (UC)",name="Aldo",models=3065}, --expected models - [108]={id=1008,japanese="ナジャ(UC)",english="Naja (UC)",name="NajaSalaheem",models=3066}, - [109]={id=1009,japanese="ライオンII",english="Lion II",name="Lion",models=3081}, - [110]={id=1010,japanese="ザイドII",english="Zeid II",name="Zeid",models=3086}, - [111]={id=1011,japanese="プリッシュII",english="Prishe II",name="Prishe",models=3082}, - [112]={id=1012,japanese="ナシュメラII",english="Nashmeira II",name="Nashmeira",models=3083}, - [113]={id=1013,japanese="リリゼットII",english="Lilisette II",name="Lilisette",models=3084}, - [114]={id=1014,japanese="テンゼンII",english="Tenzen II",name="Tenzen",models=3097}, - [115]={id=1015,japanese="ミュモルII",english="Mumor II",name="Mumor",models=3104}, - [116]={id=1016,japanese="イングリッドII",english="Ingrid II",name="Ingrid",models=3102}, - [117]={id=1017,japanese="アシェラII",english="Arciela II",name="Arciela",models=3085}, - [118]={id=1018,japanese="イロハII",english="Iroha II",name="Iroha",models=3112}, - [119]={id=1019,japanese="シャントットII",english="Shantotto II",name="Shantotto",models=3110}, ---[120]={id=1003,japanese="コーネリア",english="Cornelia",name="Cornelia",models=3119}, --goodbye, my love + [1]={id=896,japanese="シャントット",english="Shantotto",name="Shantotto",models=3000}, + [2]={id=897,japanese="ナジ",english="Naji",name="Naji",models=3001}, + [3]={id=898,japanese="クピピ",english="Kupipi",name="Kupipi",models=3002}, + [4]={id=899,japanese="エグセニミル",english="Excenmille",name="Excenmille",models=3003}, + [5]={id=900,japanese="アヤメ",english="Ayame",name="Ayame",models=3004}, + [6]={id=901,japanese="ナナー・ミーゴ",english="Nanaa Mihgo",name="NanaaMihgo",models=3005}, + [7]={id=902,japanese="クリルラ",english="Curilla",name="Curilla",models=3006}, + [8]={id=903,japanese="フォルカー",english="Volker",name="Volker",models=3007}, + [9]={id=904,japanese="アジドマルジド",english="Ajido-Marujido",name="Ajido-Marujido",models=3008}, + [10]={id=905,japanese="トリオン",english="Trion",name="Trion",models=3009}, + [11]={id=906,japanese="ザイド",english="Zeid",name="Zeid",models=3010}, + [12]={id=907,japanese="ライオン",english="Lion",name="Lion",models=3011}, + [13]={id=908,japanese="テンゼン",english="Tenzen",name="Tenzen",models=3012}, + [14]={id=909,japanese="ミリ・アリアポー",english="Mihli Aliapoh",name="MihliAliapoh",models=3013}, + [15]={id=910,japanese="ヴァレンラール",english="Valaineral",name="Valaineral",models=3014}, + [16]={id=911,japanese="ヨアヒム",english="Joachim",name="Joachim",models=3015}, + [17]={id=912,japanese="ナジャ・サラヒム",english="Naja Salaheem",name="NajaSalaheem",models=3016}, + [18]={id=913,japanese="プリッシュ",english="Prishe",name="Prishe",models=3017}, + [19]={id=914,japanese="ウルミア",english="Ulmia",name="Ulmia",models=3018}, + [20]={id=915,japanese="スカリーZ",english="Shikaree Z",name="ShikareeZ",models=3019}, + [21]={id=916,japanese="チェルキキ",english="Cherukiki",name="Cherukiki",models=3020}, + [22]={id=917,japanese="アイアンイーター",english="Iron Eater",name="IronEater",models=3021}, + [23]={id=918,japanese="ゲッショー",english="Gessho",name="Gessho",models=3022}, + [24]={id=919,japanese="ガダラル",english="Gadalar",name="Gadalar",models=3023}, + [25]={id=920,japanese="ライニマード",english="Rainemard",name="Rainemard",models=3024}, + [26]={id=921,japanese="イングリッド",english="Ingrid",name="Ingrid",models=3025}, + [27]={id=922,japanese="レコ・ハボッカ",english="Lehko Habhoka",name="LehkoHabhoka",models=3026}, + [28]={id=923,japanese="ナシュメラ",english="Nashmeira",name="Nashmeira",models=3027}, + [29]={id=924,japanese="ザザーグ",english="Zazarg",name="Zazarg",models=3028}, + [30]={id=925,japanese="アヴゼン",english="Ovjang",name="Ovjang",models=3029}, + [31]={id=926,japanese="メネジン",english="Mnejing",name="Mnejing",models=3030}, + [32]={id=927,japanese="サクラ",english="Sakura",name="Sakura",models=3031}, + [33]={id=928,japanese="ルザフ",english="Luzaf",name="Luzaf",models=3032}, + [34]={id=929,japanese="ナジュリス",english="Najelith",name="Najelith",models=3033}, + [35]={id=930,japanese="アルド",english="Aldo",name="Aldo",models=3034}, + [36]={id=931,japanese="モーグリ",english="Moogle",name="Moogle",models=3035}, + [37]={id=932,japanese="ファブリニクス",english="Fablinix",name="Fablinix",models=3036}, + [38]={id=933,japanese="マート",english="Maat",name="Maat",models=3037}, + [39]={id=934,japanese="D.シャントット",english="D. Shantotto",name="D.Shantotto",models=3038}, + [40]={id=935,japanese="星の神子",english="Star Sibyl",name="StarSibyl",models=3039}, + [41]={id=936,japanese="カラハバルハ",english="Karaha-Baruha",name="Karaha-Baruha",models=3040}, + [42]={id=937,japanese="シド",english="Cid",name="Cid",models=3041}, + [43]={id=938,japanese="ギルガメッシュ",english="Gilgamesh",name="Gilgamesh",models=3042}, + [44]={id=939,japanese="アレヴァト",english="Areuhat",name="Areuhat",models=3043}, + [45]={id=940,japanese="セミ・ラフィーナ",english="Semih Lafihna",name="SemihLafihna",models=3044}, + [46]={id=941,japanese="エリヴィラ",english="Elivira",name="Elivira",models=3045}, + [47]={id=942,japanese="ノユリ",english="Noillurie",name="Noillurie",models=3046}, + [48]={id=943,japanese="ルー・マカラッカ",english="Lhu Mhakaracca",name="LhuMhakaracca",models=3047}, + [49]={id=944,japanese="フェリアスコフィン",english="Ferreous Coffin",name="FerreousCoffin",models=3048}, + [50]={id=945,japanese="リリゼット",english="Lilisette",name="Lilisette",models=3049}, + [51]={id=946,japanese="ミュモル",english="Mumor",name="Mumor",models=3050}, + [52]={id=947,japanese="ウカ・トトゥリン",english="Uka Totlihn",name="UkaTotlihn",models=3051}, + [53]={id=948,japanese="クララ",english="Klara",name="Klara",models=3053}, + [54]={id=949,japanese="ロマー・ミーゴ",english="Romaa Mihgo",name="RomaaMihgo",models=3054}, + [55]={id=950,japanese="クイン・ハスデンナ",english="Kuyin Hathdenna",name="KuyinHathdenna",models=3055}, + [56]={id=951,japanese="ラーアル",english="Rahal",name="Rahal",models=3056}, + [57]={id=952,japanese="コルモル",english="Koru-Moru",name="Koru-Moru",models=3057}, + [58]={id=953,japanese="ピエージェ(UC)",english="Pieuje (UC)",name="Pieuje",models=3058}, + [59]={id=954,japanese="I.シールド(UC)",english="I. Shield (UC)",name="InvincibleShld",models=3060}, + [60]={id=955,japanese="アプルル(UC)",english="Apururu (UC)",name="Apururu",models=3061}, + [61]={id=956,japanese="ジャコ(UC)",english="Jakoh (UC)",name="JakohWahcondalo",models=3062}, + [62]={id=957,japanese="フラヴィリア(UC)",english="Flaviria (UC)",name="Flaviria",models=3059}, + [63]={id=958,japanese="ウェイレア",english="Babban",name="Babban",models=3067}, + [64]={id=959,japanese="アベンツィオ",english="Abenzio",name="Abenzio",models=3068}, + [65]={id=960,japanese="ルガジーン",english="Rughadjeen",name="Rughadjeen",models=3069}, + [66]={id=961,japanese="クッキーチェブキー",english="Kukki-Chebukki",name="Kukki-Chebukki",models=3070}, + [67]={id=962,japanese="マルグレート",english="Margret",name="Margret",models=3071}, + [68]={id=963,japanese="チャチャルン",english="Chacharoon",name="Chacharoon",models=3072}, + [69]={id=964,japanese="レイ・ランガヴォ",english="Lhe Lhangavo",name="LheLhangavo",models=3073}, + [70]={id=965,japanese="アシェラ",english="Arciela",name="Arciela",models=3074}, + [71]={id=966,japanese="マヤコフ",english="Mayakov",name="Mayakov",models=3075}, + [72]={id=967,japanese="クルタダ",english="Qultada",name="Qultada",models=3076}, + [73]={id=968,japanese="アーデルハイト",english="Adelheid",name="Adelheid",models=3077}, + [74]={id=969,japanese="アムチュチュ",english="Amchuchu",name="Amchuchu",models=3078}, + [75]={id=970,japanese="ブリジッド",english="Brygid",name="Brygid",models=3079}, + [76]={id=971,japanese="ミルドリオン",english="Mildaurion",name="Mildaurion",models=3080}, + [77]={id=972,japanese="ハルヴァー",english="Halver",name="Halver",models=3087}, + [78]={id=973,japanese="ロンジェルツ",english="Rongelouts",name="Rongelouts",models=3088}, + [79]={id=974,japanese="レオノアーヌ",english="Leonoyne",name="Leonoyne",models=3089}, + [80]={id=975,japanese="マクシミリアン",english="Maximilian",name="Maximilian",models=3090}, + [81]={id=976,japanese="カイルパイル",english="Kayeel-Payeel",name="Kayeel-Payeel",models=3091}, + [82]={id=977,japanese="ロベルアクベル",english="Robel-Akbel",name="Robel-Akbel",models=3092}, + [83]={id=978,japanese="クポフリート",english="Kupofried",name="Kupofried",models=3093}, + [84]={id=979,japanese="セルテウス",english="Selh\'teus",name="Selh\'teus",models=3094}, + [85]={id=980,japanese="ヨランオラン(UC)",english="Yoran-Oran (UC)",name="Yoran-Oran",models=3095}, + [86]={id=981,japanese="シルヴィ(UC)",english="Sylvie (UC)",name="Sylvie",models=3096}, + [87]={id=982,japanese="アブクーバ",english="Abquhbah",name="Abquhbah",models=3098}, + [88]={id=983,japanese="バラモア",english="Balamor",name="Balamor",models=3099}, + [89]={id=984,japanese="オーグスト",english="August",name="August",models=3100}, + [90]={id=985,japanese="ロスレーシャ",english="Rosulatia",name="Rosulatia",models=3101}, + [91]={id=986,japanese="テオドール",english="Teodor",name="Teodor",models=3103}, + [92]={id=987,japanese="ウルゴア",english="Ullegore",name="Ullegore",models=3105}, + [93]={id=988,japanese="マッキーチェブキー",english="Makki-Chebukki",name="Makki-Chebukki",models=3106}, + [94]={id=989,japanese="キング・オブ・ハーツ",english="King of Hearts",name="KingOfHearts",models=3107}, + [95]={id=990,japanese="モリマー",english="Morimar",name="Morimar",models=3108}, + [96]={id=991,japanese="ダラクァルン",english="Darrcuiln",name="Darrcuiln",models=3109}, + [97]={id=992,japanese="アークHM",english="AAHM",name="ArkHM",models=3113}, + [98]={id=993,japanese="アークEV",english="AAEV",name="ArkEV",models=3114}, + [99]={id=994,japanese="アークMR",english="AAMR",name="ArkMR",models=3115}, + [100]={id=995,japanese="アークTT",english="AATT",name="ArkTT",models=3116}, + [101]={id=996,japanese="アークGK",english="AAGK",name="ArkGK",models=3117}, + [102]={id=997,japanese="イロハ",english="Iroha",name="Iroha",models=3111}, + [103]={id=998,japanese="ユグナス",english="Ygnas",name="Ygnas",models=3118}, + [104]={id=1004,japanese="エグセニミルII",english="Excenmille [S]",name="Excenmille",models=3052}, + [105]={id=1005,japanese="アヤメ(UC)",english="Ayame (UC)",name="Ayame",models=3063}, + [106]={id=1006,japanese="マート(UC)",english="Maat (UC)",name="Maat",models=3064}, --expected models + [107]={id=1007,japanese="アルド(UC)",english="Aldo (UC)",name="Aldo",models=3065}, --expected models + [108]={id=1008,japanese="ナジャ(UC)",english="Naja (UC)",name="NajaSalaheem",models=3066}, + [109]={id=1009,japanese="ライオンII",english="Lion II",name="Lion",models=3081}, + [110]={id=1010,japanese="ザイドII",english="Zeid II",name="Zeid",models=3086}, + [111]={id=1011,japanese="プリッシュII",english="Prishe II",name="Prishe",models=3082}, + [112]={id=1012,japanese="ナシュメラII",english="Nashmeira II",name="Nashmeira",models=3083}, + [113]={id=1013,japanese="リリゼットII",english="Lilisette II",name="Lilisette",models=3084}, + [114]={id=1014,japanese="テンゼンII",english="Tenzen II",name="Tenzen",models=3097}, + [115]={id=1015,japanese="ミュモルII",english="Mumor II",name="Mumor",models=3104}, + [116]={id=1016,japanese="イングリッドII",english="Ingrid II",name="Ingrid",models=3102}, + [117]={id=1017,japanese="アシェラII",english="Arciela II",name="Arciela",models=3085}, + [118]={id=1018,japanese="イロハII",english="Iroha II",name="Iroha",models=3112}, + [119]={id=1019,japanese="シャントットII",english="Shantotto II",name="Shantotto",models=3110}, +-- [120]={id=1003,japanese="コーネリア",english="Cornelia",name="Cornelia",models=3119}, --goodbye, my love } From 9f4e61c26a66fc6caf4de6007541930da8e293c6 Mon Sep 17 00:00:00 2001 From: from20020516 Date: Fri, 1 Jun 2018 15:43:27 +0900 Subject: [PATCH 0133/1002] help command added. --- addons/Bonanza/Bonanza.lua | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/addons/Bonanza/Bonanza.lua b/addons/Bonanza/Bonanza.lua index 5723a9e9eb..9b10a91a7a 100644 --- a/addons/Bonanza/Bonanza.lua +++ b/addons/Bonanza/Bonanza.lua @@ -65,8 +65,22 @@ windower.register_event('addon command',function(...) math.random() --shuffle rand cmd[i] = tonumber(cmd[i]) and cmd[i]*1 or cmd[i] end - - if cmd[1] == 'judge' then + if not cmd[1] or cmd[1] == 'help' then + local chat = windower.add_to_chat + local color = string.color + chat(1,'Bonanza - Command List:') + chat(207,'//bonanza '..color(' [number] ...',166)) + chat(160,' purchase specified marble(s).') + chat(207,'//bonanza '..color('random',166)) + chat(160,' purchase up to 10 marbles with at random.') + chat(207,'//bonanza '..color('sequence ',166)) + chat(160,' purchase up to 10 marbles with consecutive number.') + chat(160,' e.g. '..color('15250',166)..' then buying '..color('15250',166)..' to '..color('15259',166)..'.') + chat(207,'//bonanza '..color('last ',166)) + chat(160,' purchase up to 10 random marbles with tail of specified 0-9.') + local zero = color('0',166) + chat(160,' e.g. '..zero..' then buying 2224'..zero..', 6231'..zero..', 4586'..zero..'...') + elseif cmd[1] == 'judge' then windower.chat.input('/smes') elseif count == 0 then error('you have already '..marble.limit..' marbles.') From bd7d34a9fb4e6f0c4f18133f33a46532637b8769 Mon Sep 17 00:00:00 2001 From: from20020516 Date: Fri, 1 Jun 2018 15:50:28 +0900 Subject: [PATCH 0134/1002] update addons.xml --- addons/addons.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/addons.xml b/addons/addons.xml index 4af0135282..fa5c1e865b 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -699,9 +699,9 @@ Bonanza - Centurio a.k.a. from20020516 - Judge your Bonanza Marble. + Centurio a.k.a from20020516 + Purchace and Judge Bonanza Marbles. https://github.com/from20020516/Lua/issues https://twitter.com/from20020516 - \ No newline at end of file + From 578f6aa446f12b55bafde873a7d4f1e8d21bda8a Mon Sep 17 00:00:00 2001 From: from20020516 Date: Fri, 1 Jun 2018 16:07:13 +0900 Subject: [PATCH 0135/1002] addons.xml temporary delete for resolve conflicts.:scream_cat: --- addons/addons.xml | 707 ---------------------------------------------- 1 file changed, 707 deletions(-) delete mode 100644 addons/addons.xml diff --git a/addons/addons.xml b/addons/addons.xml deleted file mode 100644 index 940690048c..0000000000 --- a/addons/addons.xml +++ /dev/null @@ -1,707 +0,0 @@ - - - - Example - Iryoku - - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis dolor est, - tristique vitae lacinia quis, vulputate sit amet mi. Duis lacinia, massa - at faucibus sagittis. - - https://github.com/IryokuChevalier/Lua/issues - http://forums.windower.net/topic/21775-random-question-thread/ - - - AEcho - Automatically uses echo drops when you get silenced. Also, uses send to send a message to an alt that you got debuffed. - Nitrous (Shiva) - https://discord.gg/b275nMv - https://github.com/nitrous24/Lua/issues - - - AnnounceTarget - JoshK6656, Sechs - Creates special manual or automatic chat messages conveying advanced information about some specific targets - https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Asura/Sechs - - - AnsweringMachine - Byrth - Stores tells that you receive for later recall. - https://github.com/Byrth/Lua-Byrth/issues - https://discord.gg/b275nMv - - - AutoControl - Automated automaton equipment setting and burden tracker. - Nitrous (Shiva) - https://discord.gg/b275nMv - https://github.com/nitrous24/Lua/issues - - - autoinvite - r3g1stry - Automatically invites players when sent a tell with a specified keyword. - https://github.com/r3g1stry/Lua/issues - http://www.ffxiah.com/user/R3G1STRY - - - AutoJoin - Arcon - Automatically joins or declines party invites. Configurable with blacklist/whitelist mode and auto-decline settings. - https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Leviathan/Arcon - - - AutoRA - Banggugyangu - Causes Ranged Attacks to behave the same as melee Auto-Attack. - https://github.com/banggugyangu/Lua/issues - - - AzureSets - Automated blue magic spell setting. - Nitrous (Shiva) - https://discord.gg/b275nMv - https://github.com/nitrous24/Lua/issues - - - BarFiller - Displays an experience bar above the Help Window. - Morath - http://forums.windower.net/index.php?/topic/807-barfiller - https://github.com/Morath86/Issues - - - BattleMod - Byrth - Customizes battle chat messages. - https://github.com/Byrth/Lua-Byrth/issues - https://discord.gg/b275nMv - - - Blist - Ikonic - More detailed blist with tiered display options. Allows for blist to be active on any or all of several chat types. - https://github.com/Icinoki/Lua/issues - http://www.ffxiah.com/player/Ragnarok/Ikonic - - - bluGuide - Anissa - Change your blue magic on the fly with this clickable menu. Sort your spells by traits, buffs, procs, and more. - https://github.com/AniAniBobbani/Lua/issues - http://www.ffxiah.com/player/Cerberus/Anissa - - - boxdestroyer - Seth VanHeulen (Acacia@Odin) - Tracks and displays info about possible combinations for treasure caskets. - https://github.com/svanheulen/boxdestroyer-windower-addon/issues - http://www.ffxiah.com/player/Odin/Acacia - - - Cancel - Byrth - Mimics the cancel plugin, but also accepts buff names instead of just IDs. - https://github.com/Byrth/Lua-Byrth/issues - https://discord.gg/b275nMv - - - cBlock - Blacklist addon for FFOChat. - Nitrous (Shiva) - https://discord.gg/b275nMv - https://github.com/nitrous24/Lua/issues - - - CellHelp - Krizz and Balloon - Tracks cells that are needed, displays your position in the lot order, and creates the appropriate LL profiles. - https://github.com/tehkrizz/Lua/issues - http://www.ffxiah.com/player/Bahamut/Krizz - - - chars - Giuliano Riccio (Zohno@Phoenix - R.I.P) - Lets you input special chars using simple tags (ex.: <note> for ♪). - https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Phoenix/Zohno - - - ChatLink - Arcon - Allows opening links posted into the FFXI chat. - https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv - - - ChatPorter - Ikonic - Displays tell, party, and linkshell chat to alternate character and optional textbox. Also, allows you to reply from either character. - https://github.com/Icinoki/Lua/issues - http://www.ffxiah.com/player/Ragnarok/Ikonic - - - Clock - Arcon - Displays an on-screen clock in a custom format with options to display several different time zones. - https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv - - - ConsoleBG - Arcon - Displays a dark (by default) background behind the Windower console to make it more readable. - https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv - - - digger - Seth VanHeulen (Acacia@Odin) - Displays Chocobo digging accuracy, fatigue and remaining greens after each dig. Also shows dig "recast" timer using the Timers plugin. - https://github.com/svanheulen/digger-windower-addon/issues - http://www.ffxiah.com/player/Odin/Acacia - - - Distance - Arcon - Shows the distance to your current target. - https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Leviathan/Arcon - - - DistancePlus - Sammeh - Replacement for Distance Addon to show distance to current target and distance from pet. Also color coordinates distance based on job and abilities, such as magic, ranged attacks, and JA's. Also shows height differential for fights requiring height delta to avoid AOE. - https://github.com/SammehFFXI/Lua/issues - http://www.ffxiah.com/player/Quetzalcoatl/Sammeh - - - DressUp - Cair - Emulates BlinkMeNot functionality. Allows for customization of gear display for you or anyone else. - https://github.com/cairface/Lua/issues - https://discord.gg/b275nMv - - - DynamisHelper - Displays a timer when a mob is procced, tracks currency obtained, and can create a LL to lot all currency. - https://github.com/tehkrizz/Lua/issues - http://www.ffxiah.com/player/Bahamut/Krizz - - - Enemybar - mmckee - This is an addon for Windower4 for FFXI. It creates a big health bar for the target to make it easy to see. - https://github.com/mjmckee/Lua/issues - http://www.ffxiah.com/player/Ragnarok/Pesche - - - Giuliano Riccio (Zohno@Phoenix - R.I.P) - enternity - Enters "Enter" automatically when prompted during a cutscene or when talking to NPCs. It will not skip choice dialog boxes. - https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Phoenix/Zohno - - - eval - Aureus - Allows developers to run arbitrary lua code in the console. - https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv - - - FastCS - Cair - Dramatically speeds up cutscenes by disabling the frame rate cap. Requires the config plugin. - https://github.com/cairface/Lua/issues - https://discord.gg/b275nMv - - - FFOColor - Nitrous (Shiva) - Allows you to show FFOChat text in one of the 5 game chat channels. As well as specify colors for the text - https://github.com/nitrous24/Lua/issues - https://discord.gg/b275nMv - - - findAll - Giuliano Riccio (Zohno@Phoenix - R.I.P) - Searches items stored on all your characters and allows live on-screen tracking of specified items. - https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Phoenix/Zohno - - - Gametime - Omnys@Valefor - Displays game time, game-week, moon information, and travel times. - https://github.com/thatdudegrim/Lua/issues - http://www.ffxiah.com/player/Valefor/Omnys - - - GearSwap - Byrth - Changes gear in response to player actions. [[Uses Packets.]] - https://github.com/Byrth/Lua-Byrth/issues - - - Highlight - Highlights party members names when mentioned in the chatlog. - Balloon - https://github.com/Podginator/Lua/issues - Podginator@gmail.com - - - instaLS - Byrth - Enables instant linkshell chat after zoning. - https://github.com/Byrth/Lua-Byrth/issues - https://discord.gg/b275nMv - - - InfoBar - Kenshi - Displays a configurable bar showing information on your targets. - https://github.com/KenshiDRK/Lua/issues - https://www.ffxiah.com/player/Ragnarok/Kenshi - - - InfoReplacer - Cair - Replaces outgoing text prefixed by % with respective game information. - https://github.com/cairface/Lua/issues - https://discord.gg/b275nMv - - - Itemizer - Ihina - Use commands to move items and gear between bags. - https://github.com/Jayjs20/Lua/issues - http://www.ffxiah.com/player/Bismarck/Ihina - - - JobChange - Sammeh - Command line Job Changer - https://github.com/SammehFFXI/Lua/issues - http://www.ffxiah.com/player/Quetzalcoatl/Sammeh - - - latentchecker - byrth,smd111 - Checks weapon skill points of weapon skill trial weapons and mythic weapons - https://github.com/smd111/LatentChecker/issues - https://github.com/smd111/LatentChecker/issues - - - Linker - Arcon - Allows opening links to certain websites from within the game, with an optional search parameter. - https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Leviathan/Arcon - - - Logger - Arcon - Logs the chat log to a file. - https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Leviathan/Arcon - - - Lookup - Karuberu - Lookup website information from an in-game command. Accepts auto-translate text and selectors like "<t>". Opens in a browser window. - https://github.com/Karuberu/Lua/issues - https://github.com/Karuberu/Lua/issues - - - Lottery - Arcon - Automatically passes an item on all accounts if lotted by another. - https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Leviathan/Arcon - - - MacroChanger - Banggugyangu - Automatically switches Macro Book and Page according to job changes. - https://github.com/banggugyangu/Lua/issues - https://discord.gg/b275nMv - - - MobCompass - A compass to show your position relative to the target (not players) for geo and has a setup for Sneak attack - https://discord.gg/b275nMv - - - Nostrum - Creates a click-able on-screen macro to help avoid targeting problems while curing. - trv - https://discord.gg/b275nMv - https://github.com/trv6/Lua/issues - - - obiaway - Automatically collect and remove elemental obi based on day/weather/storm conditions. - https://discord.gg/b275nMv - - - Omen - Braden, Sechs - Tracks primary and secondary objectives within the Omen event in a customizable on-screen window - https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Asura/Sechs - - - OhShi - Keeps track of various event related things. Such as, VW proc messages, mob casting, mob tp moves, TH procs and cor rolls, as well as others. - Nitrous (Shiva) - https://discord.gg/b275nMv - https://github.com/nitrous24/Lua/issues - - - Organizer - A multi-purpose inventory management solution. Similar to GearCollector. - Byrth, Rooks - https://discord.gg/b275nMv - https://github.com/Byrth/Lua-Byrth/issues - - - pet_fix - Byrth - Temporary addon that fixes a null pointer animation error with pets that is causing crashes. - https://github.com/Byrth/Lua-Byrth/issues - https://discord.gg/b275nMv - - - PetSchool - Banggugyangu - A helper addon for PUPs using spellcast, it informs spellcast of pet casting (healing or nuking). - https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv - - - PetTP - SnickySnacks - Tracks pet vitals (HP/TP/MP) - https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv - - - plasmon - Giuliano Riccio (Zohno@Phoenix - R.I.P) - tracks plasm, killed mobs and dropped airlixirs during a delve. - https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Phoenix/Zohno - - - plugin_manager - Byrth - Allows you to specify which plugins and addons will be used with which characters. - https://github.com/Byrth/Lua-Byrth/issues - https://discord.gg/b275nMv - - - PointWatch - Byrth - Allows you to monitor your XP/CP gains and keep track of the Dynamis time limit. - https://github.com/Byrth/Lua-Byrth/issues - https://discord.gg/b275nMv - - - porter - Giuliano Riccio (Zohno@Phoenix - R.I.P) - Shows the slips' items highlighting those that are stored. - https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Phoenix/Zohno - - - Pouches - Omnys@Valefor - Simple addon to use all of a named item in player's main inventory, like //pouches bead pouch. - https://github.com/thatdudegrim/Lua/issues - http://www.ffxiah.com/player/Valefor/Omnys - - - RAWR - Genoxd - Plays a sound effect when your unity leader says something about dragons spawning. - https://github.com/geno3302/Lua - http://www.ffxiah.com/player/Lakshmi/Genoxd - - - reive - Giuliano Riccio (Zohno@Phoenix - R.I.P) - Tracks exp, bayld, momentum scores and bonuses during a reive. - https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Phoenix/Zohno - - - Remember - Byrth - Should request spawn packets for players / mobile NPCs that failed to spawn. - https://github.com/Byrth/Lua-Byrth/issues - https://discord.gg/b275nMv - - - Respond - Byrth - Respond to tells and FFOchat PMs using //r. - https://github.com/Byrth/Lua-Byrth/issues - https://discord.gg/b275nMv - - - Rhombus - Creates a highly customizable, click-able, on-screen menu. - trv - https://discord.gg/b275nMv - https://github.com/trv6/Lua/issues - - - ROE - Cair - Lets you save your Records of Eminence objectives to profiles for easily swapping out objectives. - https://github.com/cairface/Lua/issues - https://discord.gg/b275nMv - - - RollTracker - Balloon - Simplifies Cor rolls, tells you the bonus they give, stops you from doubling up on lucky rolls and reports your chance to bust. - https://github.com/Podginator/Lua/issues - Podginator@gmail.com - - - salvage2 - Krizz - Displays pathos that have not been removed in Salvage 2. Displays zone timer. - https://github.com/tehkrizz/Lua/issues - http://www.ffxiah.com/player/Bahamut/Krizz - - - SATACast - Banggugyangu - Informs Spellcast about changes to Sneak Attack and Trick Attack status. - https://github.com/banggugyangu/Lua/issues - https://discord.gg/b275nMv - - - Scoreboard - Suji - Basic in-game damage parser. It displays live DPS and works even when chat filters are enabled. - https://github.com/jerryhebert/Lua/issues - https://discord.gg/b275nMv - - - setbgm - Seth VanHeulen (Acacia@Odin) - Set your background/battle/other music to any music in the game. - https://github.com/svanheulen/setbgm-windower-addon/issues - http://www.ffxiah.com/player/Odin/Acacia - - - Shortcuts - Byrth - Applys spellcast-like command completion (interpretation and target completion) to commands. Includes emotes, /check, and /pcmd. - https://github.com/Byrth/Lua-Byrth/issues - https://discord.gg/b275nMv - - - Silence - Ihina - Eliminates the flood of equipment change messages. - https://github.com/Jayjs20/Lua/issues - http://www.ffxiah.com/player/Bismarck/Ihina - - - ShoutHelper - Jandel - Help managing party job in an alliance shout. Displays a in-game editable list (initially empty) in which one can set job and players - https://github.com/Jandella/Lua/issues - http://www.ffxiah.com/player/Ragnarok/Jandel - - - Send - Byrth - Sends commands between windower instances using IPC. - https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv - - - SpeedChecker - Arcon - Displays a small box indicating your current movement speed modifier (+/- X%). - https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Leviathan/Arcon - - - SpellCheck - Damien Dennehy (Zubis@Asura) - This addon lists spells you haven't unlocked yet. - https://github.com/DamienDennehy/Lua/issues - http://www.ffxiah.com/player/Asura/Zubis - - - StaggerTrack - Nitrous (Shiva) - Catches voidwatch weakness messages and prints them to a textbox in case you miss them in the battle spam. - https://github.com/nitrous24/Lua/issues - https://discord.gg/b275nMv - - - STNA - Nitrous (Shiva) - One-button status removal for dual boxing. - https://github.com/nitrous24/Lua/issues - https://discord.gg/b275nMv - - - stopwatch - Patrick Finnigan (Puhfyn@Ragnarok) - Timer that counts up and allows you to track time since events e.g. spawns. - https://github.com/finnigantime/Lua/issues - http://www.ffxiah.com/player/Ragnarok/Puhfyn - - - StratHelper - Ihm - A simple helper addon for Spellcast for Scholar Stratagems. It will automatically calculate the number of stratagems you have and push them into spellcast variables. - https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv - - - subTarget - Sebyg666 - Enhances the usage of the send addon by allowing a stal or stpc or st target to be sent as the spell recipient. This removes the need for multiple macros for the same spell. - https://github.com/sebyg666/Lua/issues - https://github.com/sebyg666/Lua/tree/4.1-dev/addons/SubTarget - - - TargetInfo - Arcon - Displays information about your current target in memory. - https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Leviathan/Arcon - - - Text - Arcon - Allows creating and manipulating on-screen text objects through Windower commands. - https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Leviathan/Arcon - - - Treasury - Arcon - Lots or passes items based on configurable lists, drops unwanted items from the inventory and automatically stacks items when they drop. - https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Leviathan/Arcon - - - thtracker - Krizz - Displays latest TH level from chat. - https://github.com/tehkrizz/Lua/issues - http://www.ffxiah.com/player/Bahamut/Krizz - - - timestamp - Giuliano Riccio (Zohno@Phoenix - R.I.P) - Prefixes any chat message with a timestamp. Based on Timestamp plugin. - https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Phoenix/Zohno - - - TParty - Arcon - Shows a target's HP percentage next to their health bar as well as party/alliance members's TP. - https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Leviathan/Arcon - - - translate - Byrth - Gives a rough JP->EN translation using the resources and custom dictionaries. - https://github.com/Byrth/Lua-Byrth/issues - https://discord.gg/b275nMv - - - TreasurePool - Kenshi - Replacement for the Treasure Pool thats shows time till the item auto drop and who is the current winning lot. - https://github.com/KenshiDRK/Lua/issues - https://www.ffxiah.com/player/Ragnarok/Kenshi - - - Update - Arcon - Updates and reloads all plugins and addons when typing //update. - https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Leviathan/Arcon - - - VisibleFavor - Seth VanHeulen (Acacia@Odin) - Displays a GEO bubble around your avatar to visualize Favor/Ward ranges. - https://github.com/svanheulen/visiblefavor-windower-addon/issues - http://www.ffxiah.com/player/Odin/Acacia - - - vwhl - Giuliano Riccio (Zohno@Phoenix - R.I.P) - Redirects the nm's weaknesses (VW or Abyssea) to the "tell" stream so that they can be held using the chat filters' function and highlights the important info. - https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Phoenix/Zohno - - - XIVBar - SirEdeonX (Edeon@Asura) - Displays HP, MP and TP bars on the center of the screen, akin to FFXIV, for easy tracking - https://github.com/SirEdeonX/Lua/issues - http://www.ffxiah.com/player/Asura/Edeon - - - Yush - Arcon - A file-based macro engine - https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Leviathan/Arcon - - - zonetimer - Ihina - Displays the amount of time one has been in zone. Original by Krellion. - https://github.com/Jayjs20/Lua/issues - http://www.ffxiah.com/player/Bismarck/Ihina - - - temps - Mojo - Makes buying temporary items from escha npcs much easier. - https://github.com/Snapsmojo/Lua/issues - http://www.ffxiah.com/player/Fenrir/Snaps - - - CapeTrader - Lygre, Burntwaffle - Automates the ambuscade cape augmentation process. - https://github.com/OdinBurntwaffle/Lua/issues - http://www.ffxiah.com/player/Odin/Burntwaffle - - - craft - Mojo - A Final Fantasy XI Crafting Addon - https://github.com/Snapsmojo/Lua/issues - http://www.ffxiah.com/player/Fenrir/Snaps - - - Trusts - Centurio a.k.a. from20020516 - Save/Summon Trust set. - https://github.com/from20020516/Lua/issues - https://twitter.com/from20020516 - - From df9ccc2f9a83c5fa7b798bad3d4c85a68c3f3e5d Mon Sep 17 00:00:00 2001 From: from20020516 Date: Fri, 1 Jun 2018 16:13:03 +0900 Subject: [PATCH 0136/1002] update addons.xml --- addons/addons.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/addons/addons.xml b/addons/addons.xml index 51213ba236..53ade43429 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -711,4 +711,11 @@ https://github.com/from20020516/Lua/issues https://twitter.com/from20020516 + + Trusts + Centurio a.k.a from20020516 + Save and Summon Trust sets. + https://github.com/from20020516/Lua/issues + https://twitter.com/from20020516 + From 5714ed4fa6183eb5d95b6cbcf3ff22df578b9ac8 Mon Sep 17 00:00:00 2001 From: from20020516 Date: Fri, 1 Jun 2018 16:41:45 +0900 Subject: [PATCH 0137/1002] re-update addons.xml --- addons/addons.xml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/addons/addons.xml b/addons/addons.xml index fa5c1e865b..e92413582f 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -335,6 +335,13 @@ A compass to show your position relative to the target (not players) for geo and has a setup for Sneak attack https://discord.gg/b275nMv + + MountMuzzle + Sjshovan (Apogee) + Allows the user to change or remove the default mount music. + https://github.com/Windower/Lua/issues + https://discord.gg/b275nMv + Nostrum Creates a click-able on-screen macro to help avoid targeting problems while curing. @@ -697,6 +704,13 @@ https://github.com/Snapsmojo/Lua/issues http://www.ffxiah.com/player/Fenrir/Snaps + + Checkparam + Centurio a.k.a from20020516 + Displays the total of property of target player's current equipments. + https://github.com/from20020516/Lua/issues + https://twitter.com/from20020516 + Bonanza Centurio a.k.a from20020516 From 96f6a243cbec30534a4de7ed6a44677dbb9307ab Mon Sep 17 00:00:00 2001 From: from20020516 Date: Fri, 1 Jun 2018 17:45:32 +0900 Subject: [PATCH 0138/1002] update addons.xml and ready to merge. --- addons/addons.xml | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/addons/addons.xml b/addons/addons.xml index 30de128b94..9518e75050 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -706,21 +706,22 @@ Checkparam - Centurio a.k.a from20020516 + Centurio aka from20020516 Displays the total of property of target player's current equipments. https://github.com/from20020516/Lua/issues https://twitter.com/from20020516 -<<<<<<< HEAD - Trusts - Centurio a.k.a from20020516 - Save and Summon Trust sets. -======= Bonanza - Centurio a.k.a from20020516 + Centurio aka from20020516 Purchace and Judge Bonanza Marbles. ->>>>>>> upstream/dev + https://github.com/from20020516/Lua/issues + https://twitter.com/from20020516 + + + Trusts + Centurio aka from20020516 + Save and Summon trust sets. https://github.com/from20020516/Lua/issues https://twitter.com/from20020516 From 1a66ef90c07c7cdb2c331f8282deb2f4f849f1db Mon Sep 17 00:00:00 2001 From: from20020516 Date: Sat, 2 Jun 2018 23:08:32 +0900 Subject: [PATCH 0139/1002] update readme.md --- addons/checkparam/README.md | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/addons/checkparam/README.md b/addons/checkparam/README.md index 64cb2ddd6a..7b0a6bcaeb 100644 --- a/addons/checkparam/README.md +++ b/addons/checkparam/README.md @@ -1,20 +1,30 @@ # checkparam - +![40696007-caf91c3c-63fe-11e8-9837-516f9e1f2b0e](https://user-images.githubusercontent.com/26649687/40877257-96ccef12-66b8-11e8-97a4-797789375a00.jpg) +## English - `/check` OR `/c` (in-game command) - Whenever you `/check` any player, displays the total of property of that players current equipments.(defined in `settings.xml`) - - プレイヤーを「調べる」したとき、そのプレイヤーが装備しているアイテムの任意のプロパティを合計して表示します。(`settings.xml`で定義) - `//checkparam` OR `//cp` (addon command) - - same as /check . you can use this command in equipment menu. - - /check と同様ですが、装備変更画面でも使用できます。 - -## data/settings.xml (auto-generated) + - same as /check . you can use this command in equipment menu. +### data/settings.xml (auto-generated) - Define the properties you want to be displayed for each job. - - `|` divide each property - - `pet: ` define properties for all pets, which means avatar: wyvern: automaton: luopan: -- 表示させたいプロパティをジョブごとに定義します。 - - `|` 区切り記号 - - `pet: ` 召喚獣: 飛竜: オートマトン: 羅盤: は代わりに`pet:`で指定します。 - + - `|` divide each property + - `pet: ` define properties for all pets, which means avatar: wyvern: automaton: luopan: +- `` ignore players with below the level `` when `/check`. default value is 99. + - **Tips:** if set `100`, ignore all players. you can still use `//cp` for yourself. - If there’s something wrong,or something strange, please tell me on Twitter [@from20020516](https://twitter.com/from20020516) **with simple English**. Thank you! + +## 日本語 +- `/check` または `/c`(ゲーム内コマンド) + - プレイヤーを「調べる」したとき、そのプレイヤーが装備しているアイテムの任意のプロパティを合計して表示します。(`settings.xml`で定義) +- `//checkparam` または `//cp`(アドオンコマンド) + - /check と同様ですが、装備変更画面でも使用できます。 + +### data/settings.xml (自動生成) +- 表示させたいプロパティをジョブごとに定義します。 + - `|` 区切り記号 + - `pet: ` 召喚獣: 飛竜: オートマトン: 羅盤: は代わりに`pet:`で指定します。 +- `` + -「調べる」時に対象のレベルが設定値未満なら結果を表示しません。(初期値99) + - **Tips:** `100`を設定すると「調べる」時の結果を表示しません。 From 03a31dc577405082aafcd64053f81166b47f45fb Mon Sep 17 00:00:00 2001 From: from20020516 Date: Sat, 2 Jun 2018 23:18:52 +0900 Subject: [PATCH 0140/1002] Fixed error message from packets.parse. --- addons/Bonanza/Bonanza.lua | 68 ++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/addons/Bonanza/Bonanza.lua b/addons/Bonanza/Bonanza.lua index 9b10a91a7a..90d55bac7a 100644 --- a/addons/Bonanza/Bonanza.lua +++ b/addons/Bonanza/Bonanza.lua @@ -117,39 +117,41 @@ function talk_moogle() end windower.register_event('incoming chunk',function(id,data) - --got a marble. - local p = packets.parse('incoming',data) - if id == 0x020 and hide_ui and p['Item'] == marble.id and p['Bag'] == 0 then - local item = windower.ffxi.get_items(0,p['Index']) - if extdata.decode(item).number == decides[1] then - hide_ui = false - table.remove(decides,1) - talk_moogle() - end - --responced to talk. - elseif id == 0x034 and hide_ui and p['NPC'] == moogle.id then - if moogle.distance > 36 then - error('not close enough to Bonanza Moogle.') - elseif marble.price > windower.ffxi.get_items().gil then - error('not have enough gils.') - else - local packet = packets.new('outgoing',0x05B) - local i = decides[1] - log('Purchase a Bonanza Marble #'..string.format('%05s',i)) - --packet part 1 - packet['Target']=moogle.id - packet['Option Index']=2+i%256*256 - packet['Target Index']=moogle.index - packet['Automated Message']=true - packet['_unknown1']=(i-i%256)/256 - packet['Zone']=p['Zone'] - packet['Menu ID']=p['Menu ID'] - packets.inject(packet) - --packet part 2 - packet['Option Index']=3 - packet['Automated Message']=false - packets.inject(packet) - return true; --hide ui + if S{0x020,0x034}[id] and hide_ui then + --got a marble. + local p = packets.parse('incoming',data) + if id == 0x020 and p['Item'] == marble.id and p['Bag'] == 0 then + local item = windower.ffxi.get_items(0,p['Index']) + if extdata.decode(item).number == decides[1] then + hide_ui = false + table.remove(decides,1) + talk_moogle() + end + --responced to talk. + elseif id == 0x034 and p['NPC'] == moogle.id then + if moogle.distance > 36 then + error('not close enough to Bonanza Moogle.') + elseif marble.price > windower.ffxi.get_items().gil then + error('not have enough gils.') + else + local packet = packets.new('outgoing',0x05B) + local i = decides[1] + log('Purchase a Bonanza Marble #'..string.format('%05s',i)) + --packet part 1 + packet['Target']=moogle.id + packet['Option Index']=2+i%256*256 + packet['Target Index']=moogle.index + packet['Automated Message']=true + packet['_unknown1']=(i-i%256)/256 + packet['Zone']=p['Zone'] + packet['Menu ID']=p['Menu ID'] + packets.inject(packet) + --packet part 2 + packet['Option Index']=3 + packet['Automated Message']=false + packets.inject(packet) + return true; --hide ui + end end end end) From 71fa18e55be99366d6f96bead8bf63a6366844f8 Mon Sep 17 00:00:00 2001 From: from20020516 Date: Sun, 3 Jun 2018 14:06:54 +0900 Subject: [PATCH 0141/1002] initial commit new addon MyHome --- addons/MyHome/MyHome.lua | 69 ++++++++++++++++++++++++++++++++++++++++ addons/MyHome/README.md | 10 ++++++ addons/addons.xml | 11 +++++-- 3 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 addons/MyHome/MyHome.lua create mode 100644 addons/MyHome/README.md diff --git a/addons/MyHome/MyHome.lua b/addons/MyHome/MyHome.lua new file mode 100644 index 0000000000..834c1e7562 --- /dev/null +++ b/addons/MyHome/MyHome.lua @@ -0,0 +1,69 @@ +_addon.name = 'MyHome' +_addon.author = 'from20020516' +_addon.version = '1.0' +_addon.commands = {'myhome','mh','warp'} + +require('logger') +extdata = require('extdata') + +lang = string.lower(windower.ffxi.get_info().language) +item_info = { + [1]={id=28540,japanese='デジョンリング',english='"Warp Ring"',slot=13}, + [2]={id=17040,japanese='デジョンカジェル',english='"Warp Cudgel"',slot=0}, + [3]={id=4181,japanese='呪符デジョン',english='"Instant Warp"'}} + +function search_item() + local item_array = {} + local bags = {0,8,10,11,12} --inventory,wardrobe1-4 + local get_items = windower.ffxi.get_items + for i=1,#bags do + for _,item in ipairs(get_items(bags[i])) do + if item.id > 0 then + item_array[item.id] = item + item_array[item.id].bag = bags[i] + end + end + end + for index,stats in pairs(item_info) do + local item = item_array[stats.id] + local set_equip = windower.ffxi.set_equip + if item then + ext = extdata.decode(item) + local enchant = ext.type == 'Enchanted Equipment' + local recast = enchant and ext.charges_remaining > 0 and math.max(ext.next_use_time+18000-os.time(),0) + local usable = recast and recast == 0 + log(stats[lang],usable and '' or recast..' sec recast.') + if usable or ext.type == 'General' then + if enchant and item.status ~= 5 then --not equipped + set_equip(item.slot,stats.slot,item.bag) + log_flag = true + repeat --waiting cast delay + coroutine.sleep(1) + local ext = extdata.decode(get_items(item.bag,item.slot)) + local delay = ext.activation_time+18000-os.time() + if delay > 0 then + log(stats[lang],delay) + elseif log_flag then + log_flag = false + log('Item use within 3 seconds..') + end + until ext.usable or delay > 10 + end + windower.chat.input('/item '..windower.to_shift_jis(stats[lang])..' ') + break; + end + else + log(stats[lang],false) + end + end +end + +windower.register_event('addon command',function() + local player = windower.ffxi.get_player() + if S{player.main_job_id,player.sub_job_id}[4] then --BLM + local spell = {japanese='デジョンII',english='"Warp II"'} + windower.chat.input('/ma '..windower.to_shift_jis(spell[lang])..' ') + else + search_item() + end +end) diff --git a/addons/MyHome/README.md b/addons/MyHome/README.md new file mode 100644 index 0000000000..1e9c233419 --- /dev/null +++ b/addons/MyHome/README.md @@ -0,0 +1,10 @@ +# MyHome +- Automatically choose and uses a warp spell or an item. + +## Command +- `//mh` OR `//warp` +- Priorities are: + 1. Warp II + 2. Warp Ring + 3. Warp Cudgel + 4. Instant Warp diff --git a/addons/addons.xml b/addons/addons.xml index e92413582f..b9d8d5f470 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -706,16 +706,23 @@ Checkparam - Centurio a.k.a from20020516 + Centurio aka from20020516 Displays the total of property of target player's current equipments. https://github.com/from20020516/Lua/issues https://twitter.com/from20020516 Bonanza - Centurio a.k.a from20020516 + Centurio aka from20020516 Purchace and Judge Bonanza Marbles. https://github.com/from20020516/Lua/issues https://twitter.com/from20020516 + + MyHome + Centurio aka from20020516 + Automatically choose and use warp spell or item. + https://github.com/from20020516/Lua/issues + https://twitter.com/from20020516 + From 7ae45ee3f0a2eef15d08b66095f64c4023d0ca4b Mon Sep 17 00:00:00 2001 From: from20020516 Date: Sun, 3 Jun 2018 14:18:29 +0900 Subject: [PATCH 0142/1002] Copyright notice added. --- addons/MyHome/MyHome.lua | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/addons/MyHome/MyHome.lua b/addons/MyHome/MyHome.lua index 834c1e7562..6f65e0642e 100644 --- a/addons/MyHome/MyHome.lua +++ b/addons/MyHome/MyHome.lua @@ -1,3 +1,30 @@ +--[[ +Copyright © 2018, from20020516 +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 MyHome 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 from20020516 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.name = 'MyHome' _addon.author = 'from20020516' _addon.version = '1.0' From eee17318d4cafb23e67452b65eae3aba0053ca35 Mon Sep 17 00:00:00 2001 From: from20020516 Date: Sun, 3 Jun 2018 23:34:31 +0900 Subject: [PATCH 0143/1002] global var `ext` changed to local. --- addons/MyHome/MyHome.lua | 2 +- addons/MyHome/README.md | 8 ++++---- addons/addons.xml | 7 +++++++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/addons/MyHome/MyHome.lua b/addons/MyHome/MyHome.lua index 6f65e0642e..5606cb241c 100644 --- a/addons/MyHome/MyHome.lua +++ b/addons/MyHome/MyHome.lua @@ -55,7 +55,7 @@ function search_item() local item = item_array[stats.id] local set_equip = windower.ffxi.set_equip if item then - ext = extdata.decode(item) + local ext = extdata.decode(item) local enchant = ext.type == 'Enchanted Equipment' local recast = enchant and ext.charges_remaining > 0 and math.max(ext.next_use_time+18000-os.time(),0) local usable = recast and recast == 0 diff --git a/addons/MyHome/README.md b/addons/MyHome/README.md index 1e9c233419..6c616795cd 100644 --- a/addons/MyHome/README.md +++ b/addons/MyHome/README.md @@ -4,7 +4,7 @@ ## Command - `//mh` OR `//warp` - Priorities are: - 1. Warp II - 2. Warp Ring - 3. Warp Cudgel - 4. Instant Warp + 1. Warp II - require main or sub job BLM. + 2. Warp Ring - search inventory and wardrobes. + 3. Warp Cudgel - search inventory and wardrobes. + 4. Instant Warp - search inventory. diff --git a/addons/addons.xml b/addons/addons.xml index b9d8d5f470..6da256f110 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -718,6 +718,13 @@ https://github.com/from20020516/Lua/issues https://twitter.com/from20020516 + + Trusts + Centurio aka from20020516 + Save and Summon trust sets. + https://github.com/from20020516/Lua/issues + https://twitter.com/from20020516 + MyHome Centurio aka from20020516 From bb55dbaa5f81582731cb82313e144e4ea9d406d3 Mon Sep 17 00:00:00 2001 From: from20020516 Date: Mon, 4 Jun 2018 00:10:18 +0900 Subject: [PATCH 0144/1002] update addons.xml --- addons/addons.xml | 3 --- 1 file changed, 3 deletions(-) diff --git a/addons/addons.xml b/addons/addons.xml index 9540d42d69..6da256f110 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -725,7 +725,6 @@ https://github.com/from20020516/Lua/issues https://twitter.com/from20020516 -<<<<<<< HEAD MyHome Centurio aka from20020516 @@ -733,6 +732,4 @@ https://github.com/from20020516/Lua/issues https://twitter.com/from20020516 -======= ->>>>>>> dev From 30c386d36ca6dcc79894785ecb7b71c3557d1b64 Mon Sep 17 00:00:00 2001 From: John Hobart Date: Tue, 5 Jun 2018 01:32:07 -0400 Subject: [PATCH 0145/1002] update the version number Making the version number something more reasonable --- addons/SpellBook/SpellBook.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/SpellBook/SpellBook.lua b/addons/SpellBook/SpellBook.lua index 93f4702c93..5cb0d16ad4 100644 --- a/addons/SpellBook/SpellBook.lua +++ b/addons/SpellBook/SpellBook.lua @@ -1,6 +1,6 @@ _addon.name = 'SpellBook' _addon.author = 'SigilBaram' -_addon.version = '0.0.1' +_addon.version = '1.0.0' _addon.commands = {'spellbook','spbk'} require('tables') From a6d07cb2a701532fd76388b6e41855ff7d02c3c3 Mon Sep 17 00:00:00 2001 From: from20020516 Date: Wed, 6 Jun 2018 17:02:48 +0900 Subject: [PATCH 0146/1002] [Update] libs/extdata.lua Modified the result to be 10x. (since post 2014) ```lua -- equip 'Moonshade Earring' with 'TP Bonus+250' aug in right_ear before exec this. extdata = require('extdata') local get_items = windower.ffxi.get_items bag = get_items().equipment.right_ear_bag ind = get_items().equipment.right_ear aug = extdata.decode({id=11697,extdata=get_items(bag,ind).extdata}).augments for i,v in ipairs(aug) do print(i,v) --TP Bonus+25 end ``` --- addons/libs/extdata.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/extdata.lua b/addons/libs/extdata.lua index f839778a75..9344fe16f1 100644 --- a/addons/libs/extdata.lua +++ b/addons/libs/extdata.lua @@ -305,7 +305,7 @@ augment_values = { [0x15E] = {{stat="Occ. maximizes magic accuracy ", offset=1,percent=true}}, [0x15F] = {{stat="Occ. quickens spellcasting ", offset=1,percent=true}}, [0x160] = {{stat="Occ. grants dmg. bonus based on TP ", offset=1,percent=true}}, - [0x161] = {{stat="TP Bonus ", offset=1, multiplier=5}}, + [0x161] = {{stat="TP Bonus ", offset=1, multiplier=50}}, [0x162] = {{stat="Quadruple Attack ", offset=1}}, [0x164] = {{stat='Potency of "Cure" effect received', offset=1, percent=true}}, From 3ae2922e73fff36fa547d639415a9ca8bed36686 Mon Sep 17 00:00:00 2001 From: from20020516 Date: Thu, 7 Jun 2018 14:28:46 +0900 Subject: [PATCH 0147/1002] [bugfix] bluguide.lua fix for players with less than 1200 BLU job points. var jobpointsspent returns too big value because probably updated player.job_points.blu --- addons/bluguide/masterlist.lua | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/addons/bluguide/masterlist.lua b/addons/bluguide/masterlist.lua index 0c1dcd6682..eaed220323 100644 --- a/addons/bluguide/masterlist.lua +++ b/addons/bluguide/masterlist.lua @@ -31,10 +31,7 @@ local function get_limits() level = player.sub_job_level end - local jobpointsspent = 0 - for k, v in pairs(player.job_points.blu) do - jobpointsspent = jobpointsspent + (v^2 + v)/2 - end + local jobpointsspent = player.job_points.blu.jp_spent if jobpointsspent >= 1200 then gifts = 2 elseif jobpointsspent >= 100 then @@ -168,7 +165,7 @@ end return spelllist ---Copyright 2015, Anissa +--Copyright © 2015, Anissa --All rights reserved. --Redistribution and use in source and binary forms, with or without @@ -192,4 +189,4 @@ return spelllist --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. \ No newline at end of file +--SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. From 976a05910687a2504a3283ceed851e4a857d488a Mon Sep 17 00:00:00 2001 From: Chiaia Date: Thu, 7 Jun 2018 02:17:07 -0400 Subject: [PATCH 0148/1002] Slips 26-27 --- addons/organizer/organizer.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/organizer/organizer.lua b/addons/organizer/organizer.lua index d5590b3407..27e2a46536 100644 --- a/addons/organizer/organizer.lua +++ b/addons/organizer/organizer.lua @@ -201,7 +201,7 @@ function options_load( ) if(settings.retain.slips == true) then org_verbose("Slips set to retain") - slips = {29312,29313,29314,29315,29316,29317,29318,29319,29320,29321,29322,29323,29324,29325,29326,29327,29328,29329,29330,29331,29332,29333,29334,29335,29336} + slips = {29312,29313,29314,29315,29316,29317,29318,29319,29320,29321,29322,29323,29324,29325,29326,29327,29328,29329,29330,29331,29332,29333,29334,29335,29336,29337,29338} for _,slips_id in pairs(slips) do _retain[slips_id] = "slips" org_debug("settings", "Adding ("..res.items[slips_id].english..') to slip retain list') From 22820f20d4c764c55b92667b49d7c902d77658fc Mon Sep 17 00:00:00 2001 From: Chiaia Date: Thu, 7 Jun 2018 02:20:18 -0400 Subject: [PATCH 0149/1002] Slips 26-27 --- addons/findAll/findAll.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/findAll/findAll.lua b/addons/findAll/findAll.lua index ea4b59f2e0..e10f6a281e 100644 --- a/addons/findAll/findAll.lua +++ b/addons/findAll/findAll.lua @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'findAll' _addon.author = 'Zohno' -_addon.version = '1.20180415' +_addon.version = '1.20180607' _addon.commands = {'findall'} require('chat') @@ -189,7 +189,7 @@ storages_order = S(res.bags:map(string.gsub-{' ', ''} .. string.lower .. return index1 < index2 end) -storage_slips_order = L{'slip 01', 'slip 02', 'slip 03', 'slip 04', 'slip 05', 'slip 06', 'slip 07', 'slip 08', 'slip 09', 'slip 10', 'slip 11', 'slip 12', 'slip 13', 'slip 14', 'slip 15', 'slip 16', 'slip 17', 'slip 18', 'slip 19', 'slip 20', 'slip 21', 'slip 22', 'slip 23', 'slip 24', 'slip 25'} +storage_slips_order = L{'slip 01', 'slip 02', 'slip 03', 'slip 04', 'slip 05', 'slip 06', 'slip 07', 'slip 08', 'slip 09', 'slip 10', 'slip 11', 'slip 12', 'slip 13', 'slip 14', 'slip 15', 'slip 16', 'slip 17', 'slip 18', 'slip 19', 'slip 20', 'slip 21', 'slip 22', 'slip 23', 'slip 24', 'slip 25', 'slip 26', 'slip 27'} merged_storages_orders = storages_order + storage_slips_order + L{'key items'} function search(query, export) From 994efc7786410e688c661d0abd453c729420cccc Mon Sep 17 00:00:00 2001 From: from20020516 Date: Thu, 7 Jun 2018 16:04:32 +0900 Subject: [PATCH 0150/1002] changed to use /ma "Warp" if possible. --- addons/MyHome/MyHome.lua | 9 ++++++--- addons/MyHome/README.md | 26 +++++++++++++++++++++----- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/addons/MyHome/MyHome.lua b/addons/MyHome/MyHome.lua index 5606cb241c..e9db017727 100644 --- a/addons/MyHome/MyHome.lua +++ b/addons/MyHome/MyHome.lua @@ -80,15 +80,18 @@ function search_item() break; end else - log(stats[lang],false) + log('You don\'t have '..stats[lang]..'.') end end end windower.register_event('addon command',function() local player = windower.ffxi.get_player() - if S{player.main_job_id,player.sub_job_id}[4] then --BLM - local spell = {japanese='デジョンII',english='"Warp II"'} + local get_spells = windower.ffxi.get_spells() + local spell = S{player.main_job_id,player.sub_job_id}[4] + and (get_spells[261] and {japanese='デジョン',english='"Warp"'} + or get_spells[262] and {japanese='デジョンII',english='"Warp II"'}) + if spell then windower.chat.input('/ma '..windower.to_shift_jis(spell[lang])..' ') else search_item() diff --git a/addons/MyHome/README.md b/addons/MyHome/README.md index 6c616795cd..f0d564d5e5 100644 --- a/addons/MyHome/README.md +++ b/addons/MyHome/README.md @@ -1,10 +1,26 @@ # MyHome +## English - Automatically choose and uses a warp spell or an item. -## Command +### Command - `//mh` OR `//warp` - Priorities are: - 1. Warp II - require main or sub job BLM. - 2. Warp Ring - search inventory and wardrobes. - 3. Warp Cudgel - search inventory and wardrobes. - 4. Instant Warp - search inventory. + 1. Warp - require learned and main job or sub job BLM. + 2. Warp II + 3. Warp Ring - search inventory and wardrobes. + 4. Warp Cudgel + 5. Instant Warp - search inventory. + +## 日本語 +- デジョンやデジョン系アイテムをリキャストに応じて自動で選択、使用します。 + +### Command +- `//mh` または `//warp` +- 優先順位: + + + 1. デジョン - 習得済かつメインまたはサポートジョブが黒魔道士 + 2. デジョンII + 3. デジョンリング - マイバッグ、またはワードローブ(1~4)を検索 + 4. デジョンカジェル + 5. 呪符デジョン - マイバッグを検索 From ae7b730f49a2d5bc47418c6a991c9796fd998d1c Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Sat, 9 Jun 2018 07:19:25 +0200 Subject: [PATCH 0151/1002] Craft: Syntax fixes --- addons/craft/craft.lua | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/addons/craft/craft.lua b/addons/craft/craft.lua index a16488ce08..aa8dc4c09c 100644 --- a/addons/craft/craft.lua +++ b/addons/craft/craft.lua @@ -100,13 +100,13 @@ local support_npcs = { local exceptions = { ['Geo Crystal'] = 6509, - ['Fire Card'] : 9764, - ['Ice Card'] : 9765, - ['Wind Card'] : 9766, - ['Earth Card'] : 9767, - ['Water Card'] : 9769, - ['Light Card']: 9770, - ['Dark Card']: 9771, + ['Fire Card'] = 9764, + ['Ice Card'] = 9765, + ['Wind Card'] = 9766, + ['Earth Card'] = 9767, + ['Water Card'] = 9769, + ['Light Card'] = 9770, + ['Dark Card'] = 9771, } local clusters = { From 060bcc5d575f33cd2032af2db1e8a6f33ecb8831 Mon Sep 17 00:00:00 2001 From: Byrth Date: Sat, 9 Jun 2018 23:55:21 -0400 Subject: [PATCH 0152/1002] Boxdestroyer v1.0.3 * Refined range clues. * Recommends whether you should examine or enter a number --- addons/boxdestroyer/boxdestroyer.lua | 237 +++++++++++++++++++++++++-- 1 file changed, 222 insertions(+), 15 deletions(-) diff --git a/addons/boxdestroyer/boxdestroyer.lua b/addons/boxdestroyer/boxdestroyer.lua index 286b086b2e..e7ecdc591b 100644 --- a/addons/boxdestroyer/boxdestroyer.lua +++ b/addons/boxdestroyer/boxdestroyer.lua @@ -28,13 +28,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- addon information _addon.name = 'boxdestroyer' -_addon.version = '1.0.2' +_addon.version = '1.0.3' _addon.command = 'boxdestroyer' _addon.author = 'Seth VanHeulen (Acacia@Odin)' -- modules require('pack') +require('tables') -- load message constants @@ -54,17 +55,24 @@ default = { 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 } +observed_default = { + ['second_even_odd'] = false, + ['first_even_odd'] = false, + ['range'] = false, + ['equal'] = false, + ['second_multiple'] = false, + ['first_multiple'] = false +} + -- global variables box = {} +observed = {} zone_id = windower.ffxi.get_info().zone -- filter helper functions function greater_less(id, greater, num) - if box[id] == nil then - box[id] = default - end local new = {} for _,v in pairs(box[id]) do if greater and v > num or not greater and v < num then @@ -75,9 +83,6 @@ function greater_less(id, greater, num) end function even_odd(id, div, rem) - if box[id] == nil then - box[id] = default - end local new = {} for _,v in pairs(box[id]) do if (math.floor(v / div) % 2) == rem then @@ -88,9 +93,6 @@ function even_odd(id, div, rem) end function equal(id, first, num) - if box[id] == nil then - box[id] = default - end local new = {} for _,v in pairs(box[id]) do if first and math.floor(v / 10) == num or not first and (v % 10) == num then @@ -100,6 +102,154 @@ function equal(id, first, num) return new end +function exclusive_mean(counts) + total = 0 + for _,v in pairs(counts) do + total = total + v + end + weighted_mean = 0 + for _,v in pairs(counts) do + weighted_mean = weighted_mean + (total - v) * v / total + end + return weighted_mean +end + +function calculate_odds(id,chances) + local reductions = {} + if not observed[id].first_even_odd then + local counter = {0} + counter[0] = 0 + for _,v in pairs(box[id]) do + counter[math.floor(v / 10) % 2] = counter[math.floor(v / 10) % 2] + 1 + end + reductions[#reductions+1] = exclusive_mean(counter) + end + if not observed[id].second_even_odd then + local counter = {0} + counter[0] = 0 + for _,v in pairs(box[id]) do + counter[v % 2] = counter[v % 2] + 1 + end + reductions[#reductions+1] = exclusive_mean(counter) + end + if not observed[id].range then + local new = {} + local reduction = 0 + for i,v in pairs(box[id]) do + new[i] = 0 + for _,m in pairs(box[id]) do + if m-v > 16 then break end + new[i] = new[i] + math.max(16-math.abs(m - v),0)^2/256 + end + reduction = reduction + (#box[id] - new[i])/#box[id] + end + + reductions[#reductions+1] = reduction + end + if not observed[id].equal then + local counter = {0,0,0,0,0,0,0,0,0} + counter[0] = 0 + local eliminated = {0,0,0,0,0,0,0,0,0} + eliminated[0] = 0 + for _,v in pairs(box[id]) do + counter[math.floor(v / 10)] = counter[math.floor(v / 10)] + 1/2 + counter[v % 10] = counter[v % 10] + 1/2 + for i = 0,9 do + if i ~= v % 10 and i ~= math.floor(v / 10) then + eliminated[i] = eliminated[i] + 1 + end + end + end + + reduction = 0 + for i,v in pairs(counter) do + reduction = reduction + eliminated[i] * v / #box[id] + end + + reductions[#reductions+1] = reduction + end + if not observed[id].second_multiple then + local counter = {0,0,0,0,0,0,0,0,0} + counter[0] = 0 + for _,v in pairs(box[id]) do + counter[v % 10] = counter[v % 10] + 1 + end + + local weights = { + counter[0] + counter[1]/2 + counter[2]/3, + counter[1]/2 + counter[2]/3 + counter[3]/3, + counter[2]/3 + counter[3]/3 + counter[4]/3, + counter[3]/3 + counter[4]/3 + counter[5]/3, + counter[4]/3 + counter[5]/3 + counter[6]/3, + counter[5]/3 + counter[6]/3 + counter[7]/3, + counter[6]/3 + counter[7]/3 + counter[8]/2, + counter[7]/3 + counter[8]/2 + counter[9] + } + + local eliminated = { + counter[3] + counter[4] + counter[5] + counter[6] + counter[7] + counter[8] + counter[9], + counter[0] + counter[4] + counter[5] + counter[6] + counter[7] + counter[8] + counter[9], + counter[0] + counter[1] + counter[5] + counter[6] + counter[7] + counter[8] + counter[9], + counter[0] + counter[1] + counter[2] + counter[6] + counter[7] + counter[8] + counter[9], + counter[0] + counter[1] + counter[2] + counter[3] + counter[7] + counter[8] + counter[9], + counter[0] + counter[1] + counter[2] + counter[3] + counter[4] + counter[8] + counter[9], + counter[0] + counter[1] + counter[2] + counter[3] + counter[4] + counter[5] + counter[9], + counter[0] + counter[1] + counter[2] + counter[3] + counter[4] + counter[5] + counter[6] + } + + local reduction = 0 + for i,v in pairs(weights) do + reduction = reduction + eliminated[i] * v / #box[id] + end + + reductions[#reductions + 1] = reduction + end + if not observed[id].first_multiple then + local counter = {0,0,0,0,0,0,0,0,0} + for _,v in pairs(box[id]) do + counter[math.floor(v / 10)] = counter[math.floor(v / 10)] + 1 + end + + local weights = { + counter[1] + counter[2]/2 + counter[3]/3, + counter[2]/2 + counter[3]/3 + counter[4]/3, + counter[3]/3 + counter[4]/3 + counter[5]/3, + counter[4]/3 + counter[5]/3 + counter[6]/3, + counter[5]/3 + counter[6]/3 + counter[7]/3, + counter[6]/3 + counter[7]/3 + counter[8]/2, + counter[7]/3 + counter[8]/2 + counter[9] + } + + local eliminated = { + counter[4] + counter[5] + counter[6] + counter[7] + counter[8] + counter[9], + counter[1] + counter[5] + counter[6] + counter[7] + counter[8] + counter[9], + counter[1] + counter[2] + counter[6] + counter[7] + counter[8] + counter[9], + counter[1] + counter[2] + counter[3] + counter[7] + counter[8] + counter[9], + counter[1] + counter[2] + counter[3] + counter[4] + counter[8] + counter[9], + counter[1] + counter[2] + counter[3] + counter[4] + counter[5] + counter[9], + counter[1] + counter[2] + counter[3] + counter[4] + counter[5] + counter[6] + } + + local reduction = 0 + for i,v in pairs(weights) do + reduction = reduction + eliminated[i] * v / #box[id] + end + + reductions[#reductions + 1] = reduction + end + + local expected_examine_value = 0 + for _,v in pairs(reductions) do + expected_examine_value = expected_examine_value + v/#reductions + end + + local optimal_guess = math.ceil(#box[id] / 2) + + local expected_guess_value = 2*optimal_guess - 2*optimal_guess^2 / #box[id] + 2*optimal_guess/#box[id] - 1 / #box[id] + + return expected_examine_value, expected_guess_value +end + -- display helper function function display(id, chances) @@ -112,7 +262,32 @@ function display(id, chances) if remaining == 0 then remaining = 1 end - windower.add_to_chat(207, 'best guess: %d (%d%%)':format(box[id][math.ceil(#box[id] / 2)], 1 / remaining * 100)) + + if chances == 1 and observed[id].equal then + -- The "equal" message (== "X") for X in 1..9 gives an unequal probability to the remaining options + -- because "XX" is twice as likely to be indicated by the "equal" message. + -- This is too annoying to propagate to the rest of the addon, although it should be some day. + local printed = false + for _,v in pairs(box[id]) do + if math.floor(v/10) == v%10 then + windower.add_to_chat(207, 'best guess: %d (%d%%)':format(v, 1 / remaining * 100)) + printed = true + break + end + end + if not printed then + windower.add_to_chat(207, 'best guess: %d (%d%%)':format(box[id][math.ceil(#box[id] / 2)], 1 / remaining * 100)) + end + else + windower.add_to_chat(207, 'best guess: %d (%d%%)':format(box[id][math.ceil(#box[id] / 2)], 1 / remaining * 100)) + local clue_value,guess_value = calculate_odds(id,chances) + if clue_value > guess_value and remaining ~= 1 then + windower.add_to_chat(207, 'boxdestroyer recommends examining the chest') + else + windower.add_to_chat(207, 'boxdestroyer recommends guessing %d':format(box[id][math.ceil(#box[id] / 2)])) + end + end + end -- ID obtaining helper function @@ -128,26 +303,51 @@ function check_incoming_chunk(id, original, modified, injected, blocked) elseif messages[zone_id] then if id == 0x0B then box = {} + observed = {} elseif id == 0x2A then local box_id = original:unpack('I', 5) local param0 = original:unpack('I', 9) local param1 = original:unpack('I', 13) local param2 = original:unpack('I', 17) local message_id = original:unpack('H', 27) % 0x8000 + + if box[box_id] == nil then + box[box_id] = default + end + if observed[box_id] == nil then + observed[box_id] = table.copy(observed_default) + end + if get_id(zone_id,'greater_less') == message_id then + -- It is unclear how these messages (caused by Thief's tools) work box[box_id] = greater_less(box_id, param1 == 0, param0) elseif get_id(zone_id,'second_even_odd') == message_id then + -- tells whether the second digit is even or odd box[box_id] = even_odd(box_id, 1, param0) + observed[box_id].second_even_odd = true elseif get_id(zone_id,'first_even_odd') == message_id then + -- tells whether the first digit is even or odd box[box_id] = even_odd(box_id, 10, param0) + observed[box_id].first_even_odd = true elseif get_id(zone_id,'range') == message_id then - box[box_id] = greater_less(box_id, true, param0) - box[box_id] = greater_less(box_id, false, param1) + -- lower bound (param0) = solution - RANDINT(5,20) + -- upper bound (param1) = solution + RANDINT(5,20) + -- param0 + 21 > solution > param0 + 4 + -- param1 - 4 > solution > param1 - 21 + -- if the bound is less than 10 or greater than 99, the message changes to "greater" or "less" respectively + box[box_id] = greater_less(box_id, true, math.max(param1-21,param0+4) ) + box[box_id] = greater_less(box_id, false, math.min(param0+21,param1-4) ) + observed[box_id].range = true elseif get_id(zone_id,'less') == message_id then - box[box_id] = greater_less(box_id, false, param0) + -- Less is a range with 9 as the lower bound + box[box_id] = greater_less(box_id, false, math.min(9+21,param0-4) ) + observed[box_id].range = true elseif get_id(zone_id,'greater') == message_id then - box[box_id] = greater_less(box_id, true, param0) + -- Greater is a range with 100 as the upper bound + box[box_id] = greater_less(box_id, true, math.max(100-21,param0+4) ) + observed[box_id].range = true elseif get_id(zone_id,'equal') == message_id then + -- single number that is either the first or second digit of the solution local new = equal(box_id, true, param0) local duplicate = param0 * 10 + param0 for k,v in pairs(new) do @@ -158,18 +358,23 @@ function check_incoming_chunk(id, original, modified, injected, blocked) for _,v in pairs(equal(box_id, false, param0)) do table.insert(new, v) end table.sort(new) box[box_id] = new + observed[box_id].equal = true elseif get_id(zone_id,'second_multiple') == message_id then + -- three digit range including the second digit of the solution local new = equal(box_id, false, param0) for _,v in pairs(equal(box_id, false, param1)) do table.insert(new, v) end for _,v in pairs(equal(box_id, false, param2)) do table.insert(new, v) end table.sort(new) box[box_id] = new + observed[box_id].second_multiple = true elseif get_id(zone_id,'first_multiple') == message_id then + -- three digit range including the first digit of the solution local new = equal(box_id, true, param0) for _,v in pairs(equal(box_id, true, param1)) do table.insert(new, v) end for _,v in pairs(equal(box_id, true, param2)) do table.insert(new, v) end table.sort(new) box[box_id] = new + observed[box_id].first_multiple = true elseif get_id(zone_id,'success') == message_id or get_id(zone_id,'failure') == message_id then box[box_id] = nil end @@ -179,6 +384,7 @@ function check_incoming_chunk(id, original, modified, injected, blocked) local chances = original:byte(9) if box[box_id] == nil then box[box_id] = default + observed[box_id] = observed_default end if chances > 0 and chances < 7 then display(box_id, chances) @@ -186,6 +392,7 @@ function check_incoming_chunk(id, original, modified, injected, blocked) end elseif id == 0x5B then box[original:unpack('I', 17)] = nil + observed[original:unpack('I', 17)] = nil end end end From 63c9d0333cd27f40ef654acb67cd5f52b330723d Mon Sep 17 00:00:00 2001 From: from20020516 Date: Mon, 11 Jun 2018 17:24:28 +0900 Subject: [PATCH 0153/1002] update README.md --- addons/MyHome/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/addons/MyHome/README.md b/addons/MyHome/README.md index f0d564d5e5..849497bfae 100644 --- a/addons/MyHome/README.md +++ b/addons/MyHome/README.md @@ -4,9 +4,11 @@ ### Command - `//mh` OR `//warp` + + - Priorities are: - 1. Warp - require learned and main job or sub job BLM. - 2. Warp II + 1. Warp - require learned and main job or sub job BLM. + 2. Warp II 3. Warp Ring - search inventory and wardrobes. 4. Warp Cudgel 5. Instant Warp - search inventory. From 7c13a184c0b8a57d98bf45a0e7c0f807ecc59dcb Mon Sep 17 00:00:00 2001 From: from20020516 Date: Mon, 11 Jun 2018 17:36:00 +0900 Subject: [PATCH 0154/1002] initial commit new addon 'Tab' (after once Undo.) --- addons/Tab/README.md | 9 ++++++++ addons/Tab/tab.lua | 53 ++++++++++++++++++++++++++++++++++++++++++++ addons/addons.xml | 7 ++++++ 3 files changed, 69 insertions(+) create mode 100644 addons/Tab/README.md create mode 100644 addons/Tab/tab.lua diff --git a/addons/Tab/README.md b/addons/Tab/README.md new file mode 100644 index 0000000000..a98513269c --- /dev/null +++ b/addons/Tab/README.md @@ -0,0 +1,9 @@ +# Tab + +### English +- Simple addon Replace Tab key input to `` or ``. (X+Tab) +- **Tips:** if you won't to include pet or trust in `` by other players, use `/ignorepet on` and `/ignoretrust on` (in-game commands) + +### 日本語 +- Tabキーの動作を``または``(X+Tab)に置き換えます。 +- **Tips:** ``に他プレイヤーのペットやフェイスを含めたくない場合、`/ignorepet on` または `/ignorefaith on`(ゲーム内コマンド)をご利用ください。 diff --git a/addons/Tab/tab.lua b/addons/Tab/tab.lua new file mode 100644 index 0000000000..67bd2d5631 --- /dev/null +++ b/addons/Tab/tab.lua @@ -0,0 +1,53 @@ +--[[ +Copyright © 2018, from20020516 +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 Tab 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 from20020516 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.name = 'Tab' +_addon.author = 'from20020516' +_addon.version = '1.0' + +key_flags={} + +--replace input tab. validated in Japanese keyboard. please let me know if problems occur with the English keyboard. +windower.register_event('keyboard',function(dik,flags,blocked) + key_flags[dik] = flags + if flags and not windower.chat.is_open(true) then + if dik == 15 and not st then --Tab + st = key_flags[45] and '' or '' --X + windower.chat.input('/ta '..st) + return true; --tab input blocking. it's probably broken.. + elseif dik == 1 or dik == 28 then --Esc or Enter + st = false + end + end +end) + +--block error message. +windower.register_event('incoming text',function(original,modified,original_mode) + if original_mode == 123 and st then + return true; --error message blocking when target doesn't exists. + end +end) diff --git a/addons/addons.xml b/addons/addons.xml index 5765a7c6cb..6e1562c7ca 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -739,4 +739,11 @@ https://github.com/from20020516/Lua/issues https://twitter.com/from20020516 + + Tab + Centurio aka from20020516 + Simple addon Replace Tab key input to <stnpc> or X+Tab to <stpc>. + https://github.com/from20020516/Lua/issues + https://twitter.com/from20020516 + From 31349d7c07be1a11f26c00a828a57a67dc837e62 Mon Sep 17 00:00:00 2001 From: aukon Date: Mon, 11 Jun 2018 11:36:28 +0100 Subject: [PATCH 0155/1002] Update to handle new resources --- addons/Debuffed/Debuffed.lua | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/addons/Debuffed/Debuffed.lua b/addons/Debuffed/Debuffed.lua index dc341069bf..0c3555ac82 100644 --- a/addons/Debuffed/Debuffed.lua +++ b/addons/Debuffed/Debuffed.lua @@ -101,23 +101,13 @@ function update_box() end end -function convert_overwrites(spell) - local str = res.spells[spell].overwrites - local t = {} - - if str then - str:gsub("[0-9]+",function(s) table.insert(t, tonumber(s)) end) - end - return L(t) -end - function handle_overwrites(target, new, t) if not debuffed_mobs[target] then return true end for effect, spell in pairs(debuffed_mobs[target]) do - local old = convert_overwrites(spell[1]) + local old = res.spells[spell[1]].overwrites -- Check if there isn't a higher priority debuff active if old:length() > 0 then @@ -146,7 +136,7 @@ function apply_debuff(target, effect, spell) end -- Check overwrite conditions - local overwrites = convert_overwrites(spell) + local overwrites = res.spells[spell].overwrites if not handle_overwrites(target, spell, overwrites) then return end @@ -155,8 +145,22 @@ function apply_debuff(target, effect, spell) debuffed_mobs[target][effect] = {spell, os.clock() + res.spells[spell].duration} end +function handle_shot(target) + if not debuffed_mobs[target] or not debuffed_mobs[target][134] then + return true + end + + local current = debuffed_mobs[target][134][1] + if current < 26 then + debuffed_mobs[target][134][1] = current + 1 + end +end + function inc_action(act) if act.category ~= 4 then + if act.category == 6 and act.param == 131 then + handle_shot(act.targets[1].id) + end return end From 2aaff0f32d6b0f70665d741935eb57cc06bb9616 Mon Sep 17 00:00:00 2001 From: from20020516 Date: Mon, 11 Jun 2018 19:42:41 +0900 Subject: [PATCH 0156/1002] Tab: keyboard event argment added. --- addons/Tab/tab.lua | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/addons/Tab/tab.lua b/addons/Tab/tab.lua index 67bd2d5631..22441541be 100644 --- a/addons/Tab/tab.lua +++ b/addons/Tab/tab.lua @@ -29,14 +29,16 @@ _addon.name = 'Tab' _addon.author = 'from20020516' _addon.version = '1.0' -key_flags={} +st = false +x_pressed = false --replace input tab. validated in Japanese keyboard. please let me know if problems occur with the English keyboard. -windower.register_event('keyboard',function(dik,flags,blocked) - key_flags[dik] = flags - if flags and not windower.chat.is_open(true) then - if dik == 15 and not st then --Tab - st = key_flags[45] and '' or '' --X +windower.register_event('keyboard',function(dik,pressed,flags,blocked) + if not windower.chat.is_open() then + if dik == 45 then + x_pressed = pressed + elseif dik == 15 and not st then --Tab + st = x_pressed and '' or '' windower.chat.input('/ta '..st) return true; --tab input blocking. it's probably broken.. elseif dik == 1 or dik == 28 then --Esc or Enter @@ -44,10 +46,3 @@ windower.register_event('keyboard',function(dik,flags,blocked) end end end) - ---block error message. -windower.register_event('incoming text',function(original,modified,original_mode) - if original_mode == 123 and st then - return true; --error message blocking when target doesn't exists. - end -end) From 8c1d893f3494321243bb6e1dd940359a4cd4b086 Mon Sep 17 00:00:00 2001 From: from20020516 Date: Mon, 11 Jun 2018 19:54:18 +0900 Subject: [PATCH 0157/1002] Tab: Changed event triggers only if true. --- addons/Tab/tab.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/addons/Tab/tab.lua b/addons/Tab/tab.lua index 22441541be..b1ad3a952e 100644 --- a/addons/Tab/tab.lua +++ b/addons/Tab/tab.lua @@ -29,6 +29,7 @@ _addon.name = 'Tab' _addon.author = 'from20020516' _addon.version = '1.0' +require('sets') st = false x_pressed = false @@ -37,11 +38,11 @@ windower.register_event('keyboard',function(dik,pressed,flags,blocked) if not windower.chat.is_open() then if dik == 45 then x_pressed = pressed - elseif dik == 15 and not st then --Tab + elseif dik == 15 and pressed and not st then --Tab st = x_pressed and '' or '' windower.chat.input('/ta '..st) return true; --tab input blocking. it's probably broken.. - elseif dik == 1 or dik == 28 then --Esc or Enter + elseif S{1,28}[dik] and pressed then --Esc or Enter st = false end end From 82f984d1d7434b658524e9204939e0e6f93a2cd4 Mon Sep 17 00:00:00 2001 From: from20020516 Date: Tue, 12 Jun 2018 09:09:25 +0900 Subject: [PATCH 0158/1002] Tab: Update --- addons/Tab/tab.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/Tab/tab.lua b/addons/Tab/tab.lua index b1ad3a952e..b3ddd013d3 100644 --- a/addons/Tab/tab.lua +++ b/addons/Tab/tab.lua @@ -35,10 +35,10 @@ x_pressed = false --replace input tab. validated in Japanese keyboard. please let me know if problems occur with the English keyboard. windower.register_event('keyboard',function(dik,pressed,flags,blocked) - if not windower.chat.is_open() then - if dik == 45 then - x_pressed = pressed - elseif dik == 15 and pressed and not st then --Tab + if dik == 45 then + x_pressed = pressed + elseif not windower.chat.is_open(true) then + if dik == 15 and pressed and not st then --Tab st = x_pressed and '' or '' windower.chat.input('/ta '..st) return true; --tab input blocking. it's probably broken.. From 8e82b74949b86492897dcf245aba0335be449bb1 Mon Sep 17 00:00:00 2001 From: from20020516 Date: Tue, 12 Jun 2018 09:13:09 +0900 Subject: [PATCH 0159/1002] Tab: Update addons.xml --- addons/Tab/tab.lua | 2 +- addons/addons.xml | 15 +++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/addons/Tab/tab.lua b/addons/Tab/tab.lua index b3ddd013d3..cae63eaf58 100644 --- a/addons/Tab/tab.lua +++ b/addons/Tab/tab.lua @@ -37,7 +37,7 @@ x_pressed = false windower.register_event('keyboard',function(dik,pressed,flags,blocked) if dik == 45 then x_pressed = pressed - elseif not windower.chat.is_open(true) then + elseif not windower.chat.is_open() then if dik == 15 and pressed and not st then --Tab st = x_pressed and '' or '' windower.chat.input('/ta '..st) diff --git a/addons/addons.xml b/addons/addons.xml index 5527fd6961..777229bbd3 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -740,18 +740,17 @@ https://twitter.com/from20020516 -<<<<<<< HEAD - Tab - Centurio aka from20020516 - Simple addon Replace Tab key input to <stnpc> or X+Tab to <stpc>. - https://github.com/from20020516/Lua/issues - https://twitter.com/from20020516 -======= Debuffed Auk Tracks and displays debuffs on your current target. https://github.com/aukon/Lua/issues https://discord.gg/b275nMv ->>>>>>> upstream/dev + + + Tab + Centurio aka from20020516 + Simple addon Replace Tab key input to <stnpc> or X+Tab to <stpc>. + https://github.com/from20020516/Lua/issues + https://twitter.com/from20020516 From 8af387e0f351990f79f77647f34c9ca87a97abf9 Mon Sep 17 00:00:00 2001 From: from20020516 Date: Tue, 12 Jun 2018 10:55:19 +0900 Subject: [PATCH 0160/1002] [bugfix] Gearswap/triggers.lua for work 'Area Display' effect while , and in JP client. I'd like you to merge If there is no problem in English environment. --- addons/GearSwap/triggers.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/GearSwap/triggers.lua b/addons/GearSwap/triggers.lua index b9b361adb7..5c09027641 100644 --- a/addons/GearSwap/triggers.lua +++ b/addons/GearSwap/triggers.lua @@ -77,7 +77,7 @@ windower.register_event('outgoing text',function(original,modified,blocked,ffxi, if unified_prefix and temptarg and (validabils[language][unified_prefix][abil] or unified_prefix=='/ra') then if st_flag then st_flag = nil - return true + return modified elseif temp_mob_arr then refresh_globals() @@ -338,4 +338,4 @@ parse.i[0x029] = function (data) equip_sets(prefix..'aftercast',ts,tab.spell) end end -end \ No newline at end of file +end From 92bfbc99d66f573d4a3a3d8b002c5e11254e1d39 Mon Sep 17 00:00:00 2001 From: Matt Hernandez Date: Tue, 12 Jun 2018 13:25:52 -0700 Subject: [PATCH 0161/1002] Add list command to Trusts addon. Added `//tru list` command to show saved sets. Tested on the latest client. --- addons/Trusts/README.md | 3 +++ addons/Trusts/Trusts.lua | 15 +++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/addons/Trusts/README.md b/addons/Trusts/README.md index a6e7765fa3..463026e6da 100644 --- a/addons/Trusts/README.md +++ b/addons/Trusts/README.md @@ -2,6 +2,7 @@ - //tru save `` : Save trusts in current party. - //tru `` : Calls trusts you saved. +- //tru list : Lists your saved sets. - //tru random : What's your fortune today? - //tru check : List of unlearned trusts. gotta catch 'em all! @@ -14,6 +15,8 @@ - 呼び出し先と"同枠"のフェイスは戻す - 既にPTにいる場合は戻さない = 倒れたフェイスの補充が可能 - リキャストが不足している場合は戻さない +- //tru list + - 保存したセットを一覧表示します。 - //tru random - フェイスガチャ。PT枠上限までランダムで召喚 - //tru check diff --git a/addons/Trusts/Trusts.lua b/addons/Trusts/Trusts.lua index 99800e75d8..20cf4aa647 100644 --- a/addons/Trusts/Trusts.lua +++ b/addons/Trusts/Trusts.lua @@ -74,12 +74,15 @@ windower.register_event('addon command',function(...) chat(1,'Trusts - Command List:') chat(207,'//tru '..color('save ',166,160)..' --Save trusts in current party.') chat(207,'//tru '..color('',166,160)..' --Calls trusts you saved.') + chat(207,'//tru '..color('list',166,160)..' --Lists your saved sets.') chat(207,'//tru '..color('random',166,160)..' --What\'s your fortune today?') chat(207,'//tru '..color('check',166,160)..' --List of unlearned trusts. gotta catch \'em all!') elseif cmd[1] == 'save' then save_set(cmd[2]) elseif cmd[1] == 'check' then check_learned() + elseif cmd[1] == 'list' then + list_sets() else call_set(cmd[1] or 'default') end @@ -100,6 +103,18 @@ function save_set(set) log('set '..set..' saved.') end +function list_sets() + local chat = windower.add_to_chat + settings = config.load() + chat(1, 'Trusts - Saved sets:') + + for set, _ in pairs(settings.sets) do + if set ~= 'default' then + chat(207, set) + end + end +end + function check_lang(entity) return {japanese=entity.japanese,english=entity.english}[lang]; end From 6d52961a3415586811f15194a20faee193404196 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Sun, 17 Jun 2018 17:32:47 +0200 Subject: [PATCH 0162/1002] Fixed addons.xml --- addons/addons.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/addons.xml b/addons/addons.xml index 777229bbd3..87452f596c 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -554,7 +554,7 @@ SpellBook Sigil Baram (Ravlyn@Asura) List unknown spells by job or category. Can also limit results by level or spent jp required by the spell. - https://github.com/sigilbaram/SpellBook/issues + https://github.com/sigilbaram/SpellBook/issues https://discord.gg/b275nMv From 6d98f77ed4d591311314acb93a538e5a438cdb05 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Mon, 18 Jun 2018 21:21:35 +0200 Subject: [PATCH 0163/1002] Fixed packet parsing for unknown non-numerical enum values --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index c7039e64f3..a8de30a672 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -265,7 +265,7 @@ local enums = { } local e = function(t, val) - return enums[t][val] or 'Unknown value for \'%s\': %i':format(t, val) + return enums[t][val] or 'Unknown value for \'%s\': %s':format(t, tostring(val)) end --[[ From 5e3aeb00ae3fe2fcd51a8a67ca2185401f9abdc2 Mon Sep 17 00:00:00 2001 From: from20020516 Date: Tue, 19 Jun 2018 11:25:21 +0900 Subject: [PATCH 0164/1002] Update to check MP when you BLM. --- addons/MyHome/MyHome.lua | 6 +++--- addons/addons.xml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/MyHome/MyHome.lua b/addons/MyHome/MyHome.lua index e9db017727..a701f4f0a4 100644 --- a/addons/MyHome/MyHome.lua +++ b/addons/MyHome/MyHome.lua @@ -59,7 +59,7 @@ function search_item() local enchant = ext.type == 'Enchanted Equipment' local recast = enchant and ext.charges_remaining > 0 and math.max(ext.next_use_time+18000-os.time(),0) local usable = recast and recast == 0 - log(stats[lang],usable and '' or recast..' sec recast.') + log(stats[lang],usable and '' or recast and recast..' sec recast.') if usable or ext.type == 'General' then if enchant and item.status ~= 5 then --not equipped set_equip(item.slot,stats.slot,item.bag) @@ -89,8 +89,8 @@ windower.register_event('addon command',function() local player = windower.ffxi.get_player() local get_spells = windower.ffxi.get_spells() local spell = S{player.main_job_id,player.sub_job_id}[4] - and (get_spells[261] and {japanese='デジョン',english='"Warp"'} - or get_spells[262] and {japanese='デジョンII',english='"Warp II"'}) + and (get_spells[261] and player.vitals.mp >= 100 and {japanese='デジョン',english='"Warp"'} + or get_spells[262] and player.vitals.mp >= 150 and {japanese='デジョンII',english='"Warp II"'}) if spell then windower.chat.input('/ma '..windower.to_shift_jis(spell[lang])..' ') else diff --git a/addons/addons.xml b/addons/addons.xml index 87452f596c..cacab5fa53 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -735,7 +735,7 @@ MyHome Centurio aka from20020516 - Automatically choose and use warp spell or item. + Automatically choose and use a warp spell or an item. https://github.com/from20020516/Lua/issues https://twitter.com/from20020516 From 7e82a6c8f7ea112f1deedfefb97b087cd17dd9ba Mon Sep 17 00:00:00 2001 From: aukon Date: Sun, 24 Jun 2018 09:58:23 +0100 Subject: [PATCH 0165/1002] Fix nil errors --- addons/Debuffed/Debuffed.lua | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/addons/Debuffed/Debuffed.lua b/addons/Debuffed/Debuffed.lua index 0c3555ac82..54ea479188 100644 --- a/addons/Debuffed/Debuffed.lua +++ b/addons/Debuffed/Debuffed.lua @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'Debuffed' _addon.author = 'Auk' -_addon.version = '1.0.0.2' +_addon.version = '1.0.0.3' _addon.commands = {'dbf','debuffed'} config = require('config') @@ -107,10 +107,10 @@ function handle_overwrites(target, new, t) end for effect, spell in pairs(debuffed_mobs[target]) do - local old = res.spells[spell[1]].overwrites + local old = res.spells[spell[1]].overwrites or {} -- Check if there isn't a higher priority debuff active - if old:length() > 0 then + if table.length(old) > 0 then for _,v in ipairs(old) do if new == v then return false @@ -119,7 +119,7 @@ function handle_overwrites(target, new, t) end -- Check if a lower priority debuff is being overwritten - if t:length() > 0 then + if table.length(t) > 0 then for _,v in ipairs(t) do if spell[1] == v then debuffed_mobs[target][effect] = nil @@ -136,13 +136,13 @@ function apply_debuff(target, effect, spell) end -- Check overwrite conditions - local overwrites = res.spells[spell].overwrites + local overwrites = res.spells[spell].overwrites or {} if not handle_overwrites(target, spell, overwrites) then return end -- Create timer - debuffed_mobs[target][effect] = {spell, os.clock() + res.spells[spell].duration} + debuffed_mobs[target][effect] = {spell, os.clock() + res.spells[spell].duration or 0} end function handle_shot(target) From e3cce7d04bc2503c31f3490901698079525e1aec Mon Sep 17 00:00:00 2001 From: deadman80 Date: Mon, 25 Jun 2018 16:35:59 -0400 Subject: [PATCH 0166/1002] New Addon: EasyNuke Unified commands for single target and area of effect elemental magic and cures, plus Drain/Aspir and DRK Absorbs. --- addons/EasyNuke/EasyNuke.lua | 207 +++++++++++++++++++++++++++++++++++ addons/EasyNuke/readme.md | 68 ++++++++++++ 2 files changed, 275 insertions(+) create mode 100644 addons/EasyNuke/EasyNuke.lua create mode 100644 addons/EasyNuke/readme.md diff --git a/addons/EasyNuke/EasyNuke.lua b/addons/EasyNuke/EasyNuke.lua new file mode 100644 index 0000000000..53bf7237b7 --- /dev/null +++ b/addons/EasyNuke/EasyNuke.lua @@ -0,0 +1,207 @@ +--[[ +Copyright © 2018, FaceDesk Linkshell +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 findAll 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 FaceDesk Linkshell, or it's members, 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.name = 'EasyNuke' +_addon.author = 'FaceDesk Linkshell' +_addon.version = '1.0.2' +_addon.command = "ez" + +require('chat') +require('lists') +require('logger') +require('sets') +require('tables') +require('strings') +require('pack') + +file = require('files') +config = require('config') +texts = require('texts') +res = require('resources') + +local defaults = T{} +defaults.current_element = "fire" +defaults.target_mode = "t" +settings = config.load(defaults) + +current_element = "fire" +target_mode = "t" + +elements = T{"fire","wind","thunder","light","ice","water","earth","dark"} +elements_dark = T{"ice","water","earth","dark"} +elements_light = T{"fire","wind","thunder","light"} +elements_index = 1 +other_modes = T{"fire","wind","thunder","light","ice","water","earth","dark","drain","aspir","absorb","cure"} + +targets = T{"t","bt","stnpc"} +targets_index = 1 + +spell_tables = {} +spell_tables["fire"] = T{"Fire","Fire II","Fire III","Fire IV","Fire V","Fire VI",} +spell_tables["fire"]["ga"] = T{"Firaga","Firaga II","Firaga III","Firaja",} +spell_tables["fire"]["ra"] = T{"Fira","Fira II","Fira III"} +spell_tables["earth"] = T{"Stone","Stone II","Stone III","Stone IV","Stone V","Stone VI",} +spell_tables["earth"]["ga"] = T{"Stonega","Stonega II","Stonega III","Stoneja",} +spell_tables["earth"]["ra"] = T{"Stonera","Stonera II","Stonera III"} +spell_tables["wind"] = T{"Aero","Aero II","Aero III","Aero IV","Aero V","Aero VI",} +spell_tables["wind"]["ga"] = T{"Aeroga","Aeroga II","Aeroga III","Aeroja",} +spell_tables["wind"]["ra"] = T{"Aerora","Aerora II","Aerora III"} +spell_tables["water"] = T{"Water","Water II","Water III","Water IV","Water V","Water VI",} +spell_tables["water"]["ga"] = T{"Waterga","Waterga II","Waterga III","Waterja",} +spell_tables["water"]["ra"] = T{"Watera","Watera II","Watera III"} +spell_tables["ice"] = T{"Blizzard","Blizzard II","Blizzard III","Blizzard IV","Blizzard V","Blizzard VI",} +spell_tables["ice"]["ga"] = T{"Blizzaga","Blizzaga II","Blizzaga III","Blizzaja",} +spell_tables["ice"]["ra"] = T{"Blizzara","Blizzara II","Blizzara III"} +spell_tables["thunder"] = T{"Thunder","Thunder II","Thunder III","Thunder IV","Thunder V","Thunder VI",} +spell_tables["thunder"]["ga"] = T{"Thundaga","Thundaga II","Thundaga III","Thundaja",} +spell_tables["thunder"]["ra"] = T{"Thundara","Thundara II","Thundara III"} +spell_tables["light"] = T{"Banish","Banish II","Holy","Banish III",} +spell_tables["light"]["ga"] = T{"Banishga","Banishga II"} +spell_tables["dark"] = T{"Impact"} +spell_tables["dark"]["ga"] = T{"Comet"} +spell_tables["cure"] = T{"Cure","Cure II","Cure III","Cure IV","Cure V","Cure VI"} +spell_tables["cure"]["ga"] = T{"Curaga","Curaga II","Curaga III","Curaga IV","Curaga V",} +spell_tables["cure"]["ra"] = T{"Cura","Cura II","Cura III"} +spell_tables["drain"] = T{"Aspir","Aspir II","Aspir III","Drain","Drain II","Drain III"} +spell_tables["absorb"] = T{"Absorb-Acc","Absorb-TP","Absorb-Attri","Absorb-STR","Absorb-DEX","Absorb-VIT","Absorb-AGI","Absorb-INT","Absorb-MND","Absorb-CHR"} + +function find_index () + if current_element == "fire" then elements_index = 1 end + if current_element == "wind" then elements_index = 2 end + if current_element == "thunder" then elements_index = 3 end + if current_element == "light" then elements_index = 4 end + if current_element == "ice" then elements_index = 5 end + if current_element == "water" then elements_index = 6 end + if current_element == "earth" then elements_index = 7 end + if current_element == "dark" then elements_index = 8 end +end + +windower.register_event('addon command', function (command, arg) + + if command == 'boom' then + if arg == nil then arg = 1 end + arg = tonumber(arg) + if arg > #spell_tables[current_element] then windower.send_command("@input /echo Invalid Spell. Try again.") return end + local current_spell_table = spell_tables[current_element] + windower.send_command("@input /ma "..current_spell_table[arg].." <"..target_mode..">") + end + + if command == "boomga" then + if arg == nil then arg = 1 end + arg = tonumber(arg) + if arg > #spell_tables[current_element]["ga"] then windower.send_command("@input /echo Invalid Spell. Try again.") return end + local current_spell_table = spell_tables[current_element]["ga"] + windower.send_command("@input /ma "..current_spell_table[arg].." <"..target_mode..">") + end + + if command == "boomra" then + if arg == nil then arg = 1 end + arg = tonumber(arg) + if arg > #spell_tables[current_element]["ra"] then windower.send_command("@input /echo Invalid Spell. Try again.") return end + local current_spell_table = spell_tables[current_element]["ra"] + windower.send_command("@input /ma "..current_spell_table[arg].." <"..target_mode..">") + end + + if command == "target" then + if arg then + arg = string.lower(arg) + target_mode = arg + windower.send_command("@input /echo Target mode is now: "..target_mode) + else targets_index = targets_index + 1 + if targets_index > 3 then targets_index = 1 end + target_mode = targets[targets_index] + windower.send_command("@input /echo Target Mode is now: "..target_mode) + end + end + + if command == "element" then + arg = string.lower(arg) + if elements:contains(arg) then + current_element = arg + windower.send_command("@input /echo Element Mode is now: "..string.ucfirst(current_element)) + elseif other_modes:contains(arg) then + current_element = arg + windower.send_command("@input /echo Element Mode is now: "..string.ucfirst(current_element)) + else windower.send_command("@input /echo Invalid element") + end + end + + if command == "cycle" then + arg = string.lower(arg) + if arg == nil then + find_index() + elements_index = elements_index + 1 + if elements_index > 8 then elements_index = 1 end + current_element = tostring(elements[elements_index]) + windower.send_command("@input /echo Element Mode is now: "..string.ucfirst(current_element)) + elseif arg == "back" then + find_index() + elements_index = elements_index - 1 + if elements_index < 1 then elements_index = 8 end + current_element = elements[elements_index] + windower.send_command("@input /echo Element Mode is now: "..string.ucfirst(current_element)) + elseif arg == "dark" then + find_index() + elements_index = elements_index + 1 + if elements_index < 5 then elements_index = 5 end + if elements_index > 8 then elements_index = 5 end + current_element = elements[elements_index] + windower.send_command("@input /echo Element Mode is now: "..string.ucfirst(current_element)) + elseif arg == "light" then + find_index() + elements_index = elements_index + 1 + if elements_index > 4 then elements_index = 1 end + current_element = elements[elements_index] + windower.send_command("@input /echo Element Mode is now: "..string.ucfirst(current_element)) + elseif arg == "fusion" then + if current_element ~= "fire" and current_element ~= "light" then current_element = "fire" + elseif current_element == "fire" then current_element = "light" + elseif current_element == "light" then current_element = "fire" + end + elseif arg == "distortion" or arg == "dist" or arg == "d" then + if current_element ~= "ice" and current_element ~= "water" then current_element = "ice" + elseif current_element == "ice" then current_element = "water" + elseif current_element == "water" then current_element = "ice" + end + elseif arg == "gravitation" or arg == "grav" or arg == "g" then + if current_element ~= "earth" and current_element ~= "dark" then current_element = "earth" + elseif current_element == "earth" then current_element = "dark" + elseif current_element == "dark" then current_element = "earth" + end + elseif arg == "fragmentation" or arg == "frag" or arg == "f" then + if current_element ~= "thunder" and current_element ~= "wind" then current_element = "thunder" + elseif current_element == "thunder" then current_element = "wind" + elseif current_element == "wind" then current_element = "thunder" + end + end + end + + if command == "showcurrent" then + windower.send_command("@input /echo ----- Element Mode: "..string.ucfirst(current_element).." --- Target Mode: < "..target_mode.." > -----") + end +end) \ No newline at end of file diff --git a/addons/EasyNuke/readme.md b/addons/EasyNuke/readme.md new file mode 100644 index 0000000000..eb6e4ba1b8 --- /dev/null +++ b/addons/EasyNuke/readme.md @@ -0,0 +1,68 @@ +EasyNuke provides universal commands for casting single target and area of effect BLM and GEO nukes, and WHM cures. + +Commands: + +element # +* Changes current element mode to #. +** EX: //ez element ice <<<< Sets mode to ice. +** Macro usage: /con ez element # +** Valid arguments: Fire, Wind, Thunder, Light, Ice, Water, Earth, Dark, Drain, Aspir, Absorb, Cure +*** Drain and Aspir Mode: Aspir, Aspir II, Aspir III, Drain, Drain II, Drain III +*** Absorb Mode: Absorb-Acc, Absorb-TP, Absorb-Attri, Absorb-STR, Absorb-DEX, Absorb-VIT, Absorb-AGI, Absorb-INT, Absorb-MND, Absorb-CHR +*** EX: //ez element absorb >>> //ez boom 4 <<<< Casts Absorb-STR + +cycle +* Cycles through element modes in the following left-to-right order: Fire, Wind, Thunder, Light, Ice, Water, Earth, Dark +** EX: //ez cycle <<<< If you were in Light mode, then you will change to Ice mode. +** Macro usage: /con ez cycle + +cycle back +* Same as "cycle", but goes in right-to-left order. +** EX: //ez cycle back <<<< If you were in Light mode, then you will change to Thunder mode. +** Macro usage: /con ez cycle back + +cycle dark +* Cycles through element modes in the following order: Ice, Water, Earth, Dark +** EX: //ez cycle dark <<<< If you were in Light mode, then you will change to Ice mode. +** Macro usage: /con ez cycle dark + +cycle light +* Cycles through element modes in the following order: Fire, Wind, Thunder, Light +** EX: //ez cycle light <<<< If you were in Light mode, then you will change to Ice mode. +** Macro usage: /con ez cycle light + +cycle # +* Cycles between the two elements of a T2 skillchain. +** Fusion: Fire, Light +** Fragmentation, Frag, F: Thunder, Wind +** Distortion, Dist, D: Ice, Water +** Gravitation, Grav, G: Earth, Dark +*** EX: //ez cycle dist <<<< If you were in Ice mode, will change you to Water mode. If you were in any other mode, will change you to Ice mode. +*** Macro usage: /con ez cycle fragmentation + +target # +* Changes targeting mode to #. This sets what's between the < > brackets used for targeting in macros. +** EX: //ez target bt <<<< Spells will be cast using . +*** There are no failsafes for this. Any given argument will be accepted, even if it does not function as a targeting argument. +*** If no argument is given, then will cycle through target modes in the following order: t, bt, stnpc +** Macro usage: /con ez target # OR /con ez target + +showcurrent +* Echoes the current elemental and targeting modes in the chat log. +** EX: //ez showcurrent +** Macro usage: /con ez showcurrent + +boom # +* Casts a single target tier# nuke of the current element, and using the current targeting mode. +** EX: //ez boom 4 <<<< If in "fire" mode, and mode is "t", will cast Fire IV on your current target. +** Macro usage: /con ez boom # + +boomga # +* Casts an area of effect nuke of tier#. BLM: -ga, -ga II, -ga III, -ja. (Also works for Curaga's while in Cure mode.) +** EX: //ez boomga 4 <<<< If in "ice" mode, and mode is "t", will cast Blizzaja on your current target. +** Macro usage: /con ez boomga # + +boomra # +* Casts an area of effect nuke of tier#. GEO's -ra AOE nukes and WHM's Cura line +** EX: //ez boomga 4 <<<< If in "ice" mode, and mode is "t", will cast Blizzaja on your current target. +** Macro usage: /con ez boomga # \ No newline at end of file From 70f3acf43990872341edbe9e7d97f7be247662f2 Mon Sep 17 00:00:00 2001 From: Byrth Date: Mon, 25 Jun 2018 22:27:12 -0400 Subject: [PATCH 0167/1002] Sorc Petasos +1 was messed up --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 3135d79a1d..13a4d3e6f3 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -28,7 +28,7 @@ slips.items = { [slips.storages[13]] = L{10650, 10670, 10690, 10710, 10730, 10651, 10671, 10691, 10711, 10731, 10652, 10672, 10692, 10712, 10732, 10653, 10673, 10693, 10713, 10733, 10654, 10674, 10694, 10714, 10734, 10655, 10675, 10695, 10715, 10735, 10656, 10676, 10696, 10716, 10736, 10657, 10677, 10697, 10717, 10737, 10658, 10678, 10698, 10718, 10738, 10659, 10679, 10699, 10719, 10739, 10660, 10680, 10700, 10720, 10740, 10661, 10681, 10701, 10721, 10741, 10662, 10682, 10702, 10722, 10742, 10663, 10683, 10703, 10723, 10743, 10664, 10684, 10704, 10724, 10744, 10665, 10685, 10705, 10725, 10745, 10666, 10686, 10706, 10726, 10746, 10667, 10687, 10707, 10727, 10747, 10668, 10688, 10708, 10728, 10748, 10669, 10689, 10709, 10729, 10749}, -- 100 [slips.storages[14]] = L{10901, 10474, 10523, 10554, 10620, 10906, 10479, 10528, 10559, 10625, 10911, 10484, 10533, 10564, 10630, 19799, 18916, 10442, 10280, 16084, 27788, 27928, 28071, 28208, 27649, 27789, 27929, 28072, 28209, 27650, 27790, 27930, 28073, 28210, 27651, 27791, 27931, 28074, 28211, 27652, 27792, 27932, 28075, 28212, 27653, 27793, 27933, 28076, 28213, 27654, 27794, 27934, 28077, 28214, 27655, 27795, 27935, 28078, 28215, 27656, 27796, 27936, 28079, 28216, 27657, 27797, 27937, 28080, 28217, 27658, 27798, 27938, 28081, 28218, 27659, 27799, 27939, 28082, 28219, 27660, 27800, 27940, 28083, 28220, 27661, 27801, 27941, 28084, 28221, 27662, 27802, 27942, 28085, 28222}, -- 94 [slips.storages[15]] = L{27663, 27807, 27943, 28090, 28223, 27664, 27808, 27944, 28091, 28224, 27665, 27809, 27945, 28092, 28225, 27666, 27810, 27946, 28093, 28226, 27667, 27811, 27947, 28094, 28227, 27668, 27812, 27948, 28095, 28228, 27669, 27813, 27949, 28096, 28229, 27670, 27814, 27950, 28097, 28230, 27671, 27815, 27951, 28098, 28231, 27672, 27816, 27952, 28099, 28232, 27673, 27817, 27953, 28100, 28233, 27674, 27818, 27954, 28101, 28234, 27675, 27819, 27955, 28102, 28235, 27676, 27820, 27956, 28103, 28236, 27677, 27821, 27957, 28104, 28237, 27678, 27822, 27958, 28105, 28238, 27679, 27823, 27959, 28106, 28239, 27680, 27824, 27960, 28107, 28240, 27681, 27825, 27961, 28108, 28241, 27682, 27826, 27962, 28109, 28242, 27683, 27827, 27963, 28110, 28243}, -- 105 - [slips.storages[16]] = L{27684, 27828, 27964, 28111, 28244, 27685, 27829, 27965, 28112, 28245, 27686, 27830, 27966, 28113, 28246, 28246, 27831, 27967, 28114, 28247, 27688, 27832, 27968, 28115, 28248, 27689, 27833, 27969, 28116, 28249, 27690, 27834, 27970, 28117, 28250, 27691, 27835, 27971, 28118, 28251, 27692, 27836, 27972, 28119, 28252, 27693, 27837, 27973, 28120, 28253, 27694, 27838, 27974, 28121, 28254, 27695, 27839, 27975, 28122, 28255, 27696, 27840, 27976, 28123, 28256, 27697, 27841, 27977, 28124, 28257, 27698, 27842, 27978, 28125, 28258, 27699, 27843, 27979, 28126, 28259, 27700, 27844, 27980, 28127, 28260, 27701, 27845, 27981, 28128, 28261, 27702, 27846, 27982, 28129, 28262, 27703, 27847, 27983, 28130, 28263, 27704, 27848, 27984, 28131, 28264, 27705, 27849, 27985, 28132, 28265, 27706, 27850, 27986, 28133, 28266}, -- 115 + [slips.storages[16]] = L{27684, 27828, 27964, 28111, 28244, 27685, 27829, 27965, 28112, 28245, 27686, 27830, 27966, 28113, 28246, 27687, 27831, 27967, 28114, 28247, 27688, 27832, 27968, 28115, 28248, 27689, 27833, 27969, 28116, 28249, 27690, 27834, 27970, 28117, 28250, 27691, 27835, 27971, 28118, 28251, 27692, 27836, 27972, 28119, 28252, 27693, 27837, 27973, 28120, 28253, 27694, 27838, 27974, 28121, 28254, 27695, 27839, 27975, 28122, 28255, 27696, 27840, 27976, 28123, 28256, 27697, 27841, 27977, 28124, 28257, 27698, 27842, 27978, 28125, 28258, 27699, 27843, 27979, 28126, 28259, 27700, 27844, 27980, 28127, 28260, 27701, 27845, 27981, 28128, 28261, 27702, 27846, 27982, 28129, 28262, 27703, 27847, 27983, 28130, 28263, 27704, 27848, 27984, 28131, 28264, 27705, 27849, 27985, 28132, 28265, 27706, 27850, 27986, 28133, 28266}, -- 115 [slips.storages[17]] = L{26624, 26800, 26976, 27152, 27328, 26626, 26802, 26978, 27154, 27330, 26628, 26804, 26980, 27156, 27332, 26630, 26806, 26982, 27158, 27334, 26632, 26808, 26984, 27160, 27336, 26634, 26810, 26986, 27162, 27338, 26636, 26812, 26988, 27164, 27340, 26638, 26814, 26990, 27166, 27342, 26640, 26816, 26992, 27168, 27344, 26642, 26818, 26994, 27170, 27346, 26644, 26820, 26996, 27172, 27348, 26646, 26822, 26998, 27174, 27350, 26648, 26824, 27000, 27176, 27352, 26650, 26826, 27002, 27178, 27354, 26652, 26828, 27004, 27180, 27356, 26654, 26830, 27006, 27182, 27358, 26656, 26832, 27008, 27184, 27360, 26658, 26834, 27010, 27186, 27362, 26660, 26836, 27012, 27188, 27364, 26662, 26838, 27014, 27190, 27366, 26664, 26840, 27016, 27192, 27368, 26666, 26842, 27018, 27194, 27370}, -- 110 [slips.storages[18]] = L{26625, 26801, 26977, 27153, 27329, 26627, 26803, 26979, 27155, 27331, 26629, 26805, 26981, 27157, 27333, 26631, 26807, 26983, 27159, 27335, 26633, 26809, 26985, 27161, 27337, 26635, 26811, 26987, 27163, 27339, 26637, 26813, 26989, 27165, 27341, 26639, 26815, 26991, 27167, 27343, 26641, 26817, 26993, 27169, 27345, 26643, 26819, 26995, 27171, 27347, 26645, 26821, 26997, 27173, 27349, 26647, 26823, 26999, 27175, 27351, 26649, 26825, 27001, 27177, 27353, 26651, 26827, 27003, 27179, 27355, 26653, 26829, 27005, 27181, 27357, 26655, 26831, 27007, 27183, 27359, 26657, 26833, 27009, 27185, 27361, 26659, 26835, 27011, 27187, 27363, 26661, 26837, 27013, 27189, 27365, 26663, 26839, 27015, 27191, 27367, 26665, 26841, 27017, 27193, 27369, 26667, 26843, 27019, 27195, 27371}, -- 110 [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757}, -- 191 From 8e39e479ac8d5671ad25dd4173dbe72cb68856e4 Mon Sep 17 00:00:00 2001 From: deadman80 Date: Mon, 25 Jun 2018 23:40:50 -0400 Subject: [PATCH 0168/1002] Requested Corrections made. Requested corrections made, some code improvements. Corrected typo in readme.md --- addons/EasyNuke/EasyNuke.lua | 409 +++++++++++++++++------------------ addons/EasyNuke/readme.md | 136 ++++++------ 2 files changed, 271 insertions(+), 274 deletions(-) diff --git a/addons/EasyNuke/EasyNuke.lua b/addons/EasyNuke/EasyNuke.lua index 53bf7237b7..a338e9cedb 100644 --- a/addons/EasyNuke/EasyNuke.lua +++ b/addons/EasyNuke/EasyNuke.lua @@ -1,207 +1,204 @@ ---[[ -Copyright © 2018, FaceDesk Linkshell -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 findAll 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 FaceDesk Linkshell, or it's members, 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.name = 'EasyNuke' -_addon.author = 'FaceDesk Linkshell' -_addon.version = '1.0.2' -_addon.command = "ez" - -require('chat') -require('lists') -require('logger') -require('sets') -require('tables') -require('strings') -require('pack') - -file = require('files') -config = require('config') -texts = require('texts') -res = require('resources') - -local defaults = T{} -defaults.current_element = "fire" -defaults.target_mode = "t" -settings = config.load(defaults) - -current_element = "fire" -target_mode = "t" - -elements = T{"fire","wind","thunder","light","ice","water","earth","dark"} -elements_dark = T{"ice","water","earth","dark"} -elements_light = T{"fire","wind","thunder","light"} -elements_index = 1 -other_modes = T{"fire","wind","thunder","light","ice","water","earth","dark","drain","aspir","absorb","cure"} - -targets = T{"t","bt","stnpc"} -targets_index = 1 - -spell_tables = {} -spell_tables["fire"] = T{"Fire","Fire II","Fire III","Fire IV","Fire V","Fire VI",} -spell_tables["fire"]["ga"] = T{"Firaga","Firaga II","Firaga III","Firaja",} -spell_tables["fire"]["ra"] = T{"Fira","Fira II","Fira III"} -spell_tables["earth"] = T{"Stone","Stone II","Stone III","Stone IV","Stone V","Stone VI",} -spell_tables["earth"]["ga"] = T{"Stonega","Stonega II","Stonega III","Stoneja",} -spell_tables["earth"]["ra"] = T{"Stonera","Stonera II","Stonera III"} -spell_tables["wind"] = T{"Aero","Aero II","Aero III","Aero IV","Aero V","Aero VI",} -spell_tables["wind"]["ga"] = T{"Aeroga","Aeroga II","Aeroga III","Aeroja",} -spell_tables["wind"]["ra"] = T{"Aerora","Aerora II","Aerora III"} -spell_tables["water"] = T{"Water","Water II","Water III","Water IV","Water V","Water VI",} -spell_tables["water"]["ga"] = T{"Waterga","Waterga II","Waterga III","Waterja",} -spell_tables["water"]["ra"] = T{"Watera","Watera II","Watera III"} -spell_tables["ice"] = T{"Blizzard","Blizzard II","Blizzard III","Blizzard IV","Blizzard V","Blizzard VI",} -spell_tables["ice"]["ga"] = T{"Blizzaga","Blizzaga II","Blizzaga III","Blizzaja",} -spell_tables["ice"]["ra"] = T{"Blizzara","Blizzara II","Blizzara III"} -spell_tables["thunder"] = T{"Thunder","Thunder II","Thunder III","Thunder IV","Thunder V","Thunder VI",} -spell_tables["thunder"]["ga"] = T{"Thundaga","Thundaga II","Thundaga III","Thundaja",} -spell_tables["thunder"]["ra"] = T{"Thundara","Thundara II","Thundara III"} -spell_tables["light"] = T{"Banish","Banish II","Holy","Banish III",} -spell_tables["light"]["ga"] = T{"Banishga","Banishga II"} -spell_tables["dark"] = T{"Impact"} -spell_tables["dark"]["ga"] = T{"Comet"} -spell_tables["cure"] = T{"Cure","Cure II","Cure III","Cure IV","Cure V","Cure VI"} -spell_tables["cure"]["ga"] = T{"Curaga","Curaga II","Curaga III","Curaga IV","Curaga V",} -spell_tables["cure"]["ra"] = T{"Cura","Cura II","Cura III"} -spell_tables["drain"] = T{"Aspir","Aspir II","Aspir III","Drain","Drain II","Drain III"} -spell_tables["absorb"] = T{"Absorb-Acc","Absorb-TP","Absorb-Attri","Absorb-STR","Absorb-DEX","Absorb-VIT","Absorb-AGI","Absorb-INT","Absorb-MND","Absorb-CHR"} - -function find_index () - if current_element == "fire" then elements_index = 1 end - if current_element == "wind" then elements_index = 2 end - if current_element == "thunder" then elements_index = 3 end - if current_element == "light" then elements_index = 4 end - if current_element == "ice" then elements_index = 5 end - if current_element == "water" then elements_index = 6 end - if current_element == "earth" then elements_index = 7 end - if current_element == "dark" then elements_index = 8 end -end - -windower.register_event('addon command', function (command, arg) - - if command == 'boom' then - if arg == nil then arg = 1 end - arg = tonumber(arg) - if arg > #spell_tables[current_element] then windower.send_command("@input /echo Invalid Spell. Try again.") return end - local current_spell_table = spell_tables[current_element] - windower.send_command("@input /ma "..current_spell_table[arg].." <"..target_mode..">") - end - - if command == "boomga" then - if arg == nil then arg = 1 end - arg = tonumber(arg) - if arg > #spell_tables[current_element]["ga"] then windower.send_command("@input /echo Invalid Spell. Try again.") return end - local current_spell_table = spell_tables[current_element]["ga"] - windower.send_command("@input /ma "..current_spell_table[arg].." <"..target_mode..">") - end - - if command == "boomra" then - if arg == nil then arg = 1 end - arg = tonumber(arg) - if arg > #spell_tables[current_element]["ra"] then windower.send_command("@input /echo Invalid Spell. Try again.") return end - local current_spell_table = spell_tables[current_element]["ra"] - windower.send_command("@input /ma "..current_spell_table[arg].." <"..target_mode..">") - end - - if command == "target" then - if arg then - arg = string.lower(arg) - target_mode = arg - windower.send_command("@input /echo Target mode is now: "..target_mode) - else targets_index = targets_index + 1 - if targets_index > 3 then targets_index = 1 end - target_mode = targets[targets_index] - windower.send_command("@input /echo Target Mode is now: "..target_mode) - end - end - - if command == "element" then - arg = string.lower(arg) - if elements:contains(arg) then - current_element = arg - windower.send_command("@input /echo Element Mode is now: "..string.ucfirst(current_element)) - elseif other_modes:contains(arg) then - current_element = arg - windower.send_command("@input /echo Element Mode is now: "..string.ucfirst(current_element)) - else windower.send_command("@input /echo Invalid element") - end - end - - if command == "cycle" then - arg = string.lower(arg) - if arg == nil then - find_index() - elements_index = elements_index + 1 - if elements_index > 8 then elements_index = 1 end - current_element = tostring(elements[elements_index]) - windower.send_command("@input /echo Element Mode is now: "..string.ucfirst(current_element)) - elseif arg == "back" then - find_index() - elements_index = elements_index - 1 - if elements_index < 1 then elements_index = 8 end - current_element = elements[elements_index] - windower.send_command("@input /echo Element Mode is now: "..string.ucfirst(current_element)) - elseif arg == "dark" then - find_index() - elements_index = elements_index + 1 - if elements_index < 5 then elements_index = 5 end - if elements_index > 8 then elements_index = 5 end - current_element = elements[elements_index] - windower.send_command("@input /echo Element Mode is now: "..string.ucfirst(current_element)) - elseif arg == "light" then - find_index() - elements_index = elements_index + 1 - if elements_index > 4 then elements_index = 1 end - current_element = elements[elements_index] - windower.send_command("@input /echo Element Mode is now: "..string.ucfirst(current_element)) - elseif arg == "fusion" then - if current_element ~= "fire" and current_element ~= "light" then current_element = "fire" - elseif current_element == "fire" then current_element = "light" - elseif current_element == "light" then current_element = "fire" - end - elseif arg == "distortion" or arg == "dist" or arg == "d" then - if current_element ~= "ice" and current_element ~= "water" then current_element = "ice" - elseif current_element == "ice" then current_element = "water" - elseif current_element == "water" then current_element = "ice" - end - elseif arg == "gravitation" or arg == "grav" or arg == "g" then - if current_element ~= "earth" and current_element ~= "dark" then current_element = "earth" - elseif current_element == "earth" then current_element = "dark" - elseif current_element == "dark" then current_element = "earth" - end - elseif arg == "fragmentation" or arg == "frag" or arg == "f" then - if current_element ~= "thunder" and current_element ~= "wind" then current_element = "thunder" - elseif current_element == "thunder" then current_element = "wind" - elseif current_element == "wind" then current_element = "thunder" - end - end - end - - if command == "showcurrent" then - windower.send_command("@input /echo ----- Element Mode: "..string.ucfirst(current_element).." --- Target Mode: < "..target_mode.." > -----") - end +--[[ +Copyright © 2018, FaceDesk Linkshell +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 EasyNuke 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 FaceDesk Linkshell, or it's members, 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.name = 'EasyNuke' +_addon.author = 'FaceDesk Linkshell' +_addon.version = '1.0.3' +_addon.command = "ez" + +require('chat') +require('lists') +require('logger') +require('sets') +require('tables') +require('strings') +require('pack') + +file = require('files') +config = require('config') +texts = require('texts') +res = require('resources') + +local defaults = T{} +defaults.current_element = "fire" +defaults.target_mode = "t" +settings = config.load(defaults) + +current_element = "fire" +target_mode = "t" + +elements = T{"fire","wind","thunder","light","ice","water","earth","dark"} +elements_dark = T{"ice","water","earth","dark"} +elements_light = T{"fire","wind","thunder","light"} +elements_index = 1 +other_modes = S{"drain","aspir","absorb","cure"} + +targets = T{"t","bt","stnpc"} +targets_index = 1 + +spell_tables = {} +spell_tables["fire"] = T{"Fire","Fire II","Fire III","Fire IV","Fire V","Fire VI",} +spell_tables["fire"]["ga"] = T{"Firaga","Firaga II","Firaga III","Firaja",} +spell_tables["fire"]["ra"] = T{"Fira","Fira II","Fira III"} +spell_tables["earth"] = T{"Stone","Stone II","Stone III","Stone IV","Stone V","Stone VI",} +spell_tables["earth"]["ga"] = T{"Stonega","Stonega II","Stonega III","Stoneja",} +spell_tables["earth"]["ra"] = T{"Stonera","Stonera II","Stonera III"} +spell_tables["wind"] = T{"Aero","Aero II","Aero III","Aero IV","Aero V","Aero VI",} +spell_tables["wind"]["ga"] = T{"Aeroga","Aeroga II","Aeroga III","Aeroja",} +spell_tables["wind"]["ra"] = T{"Aerora","Aerora II","Aerora III"} +spell_tables["water"] = T{"Water","Water II","Water III","Water IV","Water V","Water VI",} +spell_tables["water"]["ga"] = T{"Waterga","Waterga II","Waterga III","Waterja",} +spell_tables["water"]["ra"] = T{"Watera","Watera II","Watera III"} +spell_tables["ice"] = T{"Blizzard","Blizzard II","Blizzard III","Blizzard IV","Blizzard V","Blizzard VI",} +spell_tables["ice"]["ga"] = T{"Blizzaga","Blizzaga II","Blizzaga III","Blizzaja",} +spell_tables["ice"]["ra"] = T{"Blizzara","Blizzara II","Blizzara III"} +spell_tables["thunder"] = T{"Thunder","Thunder II","Thunder III","Thunder IV","Thunder V","Thunder VI",} +spell_tables["thunder"]["ga"] = T{"Thundaga","Thundaga II","Thundaga III","Thundaja",} +spell_tables["thunder"]["ra"] = T{"Thundara","Thundara II","Thundara III"} +spell_tables["light"] = T{"Banish","Banish II","Holy","Banish III",} +spell_tables["light"]["ga"] = T{"Banishga","Banishga II"} +spell_tables["dark"] = T{"Impact"} +spell_tables["dark"]["ga"] = T{"Comet"} +spell_tables["cure"] = T{"Cure","Cure II","Cure III","Cure IV","Cure V","Cure VI"} +spell_tables["cure"]["ga"] = T{"Curaga","Curaga II","Curaga III","Curaga IV","Curaga V",} +spell_tables["cure"]["ra"] = T{"Cura","Cura II","Cura III"} +spell_tables["drain"] = T{"Aspir","Aspir II","Aspir III","Drain","Drain II","Drain III"} +spell_tables["drain"]["ga"] = spell_tables["drain"] +spell_tables["drain"]["ra"] = spell_tables["drain"] +spell_tables["aspir"] = spell_tables["drain"] +spell_tables["aspir"]["ga"] = spell_tables["drain"] +spell_tables["aspir"]["ra"] = spell_tables["drain"] +spell_tables["absorb"] = T{"Absorb-Acc","Absorb-TP","Absorb-Attri","Absorb-STR","Absorb-DEX","Absorb-VIT","Absorb-AGI","Absorb-INT","Absorb-MND","Absorb-CHR"} +spell_tables["absorb"]["ga"] = spell_tables["absorb"] +spell_tables["absorb"]["ra"] = spell_tables["absorb"] + +windower.register_event('addon command', function (command, arg) + + if command == "boom" or command == "nuke" then + local current_spell_table = spell_tables[current_element] + if arg == nil then arg = 1 end + arg = tonumber(arg) + if arg > #spell_tables[current_element] then + windower.add_to_chat(206,"Invalid Spell. Try again.") return + end + windower.chat.input("/ma "..current_spell_table[arg].." <"..target_mode..">") + + elseif command == "boomga" or command == "bga" then + local current_spell_table = spell_tables[current_element]["ga"] + if arg == nil then arg = 1 end + arg = tonumber(arg) + if arg > #spell_tables[current_element]["ga"] or spell_tables[current_element]["ga"] == nil then + windower.add_to_chat(206,"Invalid Spell. Try again.") return + end + windower.chat.input("/ma "..current_spell_table[arg].." <"..target_mode..">") + + elseif command == "boomra" or command == "bra" then + local current_spell_table = spell_tables[current_element]["ra"] + if arg == nil then arg = 1 end + arg = tonumber(arg) + if arg > #spell_tables[current_element]["ra"] or spell_tables[current_element]["ra"] == nil then + windower.add_to_chat(206,"Invalid Spell. Try again.") return + end + windower.chat.input("/ma "..current_spell_table[arg].." <"..target_mode..">") + + elseif command == "target" then + if arg then + arg = string.lower(arg) + target_mode = arg + else + targets_index = targets_index % 3 + 1 + target_mode = targets[targets_index] + end + windower.add_to_chat(206,"/echo Target Mode is now: "..target_mode) + + elseif command == "element" or command == "mode" then + arg = string.lower(arg) + if elements:contains(arg) or other_modes:contains(arg) then + current_element = arg + windower.add_to_chat(206,"/echo Element Mode is now: "..string.ucfirst(current_element)) + else + windower.add_to_chat(206,"/echo Invalid element") + end + + elseif command == "cycle" then + if arg then + arg = string.lower(arg) + end + if arg == nil then + elements_index = elements_index % 8 + 1 + current_element = elements[elements_index] + elseif arg == "back" then + elements_index = elements_index - 1 + if elements_index < 1 then + elements_index = 8 + end + current_element = elements[elements_index] + elseif arg == "dark" then + elements_index = elements_index % 4 + 1 + current_element = elements_dark[elements_index] + elseif arg == "light" then + elements_index = elements_index % 4 + 1 + current_element = elements_light[elements_index] + elseif arg == "fusion" then + if current_element ~= "fire" and current_element ~= "light" then + current_element = "fire" + elseif current_element == "fire" then + current_element = "light" + elseif current_element == "light" then + current_element = "fire" + end + elseif arg == "distortion" or arg == "dist" then + if current_element ~= "ice" and current_element ~= "water" then + current_element = "ice" + elseif current_element == "ice" then + current_element = "water" + elseif current_element == "water" then + current_element = "ice" + end + elseif arg == "gravitation" or arg == "grav" then + if current_element ~= "earth" and current_element ~= "dark" then + current_element = "earth" + elseif current_element == "earth" then + current_element = "dark" + elseif current_element == "dark" then + current_element = "earth" + end + elseif arg == "fragmentation" or arg == "frag" then + if current_element ~= "thunder" and current_element ~= "wind" then + current_element = "thunder" + elseif current_element == "thunder" then + current_element = "wind" + elseif current_element == "wind" then + current_element = "thunder" + end + end + windower.add_to_chat(206, "Element Mode is now: "..string.ucfirst(current_element)) + elseif command == "show" or command == "current" or command == "showcurrent" then + windower.add_to_chat(206, "----- Element Mode: "..string.ucfirst(current_element).." --- Target Mode: < "..target_mode.." > -----") + end end) \ No newline at end of file diff --git a/addons/EasyNuke/readme.md b/addons/EasyNuke/readme.md index eb6e4ba1b8..b82bd15aec 100644 --- a/addons/EasyNuke/readme.md +++ b/addons/EasyNuke/readme.md @@ -1,68 +1,68 @@ -EasyNuke provides universal commands for casting single target and area of effect BLM and GEO nukes, and WHM cures. - -Commands: - -element # -* Changes current element mode to #. -** EX: //ez element ice <<<< Sets mode to ice. -** Macro usage: /con ez element # -** Valid arguments: Fire, Wind, Thunder, Light, Ice, Water, Earth, Dark, Drain, Aspir, Absorb, Cure -*** Drain and Aspir Mode: Aspir, Aspir II, Aspir III, Drain, Drain II, Drain III -*** Absorb Mode: Absorb-Acc, Absorb-TP, Absorb-Attri, Absorb-STR, Absorb-DEX, Absorb-VIT, Absorb-AGI, Absorb-INT, Absorb-MND, Absorb-CHR -*** EX: //ez element absorb >>> //ez boom 4 <<<< Casts Absorb-STR - -cycle -* Cycles through element modes in the following left-to-right order: Fire, Wind, Thunder, Light, Ice, Water, Earth, Dark -** EX: //ez cycle <<<< If you were in Light mode, then you will change to Ice mode. -** Macro usage: /con ez cycle - -cycle back -* Same as "cycle", but goes in right-to-left order. -** EX: //ez cycle back <<<< If you were in Light mode, then you will change to Thunder mode. -** Macro usage: /con ez cycle back - -cycle dark -* Cycles through element modes in the following order: Ice, Water, Earth, Dark -** EX: //ez cycle dark <<<< If you were in Light mode, then you will change to Ice mode. -** Macro usage: /con ez cycle dark - -cycle light -* Cycles through element modes in the following order: Fire, Wind, Thunder, Light -** EX: //ez cycle light <<<< If you were in Light mode, then you will change to Ice mode. -** Macro usage: /con ez cycle light - -cycle # -* Cycles between the two elements of a T2 skillchain. -** Fusion: Fire, Light -** Fragmentation, Frag, F: Thunder, Wind -** Distortion, Dist, D: Ice, Water -** Gravitation, Grav, G: Earth, Dark -*** EX: //ez cycle dist <<<< If you were in Ice mode, will change you to Water mode. If you were in any other mode, will change you to Ice mode. -*** Macro usage: /con ez cycle fragmentation - -target # -* Changes targeting mode to #. This sets what's between the < > brackets used for targeting in macros. -** EX: //ez target bt <<<< Spells will be cast using . -*** There are no failsafes for this. Any given argument will be accepted, even if it does not function as a targeting argument. -*** If no argument is given, then will cycle through target modes in the following order: t, bt, stnpc -** Macro usage: /con ez target # OR /con ez target - -showcurrent -* Echoes the current elemental and targeting modes in the chat log. -** EX: //ez showcurrent -** Macro usage: /con ez showcurrent - -boom # -* Casts a single target tier# nuke of the current element, and using the current targeting mode. -** EX: //ez boom 4 <<<< If in "fire" mode, and mode is "t", will cast Fire IV on your current target. -** Macro usage: /con ez boom # - -boomga # -* Casts an area of effect nuke of tier#. BLM: -ga, -ga II, -ga III, -ja. (Also works for Curaga's while in Cure mode.) -** EX: //ez boomga 4 <<<< If in "ice" mode, and mode is "t", will cast Blizzaja on your current target. -** Macro usage: /con ez boomga # - -boomra # -* Casts an area of effect nuke of tier#. GEO's -ra AOE nukes and WHM's Cura line -** EX: //ez boomga 4 <<<< If in "ice" mode, and mode is "t", will cast Blizzaja on your current target. -** Macro usage: /con ez boomga # \ No newline at end of file +EasyNuke provides universal commands for casting single target and area of effect BLM and GEO nukes, and WHM cures. + +Commands: + +element # +* Changes current element mode to #. +** EX: //ez element ice <<<< Sets mode to ice. +** Macro usage: /con ez element # +** Valid arguments: Fire, Wind, Thunder, Light, Ice, Water, Earth, Dark, Drain, Aspir, Absorb, Cure +*** Drain and Aspir Mode: Aspir, Aspir II, Aspir III, Drain, Drain II, Drain III +*** Absorb Mode: Absorb-Acc, Absorb-TP, Absorb-Attri, Absorb-STR, Absorb-DEX, Absorb-VIT, Absorb-AGI, Absorb-INT, Absorb-MND, Absorb-CHR +*** EX: //ez element absorb >>> //ez boom 4 <<<< Casts Absorb-STR + +cycle +* Cycles through element modes in the following left-to-right order: Fire, Wind, Thunder, Light, Ice, Water, Earth, Dark +** EX: //ez cycle <<<< If you were in Light mode, then you will change to Ice mode. +** Macro usage: /con ez cycle + +cycle back +* Same as "cycle", but goes in right-to-left order. +** EX: //ez cycle back <<<< If you were in Light mode, then you will change to Thunder mode. +** Macro usage: /con ez cycle back + +cycle dark +* Cycles through element modes in the following order: Ice, Water, Earth, Dark +** EX: //ez cycle dark <<<< If you were in Light mode, then you will change to Ice mode. +** Macro usage: /con ez cycle dark + +cycle light +* Cycles through element modes in the following order: Fire, Wind, Thunder, Light +** EX: //ez cycle light <<<< If you were in Light mode, then you will change to Ice mode. +** Macro usage: /con ez cycle light + +cycle # +* Cycles between the two elements of a T2 skillchain. +** Fusion: Fire, Light +** Fragmentation, Frag: Thunder, Wind +** Distortion, Dist: Ice, Water +** Gravitation, Grav: Earth, Dark +*** EX: //ez cycle dist <<<< If you were in Ice mode, will change you to Water mode. If you were in any other mode, will change you to Ice mode. +*** Macro usage: /con ez cycle fragmentation + +target # +* Changes targeting mode to #. This sets what's between the < > brackets used for targeting in macros. +** EX: //ez target bt <<<< Spells will be cast using . +*** There are no failsafes for this. Any given argument will be accepted, even if it does not function as a targeting argument. +*** If no argument is given, then will cycle through target modes in the following order: t, bt, stnpc +** Macro usage: /con ez target OR /con ez target # + +show, current or showcurrent +* Echoes the current elemental and targeting modes in the chat log. +** EX: //ez showcurrent +** Macro usage: /con ez showcurrent + +boom # +* Casts a single target tier# nuke of the current element, and using the current targeting mode. +** EX: //ez boom 4 <<<< If in "fire" mode, and mode is "t", will cast Fire IV on your current target. +** Macro usage: /con ez boom # + +boomga # +* Casts an area of effect nuke of tier#. BLM: -ga, -ga II, -ga III, -ja. (Also works for Curaga's while in Cure mode.) +** EX: //ez boomga 4 <<<< If in "ice" mode, and mode is "t", will cast Blizzaja on your current target. +** Macro usage: /con ez boomga # + +boomra # +* Casts an area of effect nuke of tier#. GEO's -ra AOE nukes and WHM's Cura line +** EX: //ez boomra 3 <<<< If in "ice" mode, and mode is "t", will cast Blizzara III on your current target. +** Macro usage: /con ez boomra # \ No newline at end of file From e6604a102e79b7ea13d7e6ea4d985dcf03fa3fc6 Mon Sep 17 00:00:00 2001 From: deadman80 Date: Mon, 25 Jun 2018 23:47:24 -0400 Subject: [PATCH 0169/1002] Requested Corrections done The requested corrections have been done, plus some improvements to the code. Typos corrected in the readme.md --- addons/EasyNuke/EasyNuke.lua | 227 +++++++++++++++++------------------ addons/EasyNuke/readme.md | 14 +-- addons/addons.xml | 7 ++ 3 files changed, 126 insertions(+), 122 deletions(-) diff --git a/addons/EasyNuke/EasyNuke.lua b/addons/EasyNuke/EasyNuke.lua index 53bf7237b7..ec12a6decf 100644 --- a/addons/EasyNuke/EasyNuke.lua +++ b/addons/EasyNuke/EasyNuke.lua @@ -10,7 +10,7 @@ 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 findAll nor the +* Neither the name of EasyNuke nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'EasyNuke' _addon.author = 'FaceDesk Linkshell' -_addon.version = '1.0.2' +_addon.version = '1.0.3' _addon.command = "ez" require('chat') @@ -56,7 +56,7 @@ elements = T{"fire","wind","thunder","light","ice","water","earth","dark"} elements_dark = T{"ice","water","earth","dark"} elements_light = T{"fire","wind","thunder","light"} elements_index = 1 -other_modes = T{"fire","wind","thunder","light","ice","water","earth","dark","drain","aspir","absorb","cure"} +other_modes = S{"drain","aspir","absorb","cure"} targets = T{"t","bt","stnpc"} targets_index = 1 @@ -88,120 +88,117 @@ spell_tables["cure"] = T{"Cure","Cure II","Cure III","Cure IV","Cure V","Cure VI spell_tables["cure"]["ga"] = T{"Curaga","Curaga II","Curaga III","Curaga IV","Curaga V",} spell_tables["cure"]["ra"] = T{"Cura","Cura II","Cura III"} spell_tables["drain"] = T{"Aspir","Aspir II","Aspir III","Drain","Drain II","Drain III"} +spell_tables["drain"]["ga"] = spell_tables["drain"] +spell_tables["drain"]["ra"] = spell_tables["drain"] +spell_tables["aspir"] = spell_tables["drain"] +spell_tables["aspir"]["ga"] = spell_tables["drain"] +spell_tables["aspir"]["ra"] = spell_tables["drain"] spell_tables["absorb"] = T{"Absorb-Acc","Absorb-TP","Absorb-Attri","Absorb-STR","Absorb-DEX","Absorb-VIT","Absorb-AGI","Absorb-INT","Absorb-MND","Absorb-CHR"} - -function find_index () - if current_element == "fire" then elements_index = 1 end - if current_element == "wind" then elements_index = 2 end - if current_element == "thunder" then elements_index = 3 end - if current_element == "light" then elements_index = 4 end - if current_element == "ice" then elements_index = 5 end - if current_element == "water" then elements_index = 6 end - if current_element == "earth" then elements_index = 7 end - if current_element == "dark" then elements_index = 8 end -end +spell_tables["absorb"]["ga"] = spell_tables["absorb"] +spell_tables["absorb"]["ra"] = spell_tables["absorb"] windower.register_event('addon command', function (command, arg) - if command == 'boom' then - if arg == nil then arg = 1 end - arg = tonumber(arg) - if arg > #spell_tables[current_element] then windower.send_command("@input /echo Invalid Spell. Try again.") return end - local current_spell_table = spell_tables[current_element] - windower.send_command("@input /ma "..current_spell_table[arg].." <"..target_mode..">") - end - - if command == "boomga" then - if arg == nil then arg = 1 end - arg = tonumber(arg) - if arg > #spell_tables[current_element]["ga"] then windower.send_command("@input /echo Invalid Spell. Try again.") return end - local current_spell_table = spell_tables[current_element]["ga"] - windower.send_command("@input /ma "..current_spell_table[arg].." <"..target_mode..">") - end - - if command == "boomra" then - if arg == nil then arg = 1 end - arg = tonumber(arg) - if arg > #spell_tables[current_element]["ra"] then windower.send_command("@input /echo Invalid Spell. Try again.") return end - local current_spell_table = spell_tables[current_element]["ra"] - windower.send_command("@input /ma "..current_spell_table[arg].." <"..target_mode..">") - end - - if command == "target" then - if arg then - arg = string.lower(arg) - target_mode = arg - windower.send_command("@input /echo Target mode is now: "..target_mode) - else targets_index = targets_index + 1 - if targets_index > 3 then targets_index = 1 end - target_mode = targets[targets_index] - windower.send_command("@input /echo Target Mode is now: "..target_mode) - end - end - - if command == "element" then - arg = string.lower(arg) - if elements:contains(arg) then - current_element = arg - windower.send_command("@input /echo Element Mode is now: "..string.ucfirst(current_element)) - elseif other_modes:contains(arg) then - current_element = arg - windower.send_command("@input /echo Element Mode is now: "..string.ucfirst(current_element)) - else windower.send_command("@input /echo Invalid element") - end - end - - if command == "cycle" then - arg = string.lower(arg) - if arg == nil then - find_index() - elements_index = elements_index + 1 - if elements_index > 8 then elements_index = 1 end - current_element = tostring(elements[elements_index]) - windower.send_command("@input /echo Element Mode is now: "..string.ucfirst(current_element)) - elseif arg == "back" then - find_index() - elements_index = elements_index - 1 - if elements_index < 1 then elements_index = 8 end - current_element = elements[elements_index] - windower.send_command("@input /echo Element Mode is now: "..string.ucfirst(current_element)) - elseif arg == "dark" then - find_index() - elements_index = elements_index + 1 - if elements_index < 5 then elements_index = 5 end - if elements_index > 8 then elements_index = 5 end - current_element = elements[elements_index] - windower.send_command("@input /echo Element Mode is now: "..string.ucfirst(current_element)) - elseif arg == "light" then - find_index() - elements_index = elements_index + 1 - if elements_index > 4 then elements_index = 1 end - current_element = elements[elements_index] - windower.send_command("@input /echo Element Mode is now: "..string.ucfirst(current_element)) - elseif arg == "fusion" then - if current_element ~= "fire" and current_element ~= "light" then current_element = "fire" - elseif current_element == "fire" then current_element = "light" - elseif current_element == "light" then current_element = "fire" - end - elseif arg == "distortion" or arg == "dist" or arg == "d" then - if current_element ~= "ice" and current_element ~= "water" then current_element = "ice" - elseif current_element == "ice" then current_element = "water" - elseif current_element == "water" then current_element = "ice" - end - elseif arg == "gravitation" or arg == "grav" or arg == "g" then - if current_element ~= "earth" and current_element ~= "dark" then current_element = "earth" - elseif current_element == "earth" then current_element = "dark" - elseif current_element == "dark" then current_element = "earth" - end - elseif arg == "fragmentation" or arg == "frag" or arg == "f" then - if current_element ~= "thunder" and current_element ~= "wind" then current_element = "thunder" - elseif current_element == "thunder" then current_element = "wind" - elseif current_element == "wind" then current_element = "thunder" - end - end - end - - if command == "showcurrent" then - windower.send_command("@input /echo ----- Element Mode: "..string.ucfirst(current_element).." --- Target Mode: < "..target_mode.." > -----") - end + if command == "boom" or command == "nuke" then + local current_spell_table = spell_tables[current_element] + if arg == nil then arg = 1 end + arg = tonumber(arg) + if arg > #spell_tables[current_element] then + windower.add_to_chat(206,"Invalid Spell. Try again.") return + end + windower.chat.input("/ma "..current_spell_table[arg].." <"..target_mode..">") + + elseif command == "boomga" or command == "bga" then + local current_spell_table = spell_tables[current_element]["ga"] + if arg == nil then arg = 1 end + arg = tonumber(arg) + if arg > #spell_tables[current_element]["ga"] or spell_tables[current_element]["ga"] == nil then + windower.add_to_chat(206,"Invalid Spell. Try again.") return + end + windower.chat.input("/ma "..current_spell_table[arg].." <"..target_mode..">") + + elseif command == "boomra" or command == "bra" then + local current_spell_table = spell_tables[current_element]["ra"] + if arg == nil then arg = 1 end + arg = tonumber(arg) + if arg > #spell_tables[current_element]["ra"] or spell_tables[current_element]["ra"] == nil then + windower.add_to_chat(206,"Invalid Spell. Try again.") return + end + windower.chat.input("/ma "..current_spell_table[arg].." <"..target_mode..">") + + elseif command == "target" then + if arg then + arg = string.lower(arg) + target_mode = arg + else + targets_index = targets_index % 3 + 1 + target_mode = targets[targets_index] + end + windower.add_to_chat(206,"/echo Target Mode is now: "..target_mode) + + elseif command == "element" or command == "mode" then + arg = string.lower(arg) + if elements:contains(arg) or other_modes:contains(arg) then + current_element = arg + windower.add_to_chat(206,"/echo Element Mode is now: "..string.ucfirst(current_element)) + else + windower.add_to_chat(206,"/echo Invalid element") + end + + elseif command == "cycle" then + if arg then + arg = string.lower(arg) + end + if arg == nil then + elements_index = elements_index % 8 + 1 + current_element = elements[elements_index] + elseif arg == "back" then + elements_index = elements_index - 1 + if elements_index < 1 then + elements_index = 8 + end + current_element = elements[elements_index] + elseif arg == "dark" then + elements_index = elements_index % 4 + 1 + current_element = elements_dark[elements_index] + elseif arg == "light" then + elements_index = elements_index % 4 + 1 + current_element = elements_light[elements_index] + elseif arg == "fusion" then + if current_element ~= "fire" and current_element ~= "light" then + current_element = "fire" + elseif current_element == "fire" then + current_element = "light" + elseif current_element == "light" then + current_element = "fire" + end + elseif arg == "distortion" or arg == "dist" then + if current_element ~= "ice" and current_element ~= "water" then + current_element = "ice" + elseif current_element == "ice" then + current_element = "water" + elseif current_element == "water" then + current_element = "ice" + end + elseif arg == "gravitation" or arg == "grav" then + if current_element ~= "earth" and current_element ~= "dark" then + current_element = "earth" + elseif current_element == "earth" then + current_element = "dark" + elseif current_element == "dark" then + current_element = "earth" + end + elseif arg == "fragmentation" or arg == "frag" then + if current_element ~= "thunder" and current_element ~= "wind" then + current_element = "thunder" + elseif current_element == "thunder" then + current_element = "wind" + elseif current_element == "wind" then + current_element = "thunder" + end + end + windower.add_to_chat(206, "Element Mode is now: "..string.ucfirst(current_element)) + elseif command == "show" or command == "current" or command == "showcurrent" then + windower.add_to_chat(206, "----- Element Mode: "..string.ucfirst(current_element).." --- Target Mode: < "..target_mode.." > -----") + end end) \ No newline at end of file diff --git a/addons/EasyNuke/readme.md b/addons/EasyNuke/readme.md index eb6e4ba1b8..43c24f65ea 100644 --- a/addons/EasyNuke/readme.md +++ b/addons/EasyNuke/readme.md @@ -34,9 +34,9 @@ cycle light cycle # * Cycles between the two elements of a T2 skillchain. ** Fusion: Fire, Light -** Fragmentation, Frag, F: Thunder, Wind -** Distortion, Dist, D: Ice, Water -** Gravitation, Grav, G: Earth, Dark +** Fragmentation, Frag: Thunder, Wind +** Distortion, Dist: Ice, Water +** Gravitation, Grav: Earth, Dark *** EX: //ez cycle dist <<<< If you were in Ice mode, will change you to Water mode. If you were in any other mode, will change you to Ice mode. *** Macro usage: /con ez cycle fragmentation @@ -45,9 +45,9 @@ target # ** EX: //ez target bt <<<< Spells will be cast using . *** There are no failsafes for this. Any given argument will be accepted, even if it does not function as a targeting argument. *** If no argument is given, then will cycle through target modes in the following order: t, bt, stnpc -** Macro usage: /con ez target # OR /con ez target +** Macro usage: /con ez target OR /con ez target # -showcurrent +show, current or showcurrent * Echoes the current elemental and targeting modes in the chat log. ** EX: //ez showcurrent ** Macro usage: /con ez showcurrent @@ -64,5 +64,5 @@ boomga # boomra # * Casts an area of effect nuke of tier#. GEO's -ra AOE nukes and WHM's Cura line -** EX: //ez boomga 4 <<<< If in "ice" mode, and mode is "t", will cast Blizzaja on your current target. -** Macro usage: /con ez boomga # \ No newline at end of file +** EX: //ez boomra 3 <<<< If in "ice" mode, and mode is "t", will cast Blizzara III on your current target. +** Macro usage: /con ez boomra # \ No newline at end of file diff --git a/addons/addons.xml b/addons/addons.xml index cacab5fa53..ffc75fa6cf 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -753,4 +753,11 @@ https://github.com/from20020516/Lua/issues https://twitter.com/from20020516 + + EasyNuke + FaceDesk + Unified commands to handle single target and AOE nukes and cures, plus Drain/Aspir and Absorbs. + https://github.com/deadman80/Lua/issues + https://www.ffxiah.com/user/Nyarlko + From 265c26287253e282cf0f164a3d933caabac1a635 Mon Sep 17 00:00:00 2001 From: deadman80 Date: Tue, 26 Jun 2018 15:02:37 -0400 Subject: [PATCH 0170/1002] request corrections made --- addons/EasyNuke/EasyNuke.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/EasyNuke/EasyNuke.lua b/addons/EasyNuke/EasyNuke.lua index ec12a6decf..a04e53041f 100644 --- a/addons/EasyNuke/EasyNuke.lua +++ b/addons/EasyNuke/EasyNuke.lua @@ -134,15 +134,15 @@ windower.register_event('addon command', function (command, arg) targets_index = targets_index % 3 + 1 target_mode = targets[targets_index] end - windower.add_to_chat(206,"/echo Target Mode is now: "..target_mode) + windower.add_to_chat(206,"Target Mode is now: "..target_mode) elseif command == "element" or command == "mode" then arg = string.lower(arg) if elements:contains(arg) or other_modes:contains(arg) then current_element = arg - windower.add_to_chat(206,"/echo Element Mode is now: "..string.ucfirst(current_element)) + windower.add_to_chat(206,"Element Mode is now: "..string.ucfirst(current_element)) else - windower.add_to_chat(206,"/echo Invalid element") + windower.add_to_chat(206,"Invalid element") end elseif command == "cycle" then From 6d8ef374d2905c83c7bed04eb8be3a6d13add64e Mon Sep 17 00:00:00 2001 From: deadman80 Date: Tue, 26 Jun 2018 15:11:27 -0400 Subject: [PATCH 0171/1002] Requested changes made. Repairing reverted changes due to not knowing how to use GitHub properly. --- addons/EasyNuke/EasyNuke.lua | 206 ----------------------------------- 1 file changed, 206 deletions(-) diff --git a/addons/EasyNuke/EasyNuke.lua b/addons/EasyNuke/EasyNuke.lua index 4202b68b07..a04e53041f 100644 --- a/addons/EasyNuke/EasyNuke.lua +++ b/addons/EasyNuke/EasyNuke.lua @@ -1,4 +1,3 @@ -<<<<<<< HEAD --[[ Copyright © 2018, FaceDesk Linkshell All rights reserved. @@ -202,209 +201,4 @@ windower.register_event('addon command', function (command, arg) elseif command == "show" or command == "current" or command == "showcurrent" then windower.add_to_chat(206, "----- Element Mode: "..string.ucfirst(current_element).." --- Target Mode: < "..target_mode.." > -----") end -======= ---[[ -Copyright © 2018, FaceDesk Linkshell -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 EasyNuke 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 FaceDesk Linkshell, or it's members, 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.name = 'EasyNuke' -_addon.author = 'FaceDesk Linkshell' -_addon.version = '1.0.3' -_addon.command = "ez" - -require('chat') -require('lists') -require('logger') -require('sets') -require('tables') -require('strings') -require('pack') - -file = require('files') -config = require('config') -texts = require('texts') -res = require('resources') - -local defaults = T{} -defaults.current_element = "fire" -defaults.target_mode = "t" -settings = config.load(defaults) - -current_element = "fire" -target_mode = "t" - -elements = T{"fire","wind","thunder","light","ice","water","earth","dark"} -elements_dark = T{"ice","water","earth","dark"} -elements_light = T{"fire","wind","thunder","light"} -elements_index = 1 -other_modes = S{"drain","aspir","absorb","cure"} - -targets = T{"t","bt","stnpc"} -targets_index = 1 - -spell_tables = {} -spell_tables["fire"] = T{"Fire","Fire II","Fire III","Fire IV","Fire V","Fire VI",} -spell_tables["fire"]["ga"] = T{"Firaga","Firaga II","Firaga III","Firaja",} -spell_tables["fire"]["ra"] = T{"Fira","Fira II","Fira III"} -spell_tables["earth"] = T{"Stone","Stone II","Stone III","Stone IV","Stone V","Stone VI",} -spell_tables["earth"]["ga"] = T{"Stonega","Stonega II","Stonega III","Stoneja",} -spell_tables["earth"]["ra"] = T{"Stonera","Stonera II","Stonera III"} -spell_tables["wind"] = T{"Aero","Aero II","Aero III","Aero IV","Aero V","Aero VI",} -spell_tables["wind"]["ga"] = T{"Aeroga","Aeroga II","Aeroga III","Aeroja",} -spell_tables["wind"]["ra"] = T{"Aerora","Aerora II","Aerora III"} -spell_tables["water"] = T{"Water","Water II","Water III","Water IV","Water V","Water VI",} -spell_tables["water"]["ga"] = T{"Waterga","Waterga II","Waterga III","Waterja",} -spell_tables["water"]["ra"] = T{"Watera","Watera II","Watera III"} -spell_tables["ice"] = T{"Blizzard","Blizzard II","Blizzard III","Blizzard IV","Blizzard V","Blizzard VI",} -spell_tables["ice"]["ga"] = T{"Blizzaga","Blizzaga II","Blizzaga III","Blizzaja",} -spell_tables["ice"]["ra"] = T{"Blizzara","Blizzara II","Blizzara III"} -spell_tables["thunder"] = T{"Thunder","Thunder II","Thunder III","Thunder IV","Thunder V","Thunder VI",} -spell_tables["thunder"]["ga"] = T{"Thundaga","Thundaga II","Thundaga III","Thundaja",} -spell_tables["thunder"]["ra"] = T{"Thundara","Thundara II","Thundara III"} -spell_tables["light"] = T{"Banish","Banish II","Holy","Banish III",} -spell_tables["light"]["ga"] = T{"Banishga","Banishga II"} -spell_tables["dark"] = T{"Impact"} -spell_tables["dark"]["ga"] = T{"Comet"} -spell_tables["cure"] = T{"Cure","Cure II","Cure III","Cure IV","Cure V","Cure VI"} -spell_tables["cure"]["ga"] = T{"Curaga","Curaga II","Curaga III","Curaga IV","Curaga V",} -spell_tables["cure"]["ra"] = T{"Cura","Cura II","Cura III"} -spell_tables["drain"] = T{"Aspir","Aspir II","Aspir III","Drain","Drain II","Drain III"} -spell_tables["drain"]["ga"] = spell_tables["drain"] -spell_tables["drain"]["ra"] = spell_tables["drain"] -spell_tables["aspir"] = spell_tables["drain"] -spell_tables["aspir"]["ga"] = spell_tables["drain"] -spell_tables["aspir"]["ra"] = spell_tables["drain"] -spell_tables["absorb"] = T{"Absorb-Acc","Absorb-TP","Absorb-Attri","Absorb-STR","Absorb-DEX","Absorb-VIT","Absorb-AGI","Absorb-INT","Absorb-MND","Absorb-CHR"} -spell_tables["absorb"]["ga"] = spell_tables["absorb"] -spell_tables["absorb"]["ra"] = spell_tables["absorb"] - -windower.register_event('addon command', function (command, arg) - - if command == "boom" or command == "nuke" then - local current_spell_table = spell_tables[current_element] - if arg == nil then arg = 1 end - arg = tonumber(arg) - if arg > #spell_tables[current_element] then - windower.add_to_chat(206,"Invalid Spell. Try again.") return - end - windower.chat.input("/ma "..current_spell_table[arg].." <"..target_mode..">") - - elseif command == "boomga" or command == "bga" then - local current_spell_table = spell_tables[current_element]["ga"] - if arg == nil then arg = 1 end - arg = tonumber(arg) - if arg > #spell_tables[current_element]["ga"] or spell_tables[current_element]["ga"] == nil then - windower.add_to_chat(206,"Invalid Spell. Try again.") return - end - windower.chat.input("/ma "..current_spell_table[arg].." <"..target_mode..">") - - elseif command == "boomra" or command == "bra" then - local current_spell_table = spell_tables[current_element]["ra"] - if arg == nil then arg = 1 end - arg = tonumber(arg) - if arg > #spell_tables[current_element]["ra"] or spell_tables[current_element]["ra"] == nil then - windower.add_to_chat(206,"Invalid Spell. Try again.") return - end - windower.chat.input("/ma "..current_spell_table[arg].." <"..target_mode..">") - - elseif command == "target" then - if arg then - arg = string.lower(arg) - target_mode = arg - else - targets_index = targets_index % 3 + 1 - target_mode = targets[targets_index] - end - windower.add_to_chat(206,"/echo Target Mode is now: "..target_mode) - - elseif command == "element" or command == "mode" then - arg = string.lower(arg) - if elements:contains(arg) or other_modes:contains(arg) then - current_element = arg - windower.add_to_chat(206,"/echo Element Mode is now: "..string.ucfirst(current_element)) - else - windower.add_to_chat(206,"/echo Invalid element") - end - - elseif command == "cycle" then - if arg then - arg = string.lower(arg) - end - if arg == nil then - elements_index = elements_index % 8 + 1 - current_element = elements[elements_index] - elseif arg == "back" then - elements_index = elements_index - 1 - if elements_index < 1 then - elements_index = 8 - end - current_element = elements[elements_index] - elseif arg == "dark" then - elements_index = elements_index % 4 + 1 - current_element = elements_dark[elements_index] - elseif arg == "light" then - elements_index = elements_index % 4 + 1 - current_element = elements_light[elements_index] - elseif arg == "fusion" then - if current_element ~= "fire" and current_element ~= "light" then - current_element = "fire" - elseif current_element == "fire" then - current_element = "light" - elseif current_element == "light" then - current_element = "fire" - end - elseif arg == "distortion" or arg == "dist" then - if current_element ~= "ice" and current_element ~= "water" then - current_element = "ice" - elseif current_element == "ice" then - current_element = "water" - elseif current_element == "water" then - current_element = "ice" - end - elseif arg == "gravitation" or arg == "grav" then - if current_element ~= "earth" and current_element ~= "dark" then - current_element = "earth" - elseif current_element == "earth" then - current_element = "dark" - elseif current_element == "dark" then - current_element = "earth" - end - elseif arg == "fragmentation" or arg == "frag" then - if current_element ~= "thunder" and current_element ~= "wind" then - current_element = "thunder" - elseif current_element == "thunder" then - current_element = "wind" - elseif current_element == "wind" then - current_element = "thunder" - end - end - windower.add_to_chat(206, "Element Mode is now: "..string.ucfirst(current_element)) - elseif command == "show" or command == "current" or command == "showcurrent" then - windower.add_to_chat(206, "----- Element Mode: "..string.ucfirst(current_element).." --- Target Mode: < "..target_mode.." > -----") - end ->>>>>>> 8e39e479ac8d5671ad25dd4173dbe72cb68856e4 end) \ No newline at end of file From acc47a37e3310372ce873ba9d442b729a79651fd Mon Sep 17 00:00:00 2001 From: deadman80 Date: Tue, 26 Jun 2018 16:44:27 -0400 Subject: [PATCH 0172/1002] Adjustments Added the unhandled command section, so //boom //boomga //boomra all work now. Fixed some odd behavior when cycle modes were mixed together. Converted T{} to {} or S{}. Author name changed for simplicity's sake. --- addons/EasyNuke/EasyNuke.lua | 148 +++++++++++++++++++++++------------ 1 file changed, 96 insertions(+), 52 deletions(-) diff --git a/addons/EasyNuke/EasyNuke.lua b/addons/EasyNuke/EasyNuke.lua index a04e53041f..673853a662 100644 --- a/addons/EasyNuke/EasyNuke.lua +++ b/addons/EasyNuke/EasyNuke.lua @@ -1,5 +1,5 @@ --[[ -Copyright © 2018, FaceDesk Linkshell +Copyright © 2018, Nyarlko All rights reserved. Redistribution and use in source and binary forms, with or without @@ -17,7 +17,7 @@ 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 FaceDesk Linkshell, or it's members, BE LIABLE FOR ANY +DISCLAIMED. IN NO EVENT SHALL Nyarlko, or it's members, 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 @@ -27,22 +27,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] _addon.name = 'EasyNuke' -_addon.author = 'FaceDesk Linkshell' -_addon.version = '1.0.3' +_addon.author = 'Nyarlko' +_addon.version = '1.0.7' _addon.command = "ez" -require('chat') -require('lists') -require('logger') require('sets') require('tables') require('strings') -require('pack') -file = require('files') config = require('config') -texts = require('texts') -res = require('resources') local defaults = T{} defaults.current_element = "fire" @@ -52,51 +45,92 @@ settings = config.load(defaults) current_element = "fire" target_mode = "t" -elements = T{"fire","wind","thunder","light","ice","water","earth","dark"} -elements_dark = T{"ice","water","earth","dark"} -elements_light = T{"fire","wind","thunder","light"} +elements = S{"fire","wind","thunder","light","ice","water","earth","dark"} +elements_dark = S{"ice","water","earth","dark"} +elements_light = S{"fire","wind","thunder","light"} elements_index = 1 other_modes = S{"drain","aspir","absorb","cure"} -targets = T{"t","bt","stnpc"} +targets = T{"t","bt","stnpc",} targets_index = 1 spell_tables = {} -spell_tables["fire"] = T{"Fire","Fire II","Fire III","Fire IV","Fire V","Fire VI",} -spell_tables["fire"]["ga"] = T{"Firaga","Firaga II","Firaga III","Firaja",} -spell_tables["fire"]["ra"] = T{"Fira","Fira II","Fira III"} -spell_tables["earth"] = T{"Stone","Stone II","Stone III","Stone IV","Stone V","Stone VI",} -spell_tables["earth"]["ga"] = T{"Stonega","Stonega II","Stonega III","Stoneja",} -spell_tables["earth"]["ra"] = T{"Stonera","Stonera II","Stonera III"} -spell_tables["wind"] = T{"Aero","Aero II","Aero III","Aero IV","Aero V","Aero VI",} -spell_tables["wind"]["ga"] = T{"Aeroga","Aeroga II","Aeroga III","Aeroja",} -spell_tables["wind"]["ra"] = T{"Aerora","Aerora II","Aerora III"} -spell_tables["water"] = T{"Water","Water II","Water III","Water IV","Water V","Water VI",} -spell_tables["water"]["ga"] = T{"Waterga","Waterga II","Waterga III","Waterja",} -spell_tables["water"]["ra"] = T{"Watera","Watera II","Watera III"} -spell_tables["ice"] = T{"Blizzard","Blizzard II","Blizzard III","Blizzard IV","Blizzard V","Blizzard VI",} -spell_tables["ice"]["ga"] = T{"Blizzaga","Blizzaga II","Blizzaga III","Blizzaja",} -spell_tables["ice"]["ra"] = T{"Blizzara","Blizzara II","Blizzara III"} -spell_tables["thunder"] = T{"Thunder","Thunder II","Thunder III","Thunder IV","Thunder V","Thunder VI",} -spell_tables["thunder"]["ga"] = T{"Thundaga","Thundaga II","Thundaga III","Thundaja",} -spell_tables["thunder"]["ra"] = T{"Thundara","Thundara II","Thundara III"} -spell_tables["light"] = T{"Banish","Banish II","Holy","Banish III",} -spell_tables["light"]["ga"] = T{"Banishga","Banishga II"} -spell_tables["dark"] = T{"Impact"} -spell_tables["dark"]["ga"] = T{"Comet"} -spell_tables["cure"] = T{"Cure","Cure II","Cure III","Cure IV","Cure V","Cure VI"} -spell_tables["cure"]["ga"] = T{"Curaga","Curaga II","Curaga III","Curaga IV","Curaga V",} -spell_tables["cure"]["ra"] = T{"Cura","Cura II","Cura III"} -spell_tables["drain"] = T{"Aspir","Aspir II","Aspir III","Drain","Drain II","Drain III"} +spell_tables["fire"] = {"Fire","Fire II","Fire III","Fire IV","Fire V","Fire VI",} +spell_tables["fire"]["ga"] = {"Firaga","Firaga II","Firaga III","Firaja",} +spell_tables["fire"]["ra"] = {"Fira","Fira II","Fira III"} +spell_tables["earth"] = {"Stone","Stone II","Stone III","Stone IV","Stone V","Stone VI",} +spell_tables["earth"]["ga"] = {"Stonega","Stonega II","Stonega III","Stoneja",} +spell_tables["earth"]["ra"] = {"Stonera","Stonera II","Stonera III"} +spell_tables["wind"] = {"Aero","Aero II","Aero III","Aero IV","Aero V","Aero VI",} +spell_tables["wind"]["ga"] = {"Aeroga","Aeroga II","Aeroga III","Aeroja",} +spell_tables["wind"]["ra"] = {"Aerora","Aerora II","Aerora III"} +spell_tables["water"] = {"Water","Water II","Water III","Water IV","Water V","Water VI",} +spell_tables["water"]["ga"] = {"Waterga","Waterga II","Waterga III","Waterja",} +spell_tables["water"]["ra"] = {"Watera","Watera II","Watera III"} +spell_tables["ice"] = {"Blizzard","Blizzard II","Blizzard III","Blizzard IV","Blizzard V","Blizzard VI",} +spell_tables["ice"]["ga"] = {"Blizzaga","Blizzaga II","Blizzaga III","Blizzaja",} +spell_tables["ice"]["ra"] = {"Blizzara","Blizzara II","Blizzara III"} +spell_tables["thunder"] = {"Thunder","Thunder II","Thunder III","Thunder IV","Thunder V","Thunder VI",} +spell_tables["thunder"]["ga"] = {"Thundaga","Thundaga II","Thundaga III","Thundaja",} +spell_tables["thunder"]["ra"] = {"Thundara","Thundara II","Thundara III"} +spell_tables["light"] = {"Banish","Banish II","Holy","Banish III",} +spell_tables["light"]["ga"] = {"Banishga","Banishga II"} +spell_tables["dark"] = {"Impact"} +spell_tables["dark"]["ga"] = {"Comet"} +spell_tables["cure"] = {"Cure","Cure II","Cure III","Cure IV","Cure V","Cure VI"} +spell_tables["cure"]["ga"] = {"Curaga","Curaga II","Curaga III","Curaga IV","Curaga V",} +spell_tables["cure"]["ra"] = {"Cura","Cura II","Cura III"} +spell_tables["drain"] = {"Aspir","Aspir II","Aspir III","Drain","Drain II","Drain III"} spell_tables["drain"]["ga"] = spell_tables["drain"] spell_tables["drain"]["ra"] = spell_tables["drain"] spell_tables["aspir"] = spell_tables["drain"] spell_tables["aspir"]["ga"] = spell_tables["drain"] spell_tables["aspir"]["ra"] = spell_tables["drain"] -spell_tables["absorb"] = T{"Absorb-Acc","Absorb-TP","Absorb-Attri","Absorb-STR","Absorb-DEX","Absorb-VIT","Absorb-AGI","Absorb-INT","Absorb-MND","Absorb-CHR"} +spell_tables["absorb"] = {"Absorb-Acc","Absorb-TP","Absorb-Attri","Absorb-STR","Absorb-DEX","Absorb-VIT","Absorb-AGI","Absorb-INT","Absorb-MND","Absorb-CHR"} spell_tables["absorb"]["ga"] = spell_tables["absorb"] spell_tables["absorb"]["ra"] = spell_tables["absorb"] +local indices = { + fire = 1, + wind = 2, + thunder = 3, + light = 4, + ice = 5, + water = 6, + earth = 7, + dark = 8, +} + +windower.register_event("unhandled command", function (command, arg) + if command == "boom" or command == "nuke" then + local current_spell_table = spell_tables[current_element] + if arg == nil then arg = 1 end + arg = tonumber(arg) + if arg > #spell_tables[current_element] then + windower.add_to_chat(206,"Invalid Spell.") return + end + windower.chat.input("/ma "..current_spell_table[arg].." <"..target_mode..">") + + elseif command == "boomga" or command == "bga" then + local current_spell_table = spell_tables[current_element]["ga"] + if arg == nil then arg = 1 end + arg = tonumber(arg) + if arg > #spell_tables[current_element]["ga"] or spell_tables[current_element]["ga"] == nil then + windower.add_to_chat(206,"Invalid Spell.") return + end + windower.chat.input("/ma "..current_spell_table[arg].." <"..target_mode..">") + + elseif command == "boomra" or command == "bra" then + local current_spell_table = spell_tables[current_element]["ra"] + if arg == nil then arg = 1 end + arg = tonumber(arg) + if arg > #spell_tables[current_element]["ra"] or spell_tables[current_element]["ra"] == nil then + windower.add_to_chat(206,"Invalid Spell.") return + end + windower.chat.input("/ma "..current_spell_table[arg].." <"..target_mode..">") + end +end) + windower.register_event('addon command', function (command, arg) if command == "boom" or command == "nuke" then @@ -104,7 +138,7 @@ windower.register_event('addon command', function (command, arg) if arg == nil then arg = 1 end arg = tonumber(arg) if arg > #spell_tables[current_element] then - windower.add_to_chat(206,"Invalid Spell. Try again.") return + windower.add_to_chat(206,"Invalid Spell.") return end windower.chat.input("/ma "..current_spell_table[arg].." <"..target_mode..">") @@ -113,7 +147,7 @@ windower.register_event('addon command', function (command, arg) if arg == nil then arg = 1 end arg = tonumber(arg) if arg > #spell_tables[current_element]["ga"] or spell_tables[current_element]["ga"] == nil then - windower.add_to_chat(206,"Invalid Spell. Try again.") return + windower.add_to_chat(206,"Invalid Spell.") return end windower.chat.input("/ma "..current_spell_table[arg].." <"..target_mode..">") @@ -122,7 +156,7 @@ windower.register_event('addon command', function (command, arg) if arg == nil then arg = 1 end arg = tonumber(arg) if arg > #spell_tables[current_element]["ra"] or spell_tables[current_element]["ra"] == nil then - windower.add_to_chat(206,"Invalid Spell. Try again.") return + windower.add_to_chat(206,"Invalid Spell.") return end windower.chat.input("/ma "..current_spell_table[arg].." <"..target_mode..">") @@ -131,7 +165,7 @@ windower.register_event('addon command', function (command, arg) arg = string.lower(arg) target_mode = arg else - targets_index = targets_index % 3 + 1 + targets_index = targets_index % #targets + 1 target_mode = targets[targets_index] end windower.add_to_chat(206,"Target Mode is now: "..target_mode) @@ -149,22 +183,32 @@ windower.register_event('addon command', function (command, arg) if arg then arg = string.lower(arg) end - if arg == nil then + if arg == nil then + elements_index = indices[current_element] elements_index = elements_index % 8 + 1 current_element = elements[elements_index] elseif arg == "back" then + elements_index = indices[current_element] elements_index = elements_index - 1 if elements_index < 1 then elements_index = 8 end current_element = elements[elements_index] elseif arg == "dark" then - elements_index = elements_index % 4 + 1 - current_element = elements_dark[elements_index] + if elements_light:contains(current_element) then + elements_index = 1 + else + elements_index = elements_index % 4 + 1 + end + current_element = elements_dark[elements_index] elseif arg == "light" then - elements_index = elements_index % 4 + 1 - current_element = elements_light[elements_index] - elseif arg == "fusion" then + if elements_dark:contains(current_element) then + elements_index = 1 + else + elements_index = elements_index % 4 + 1 + end + current_element = elements_light[elements_index] + elseif arg == "fusion" or "fus" then if current_element ~= "fire" and current_element ~= "light" then current_element = "fire" elseif current_element == "fire" then From 81fbe06ce05cb4361b132fb40e6d429d1d000d07 Mon Sep 17 00:00:00 2001 From: deadman80 Date: Tue, 26 Jun 2018 17:03:37 -0400 Subject: [PATCH 0173/1002] Reverted T{} to S{} changes on elements tables Had to change these back to unbreak cycle modes. Squashed the last of the cycle oddities. --- addons/EasyNuke/EasyNuke.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/addons/EasyNuke/EasyNuke.lua b/addons/EasyNuke/EasyNuke.lua index 673853a662..aa02547181 100644 --- a/addons/EasyNuke/EasyNuke.lua +++ b/addons/EasyNuke/EasyNuke.lua @@ -45,9 +45,9 @@ settings = config.load(defaults) current_element = "fire" target_mode = "t" -elements = S{"fire","wind","thunder","light","ice","water","earth","dark"} -elements_dark = S{"ice","water","earth","dark"} -elements_light = S{"fire","wind","thunder","light"} +elements = T{"fire","wind","thunder","light","ice","water","earth","dark"} +elements_dark = T{"ice","water","earth","dark"} +elements_light = T{"fire","wind","thunder","light"} elements_index = 1 other_modes = S{"drain","aspir","absorb","cure"} @@ -195,14 +195,14 @@ windower.register_event('addon command', function (command, arg) end current_element = elements[elements_index] elseif arg == "dark" then - if elements_light:contains(current_element) then + if not elements_dark:contains(current_element) then elements_index = 1 else elements_index = elements_index % 4 + 1 end current_element = elements_dark[elements_index] elseif arg == "light" then - if elements_dark:contains(current_element) then + if not elements_light:contains(current_element) then elements_index = 1 else elements_index = elements_index % 4 + 1 From 9919b22cc4489d4e70dadb90ec4192f976eb5d69 Mon Sep 17 00:00:00 2001 From: deadman80 Date: Tue, 26 Jun 2018 17:24:58 -0400 Subject: [PATCH 0174/1002] Cycle interaction fix "cycle" and "cycle back" were bugging out if used while current element/mode was an "other_modes". --- addons/EasyNuke/EasyNuke.lua | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/addons/EasyNuke/EasyNuke.lua b/addons/EasyNuke/EasyNuke.lua index aa02547181..3335e1331c 100644 --- a/addons/EasyNuke/EasyNuke.lua +++ b/addons/EasyNuke/EasyNuke.lua @@ -184,12 +184,20 @@ windower.register_event('addon command', function (command, arg) arg = string.lower(arg) end if arg == nil then - elements_index = indices[current_element] - elements_index = elements_index % 8 + 1 + if not elements:contains(current_element) then + elements_index = 1 + else + elements_index = indices[current_element] + elements_index = elements_index % 8 + 1 + end current_element = elements[elements_index] elseif arg == "back" then - elements_index = indices[current_element] - elements_index = elements_index - 1 + if not elements:contains(current_element) then + elements_index = 1 + else + elements_index = indices[current_element] + elements_index = elements_index - 1 + end if elements_index < 1 then elements_index = 8 end @@ -197,7 +205,7 @@ windower.register_event('addon command', function (command, arg) elseif arg == "dark" then if not elements_dark:contains(current_element) then elements_index = 1 - else + else elements_index = elements_index % 4 + 1 end current_element = elements_dark[elements_index] From c99d88c1719fc7dac827db144abbd0fd3ba9666a Mon Sep 17 00:00:00 2001 From: deadman80 Date: Wed, 27 Jun 2018 00:23:05 -0400 Subject: [PATCH 0175/1002] Updated Readme --- addons/EasyNuke/readme.md | 96 ++++++--------------------------------- 1 file changed, 15 insertions(+), 81 deletions(-) diff --git a/addons/EasyNuke/readme.md b/addons/EasyNuke/readme.md index 211640ea3d..32c2e24567 100644 --- a/addons/EasyNuke/readme.md +++ b/addons/EasyNuke/readme.md @@ -1,4 +1,3 @@ -<<<<<<< HEAD EasyNuke provides universal commands for casting single target and area of effect BLM and GEO nukes, and WHM cures. Commands: @@ -8,6 +7,7 @@ element # ** EX: //ez element ice <<<< Sets mode to ice. ** Macro usage: /con ez element # ** Valid arguments: Fire, Wind, Thunder, Light, Ice, Water, Earth, Dark, Drain, Aspir, Absorb, Cure +*** Cure Mode: Follows standard single/ga/ra pattern and usage *** Drain and Aspir Mode: Aspir, Aspir II, Aspir III, Drain, Drain II, Drain III *** Absorb Mode: Absorb-Acc, Absorb-TP, Absorb-Attri, Absorb-STR, Absorb-DEX, Absorb-VIT, Absorb-AGI, Absorb-INT, Absorb-MND, Absorb-CHR *** EX: //ez element absorb >>> //ez boom 4 <<<< Casts Absorb-STR @@ -24,17 +24,17 @@ cycle back cycle dark * Cycles through element modes in the following order: Ice, Water, Earth, Dark -** EX: //ez cycle dark <<<< If you were in Light mode, then you will change to Ice mode. +** EX: //ez cycle dark <<<< If you were in Dark mode, then you will change to Ice mode. ** Macro usage: /con ez cycle dark cycle light * Cycles through element modes in the following order: Fire, Wind, Thunder, Light -** EX: //ez cycle light <<<< If you were in Light mode, then you will change to Ice mode. +** EX: //ez cycle light <<<< If you were in Light mode, then you will change to Fire mode. ** Macro usage: /con ez cycle light cycle # * Cycles between the two elements of a T2 skillchain. -** Fusion: Fire, Light +** Fusion, Fus: Fire, Light ** Fragmentation, Frag: Thunder, Wind ** Distortion, Dist: Ice, Water ** Gravitation, Grav: Earth, Dark @@ -46,93 +46,27 @@ target # ** EX: //ez target bt <<<< Spells will be cast using . *** There are no failsafes for this. Any given argument will be accepted, even if it does not function as a targeting argument. *** If no argument is given, then will cycle through target modes in the following order: t, bt, stnpc -** Macro usage: /con ez target OR /con ez target # +** Macro usage: /con ez target # OR /con ez target -show, current or showcurrent +showcurrent / show / current * Echoes the current elemental and targeting modes in the chat log. ** EX: //ez showcurrent ** Macro usage: /con ez showcurrent boom # * Casts a single target tier# nuke of the current element, and using the current targeting mode. -** EX: //ez boom 4 <<<< If in "fire" mode, and mode is "t", will cast Fire IV on your current target. -** Macro usage: /con ez boom # +** EX: //ez boom 4 <<<< If Element Mode is Fire, and targeting mode is "t", you will cast Fire IV on your current target. +** EX2: //boom 6 <<<< If Element Mode is Ice, and targeting mode is "bt", you will cast Blizzard VI on the current battle target. +** Macro usage: /con ez boom # /OR/ /con boom # boomga # * Casts an area of effect nuke of tier#. BLM: -ga, -ga II, -ga III, -ja. (Also works for Curaga's while in Cure mode.) -** EX: //ez boomga 4 <<<< If in "ice" mode, and mode is "t", will cast Blizzaja on your current target. -** Macro usage: /con ez boomga # +** EX: //ez boomga 4 <<<< If Element Mode is Ice, and targeting mode is "t", will cast Blizzaja on your current target. +** EX2: //boomga 3 <<<< If Element Mode is Ice, and targeting mode is "bt", you will cast Blizzaga III on the current battle target. +** Macro usage: /con ez boomga # /OR/ /con boomga # boomra # * Casts an area of effect nuke of tier#. GEO's -ra AOE nukes and WHM's Cura line -** EX: //ez boomra 3 <<<< If in "ice" mode, and mode is "t", will cast Blizzara III on your current target. -======= -EasyNuke provides universal commands for casting single target and area of effect BLM and GEO nukes, and WHM cures. - -Commands: - -element # -* Changes current element mode to #. -** EX: //ez element ice <<<< Sets mode to ice. -** Macro usage: /con ez element # -** Valid arguments: Fire, Wind, Thunder, Light, Ice, Water, Earth, Dark, Drain, Aspir, Absorb, Cure -*** Drain and Aspir Mode: Aspir, Aspir II, Aspir III, Drain, Drain II, Drain III -*** Absorb Mode: Absorb-Acc, Absorb-TP, Absorb-Attri, Absorb-STR, Absorb-DEX, Absorb-VIT, Absorb-AGI, Absorb-INT, Absorb-MND, Absorb-CHR -*** EX: //ez element absorb >>> //ez boom 4 <<<< Casts Absorb-STR - -cycle -* Cycles through element modes in the following left-to-right order: Fire, Wind, Thunder, Light, Ice, Water, Earth, Dark -** EX: //ez cycle <<<< If you were in Light mode, then you will change to Ice mode. -** Macro usage: /con ez cycle - -cycle back -* Same as "cycle", but goes in right-to-left order. -** EX: //ez cycle back <<<< If you were in Light mode, then you will change to Thunder mode. -** Macro usage: /con ez cycle back - -cycle dark -* Cycles through element modes in the following order: Ice, Water, Earth, Dark -** EX: //ez cycle dark <<<< If you were in Light mode, then you will change to Ice mode. -** Macro usage: /con ez cycle dark - -cycle light -* Cycles through element modes in the following order: Fire, Wind, Thunder, Light -** EX: //ez cycle light <<<< If you were in Light mode, then you will change to Ice mode. -** Macro usage: /con ez cycle light - -cycle # -* Cycles between the two elements of a T2 skillchain. -** Fusion: Fire, Light -** Fragmentation, Frag: Thunder, Wind -** Distortion, Dist: Ice, Water -** Gravitation, Grav: Earth, Dark -*** EX: //ez cycle dist <<<< If you were in Ice mode, will change you to Water mode. If you were in any other mode, will change you to Ice mode. -*** Macro usage: /con ez cycle fragmentation - -target # -* Changes targeting mode to #. This sets what's between the < > brackets used for targeting in macros. -** EX: //ez target bt <<<< Spells will be cast using . -*** There are no failsafes for this. Any given argument will be accepted, even if it does not function as a targeting argument. -*** If no argument is given, then will cycle through target modes in the following order: t, bt, stnpc -** Macro usage: /con ez target OR /con ez target # - -show, current or showcurrent -* Echoes the current elemental and targeting modes in the chat log. -** EX: //ez showcurrent -** Macro usage: /con ez showcurrent - -boom # -* Casts a single target tier# nuke of the current element, and using the current targeting mode. -** EX: //ez boom 4 <<<< If in "fire" mode, and mode is "t", will cast Fire IV on your current target. -** Macro usage: /con ez boom # - -boomga # -* Casts an area of effect nuke of tier#. BLM: -ga, -ga II, -ga III, -ja. (Also works for Curaga's while in Cure mode.) -** EX: //ez boomga 4 <<<< If in "ice" mode, and mode is "t", will cast Blizzaja on your current target. -** Macro usage: /con ez boomga # - -boomra # -* Casts an area of effect nuke of tier#. GEO's -ra AOE nukes and WHM's Cura line -** EX: //ez boomra 3 <<<< If in "ice" mode, and mode is "t", will cast Blizzara III on your current target. ->>>>>>> 8e39e479ac8d5671ad25dd4173dbe72cb68856e4 -** Macro usage: /con ez boomra # \ No newline at end of file +** EX: //ez boomra 3 <<<< If Element Mode is Ice, and mode is "bt", will cast Blizzara III on your current battle target. +** EX2: //boomra 2 <<<< If Element Mode is Cure, and mode is "me", you will cast Cura II on yourself. +** Macro usage: /con ez boomra # /OR/ /con boomra # \ No newline at end of file From 4942a4a82cab56b0b2ff6823b0aa56da661aed0e Mon Sep 17 00:00:00 2001 From: deadman80 Date: Wed, 27 Jun 2018 00:41:36 -0400 Subject: [PATCH 0176/1002] Attempt at correcting readme formatting --- addons/EasyNuke/readme.md | 104 +++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 51 deletions(-) diff --git a/addons/EasyNuke/readme.md b/addons/EasyNuke/readme.md index 32c2e24567..ebdcd0444e 100644 --- a/addons/EasyNuke/readme.md +++ b/addons/EasyNuke/readme.md @@ -2,71 +2,73 @@ EasyNuke provides universal commands for casting single target and area of effec Commands: -element # -* Changes current element mode to #. -** EX: //ez element ice <<<< Sets mode to ice. -** Macro usage: /con ez element # -** Valid arguments: Fire, Wind, Thunder, Light, Ice, Water, Earth, Dark, Drain, Aspir, Absorb, Cure -*** Cure Mode: Follows standard single/ga/ra pattern and usage -*** Drain and Aspir Mode: Aspir, Aspir II, Aspir III, Drain, Drain II, Drain III -*** Absorb Mode: Absorb-Acc, Absorb-TP, Absorb-Attri, Absorb-STR, Absorb-DEX, Absorb-VIT, Absorb-AGI, Absorb-INT, Absorb-MND, Absorb-CHR -*** EX: //ez element absorb >>> //ez boom 4 <<<< Casts Absorb-STR +#### element XXX +* Changes current element mode to XXX. + * EX: //ez element ice <<<< Sets mode to ice. + * Macro usage: /con ez element XXX + * Valid arguments: Fire, Wind, Thunder, Light, Ice, Water, Earth, Dark, Drain, Aspir, Absorb, Cure + * Cure Mode: Follows standard single/ga/ra pattern and usage + * Drain and Aspir Mode: Aspir, Aspir II, Aspir III, Drain, Drain II, Drain III + * Absorb Mode: Absorb-Acc, Absorb-TP, Absorb-Attri, Absorb-STR, Absorb-DEX, Absorb-VIT, Absorb-AGI, Absorb-INT, Absorb-MND, Absorb-CHR + * EX: //ez element absorb >>> //ez boom 4 <<<< Casts Absorb-STR + * Macro usage: /con ez element XXX -cycle +#### cycle * Cycles through element modes in the following left-to-right order: Fire, Wind, Thunder, Light, Ice, Water, Earth, Dark -** EX: //ez cycle <<<< If you were in Light mode, then you will change to Ice mode. -** Macro usage: /con ez cycle + * EX: //ez cycle <<<< If you were in Light mode, then you will change to Ice mode. + * Macro usage: /con ez cycle -cycle back +#### cycle back * Same as "cycle", but goes in right-to-left order. -** EX: //ez cycle back <<<< If you were in Light mode, then you will change to Thunder mode. -** Macro usage: /con ez cycle back + * EX: //ez cycle back <<<< If you were in Light mode, then you will change to Thunder mode. + * Macro usage: /con ez cycle back -cycle dark +#### cycle dark * Cycles through element modes in the following order: Ice, Water, Earth, Dark -** EX: //ez cycle dark <<<< If you were in Dark mode, then you will change to Ice mode. -** Macro usage: /con ez cycle dark + * EX: //ez cycle dark <<<< If you were in Dark mode, then you will change to Ice mode. + * Macro usage: /con ez cycle dark -cycle light +#### cycle light * Cycles through element modes in the following order: Fire, Wind, Thunder, Light -** EX: //ez cycle light <<<< If you were in Light mode, then you will change to Fire mode. -** Macro usage: /con ez cycle light + * EX: //ez cycle light <<<< If you were in Light mode, then you will change to Fire mode. + * Macro usage: /con ez cycle light -cycle # +#### cycle XXX * Cycles between the two elements of a T2 skillchain. -** Fusion, Fus: Fire, Light -** Fragmentation, Frag: Thunder, Wind -** Distortion, Dist: Ice, Water -** Gravitation, Grav: Earth, Dark -*** EX: //ez cycle dist <<<< If you were in Ice mode, will change you to Water mode. If you were in any other mode, will change you to Ice mode. -*** Macro usage: /con ez cycle fragmentation + * Valid commands: Elements included + * Fusion, Fus: Fire, Light + * Fragmentation, Frag: Thunder, Wind + * Distortion, Dist: Ice, Water + * Gravitation, Grav: Earth, Dark + * EX: //ez cycle dist <<<< If you were in Ice mode, will change you to Water mode. If you were in any other mode, will change you to Ice mode. + * Macro usage: /con ez cycle fragmentation -target # +#### target XXX * Changes targeting mode to #. This sets what's between the < > brackets used for targeting in macros. -** EX: //ez target bt <<<< Spells will be cast using . -*** There are no failsafes for this. Any given argument will be accepted, even if it does not function as a targeting argument. -*** If no argument is given, then will cycle through target modes in the following order: t, bt, stnpc -** Macro usage: /con ez target # OR /con ez target + * EX: //ez target bt <<<< Spells will be cast using . + * There are no failsafes for this. Any given argument will be accepted, even if it does not function as a targeting argument. + * If no argument is given, then will cycle through target modes in the following order: t, bt, stnpc + * Macro usage: /con ez target # OR /con ez target -showcurrent / show / current +#### showcurrent / show / current * Echoes the current elemental and targeting modes in the chat log. -** EX: //ez showcurrent -** Macro usage: /con ez showcurrent + * EX: //ez showcurrent + * Macro usage: /con ez show -boom # -* Casts a single target tier# nuke of the current element, and using the current targeting mode. -** EX: //ez boom 4 <<<< If Element Mode is Fire, and targeting mode is "t", you will cast Fire IV on your current target. -** EX2: //boom 6 <<<< If Element Mode is Ice, and targeting mode is "bt", you will cast Blizzard VI on the current battle target. -** Macro usage: /con ez boom # /OR/ /con boom # +#### boom XXX +* Casts a single target tierXXX nuke of the current element, and using the current targeting mode. + * EX: //ez boom 4 <<<< If Element Mode is Fire, and targeting mode is "t", you will cast Fire IV on your current target. + * EX2: //boom 6 <<<< If Element Mode is Ice, and targeting mode is "bt", you will cast Blizzard VI on the current battle target. + * Macro usage: /con ez boom # /OR/ /con boom # -boomga # -* Casts an area of effect nuke of tier#. BLM: -ga, -ga II, -ga III, -ja. (Also works for Curaga's while in Cure mode.) -** EX: //ez boomga 4 <<<< If Element Mode is Ice, and targeting mode is "t", will cast Blizzaja on your current target. -** EX2: //boomga 3 <<<< If Element Mode is Ice, and targeting mode is "bt", you will cast Blizzaga III on the current battle target. -** Macro usage: /con ez boomga # /OR/ /con boomga # +#### boomga XXX +* Casts an area of effect tierXXX nuke of the current element: BLM: -ga, -ga II, -ga III, -ja. (Also works for Curaga's while in Cure mode.) + * EX: //ez boomga 4 <<<< If Element Mode is Ice, and targeting mode is "t", will cast Blizzaja on your current target. + * EX2: //boomga 3 <<<< If Element Mode is Ice, and targeting mode is "bt", you will cast Blizzaga III on the current battle target. + * Macro usage: /con ez boomga # /OR/ /con boomga # -boomra # -* Casts an area of effect nuke of tier#. GEO's -ra AOE nukes and WHM's Cura line -** EX: //ez boomra 3 <<<< If Element Mode is Ice, and mode is "bt", will cast Blizzara III on your current battle target. -** EX2: //boomra 2 <<<< If Element Mode is Cure, and mode is "me", you will cast Cura II on yourself. -** Macro usage: /con ez boomra # /OR/ /con boomra # \ No newline at end of file +#### boomra XXX +* Casts an area of effect nuke of tier XXX. GEO's -ra AOE nukes and WHM's Cura line + * EX: //ez boomra 3 <<<< If Element Mode is Ice, and mode is "bt", will cast Blizzara III on your current battle target. + * EX2: //boomra 2 <<<< If Element Mode is Cure, and mode is "me", you will cast Cura II on yourself. + * Macro usage: /con ez boomra # /OR/ /con boomra # \ No newline at end of file From e3332930e5d2fa36384730a21ab35d2c505cba1a Mon Sep 17 00:00:00 2001 From: Chiaia Date: Wed, 4 Jul 2018 03:00:54 -0400 Subject: [PATCH 0177/1002] Fix for players --- addons/targetinfo/targetinfo.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/targetinfo/targetinfo.lua b/addons/targetinfo/targetinfo.lua index 038c641822..e8bbe23736 100644 --- a/addons/targetinfo/targetinfo.lua +++ b/addons/targetinfo/targetinfo.lua @@ -1,6 +1,6 @@ _addon.name = 'TargetInfo' _addon.author = 'Arcon' -_addon.version = '1.0.1.1' +_addon.version = '1.0.1.2' _addon.language = 'English' require('luau') @@ -68,7 +68,7 @@ windower.register_event('prerender', function() local mobclaim = windower.ffxi.get_mob_by_id(mob.claim_id) local target = windower.ffxi.get_mob_by_index(mob.target_index) local info = {} - info.hex = mob.id % 0x1000 + info.hex = mob.index info.full = mob.id local speed = (mob.status == 5 or mob.status == 85) and (100 * (mob.movement_speed / 4)):round(2) or (100 * (mob.movement_speed / 5 - 1)):round(2) info.speed = ( From 6bb6c70fbe55d5f78fe29acd587bf7ad16e9f6d0 Mon Sep 17 00:00:00 2001 From: funkworkz Date: Thu, 5 Jul 2018 09:12:42 -0500 Subject: [PATCH 0178/1002] Update setbgm.lua --- addons/setbgm/setbgm.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/setbgm/setbgm.lua b/addons/setbgm/setbgm.lua index 6e94b9ebb9..3b12db51fc 100644 --- a/addons/setbgm/setbgm.lua +++ b/addons/setbgm/setbgm.lua @@ -54,7 +54,7 @@ songs = { [50]='Feast of the Ladies', [51]='Abyssea - Scarlet Skies, Shadowed Plains', [52]='Melodies Errant', [53]='Shinryu', [54]='Everlasting Bonds', [55]='Provenance Watcher', [56]='Where it All Begins', [57]='Steel Sings, Blades Dance', [58]='A New Direction', [59]='The Pioneers', [60]='Into Lands Primeval - Ulbuka', [61]="Water's Umbral Knell", [62]='Keepers of the Wild', [63]='The Sacred City of Adoulin', [64]='Breaking Ground', [65]='Hades', [66]='Arciela', [67]='Mog Resort', [68]='Worlds Away', [69]="Distant Worlds (Nanaa Mihgo's version)", [70]='Monstrosity', [71]="The Pioneers (Nanaa Mihgo's version)", [72]='The Serpentine Labyrinth', [73]='The Divine', [74]='Clouds Over Ulbuka', [75]='The Price', [76]='Forever Today', [77]='Distant Worlds (Instrumental)', [78]='Forever Today (Instrumental)', [79]='Iroha', - [80]='The Boundless Black', [81]='Isle of the Gods', [82]='Wail of the Void', [83]="Rhapsodies of Vana'diel", [84]="Mount", [85]="Ambuscade", [86]="FFRK Shadow Lord", [87]="Omen", [88]="Dynamis Divergence", [89]="Unknown", + [80]='The Boundless Black', [81]='Isle of the Gods', [82]='Wail of the Void', [83]="Rhapsodies of Vana'diel", [84]="Mount", [85]="Ambuscade", [86]="FFRK Shadow Lord", [87]="Omen", [88]="Dynamis - Divergence", [89]="Dynamis - Divergence (Wave 3)", [101]='Battle Theme', [102]='Battle in the Dungeon #2', [103]='Battle Theme #2', [104]='A Road Once Traveled', [105]='Mhaura', [106]='Voyager', [107]="The Kingdom of San d'Oria", [108]="Vana'diel March", [109]='Ronfaure', [110]='The Grand Duchy of Jeuno', [111]='Blackout', [112]='Selbina', [113]='Sarutabaruta', [114]='Batallia Downs', [115]='Battle in the Dungeon', [116]='Gustaberg', [117]="Ru'Lude Gardens", [118]='Rolanberry Fields', [119]='Awakening', [120]="Vana'diel March #2", [121]='Shadow Lord', [122]='One Last Time', [123]='Hopelessness', [124]='Recollection', [125]='Tough Battle', [126]='Mog House', [127]='Anxiety', [128]='Airship', [129]='Hook, Line and Sinker', From bc411cf4445fbf201e1a98e7d5bf177db16c110a Mon Sep 17 00:00:00 2001 From: Byrth Date: Fri, 6 Jul 2018 22:06:03 -0400 Subject: [PATCH 0179/1002] slips.lua - Adjust for 2018-07-05 update --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 13a4d3e6f3..6b08fb1339 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757}, -- 191 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453,}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454,}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725}, -- 69 : Cornelia Statue is the last + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966}, -- 76 : Zanmato +1 is the last [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25589, 25762, 25763, 25810, 25811, 25869, 25870, 25935, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, }, --160 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330,}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665,}, --115 From 158e989f4c146f4b3b5ddbbf3f9a7a0ee33885d6 Mon Sep 17 00:00:00 2001 From: from20020516 Date: Fri, 13 Jul 2018 12:19:51 +0900 Subject: [PATCH 0180/1002] Fixes some equipments including line breaks. --- addons/checkparam/checkparam.lua | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua index 083a5e4281..8949f30d85 100644 --- a/addons/checkparam/checkparam.lua +++ b/addons/checkparam/checkparam.lua @@ -43,7 +43,7 @@ defaults = { BLM = 'magic attack bonus|magic burst damage|magic burst damage ii|int|magic accuracy|magic damage|fast cast|elemental magic casting time', RDM = 'magic attack bonus|magic burst damage|magic burst damage ii|magic accuracy|fast cast|enfeebling magic skill|enhancing magic skill|store tp|dual wield', THF = 'store tp|double attack|triple attack|quadruple attack|dual wield', - PLD = 'enmity|damage taken|physical damage taken|magic damage taken|spell inturruption rate|pharanx|cure potency|fastcast', + PLD = 'enmity|damage taken|physical damage taken|magic damage taken|spell interruption rate|phalanx|cure potency|fastcast', DRK = 'store tp|double attack|triple attack|quadruple attack|weapon skill damage', BST = 'pet: double attack|pet: magic attack bonus|pet: damage taken', BRD = 'all songs|song effect duration|fast cast|song spellcasting time', @@ -58,7 +58,7 @@ defaults = { DNC = 'store tp|double attack|triple attack|quadruple attack', SCH = 'magic attack bonus|magic burst damage|magic burst damage ii|magic accuracy|magic damage|fast cast|elemental magic casting time|cure potency|enh mag eff dur|enhancing magic effect duration', GEO = 'pet: regen|pet: damage taken|indicolure effect duration|indi eff dur|fast cast|magic evasion', - RUN = 'enmity|damage taken|physical damage taken|magic damage taken|spell inturruption rate|pharanx|inquartata|fastcast', + RUN = 'enmity|damage taken|physical damage taken|magic damage taken|spell interruption rate|phalanx|inquartata|fastcast', levelfilter = 99, } settings = config.load(defaults) @@ -197,6 +197,7 @@ integrate = { ['magic burst dmg'] = 'magic burst damage', ['mag dmg'] = 'magic damage', ['crithit rate'] = 'critical hit rate', + ['phys dmg taken'] = 'physical damage taken', } enhanced = { [10392] = 'cursna+10', --Malison Medallion @@ -207,6 +208,7 @@ enhanced = { [10790] = 'cursna+10', --Ephedra Ring [10791] = 'cursna+15', --Haoma's Ring [10802] = 'fast cast+5', --Majorelle Shield + [10806] = 'potency of cure effects received+15', --Adamas [10826] = 'fast cast+3', --Witful Belt [10838] = 'dual wield+5', --Patentia Sash [11000] = 'fast cast+3', --Swith Cape @@ -248,6 +250,9 @@ enhanced = { [21063] = 'divine benison+3', --Yagrush119+ [21078] = 'divine benison+3', --Yagrush119AG [21201] = 'fast cast+2', --Atinian Staff +1 + [27279] = 'physical damage taken-6', --Eri. Leg Guards + [27280] = 'physical damage taken-7', --Eri. Leg Guards +1 + [21699] = 'potency of cure effects received+10', --Nibiru Faussar [27768] = 'fast cast+5', --Cizin Helm [27775] = 'fast cast+10', --Nahtirah Hat [28054] = 'fast cast+7', --Gendewitha Gages @@ -256,6 +261,10 @@ enhanced = { [28197] = 'snapshot+9', --Nahtirah Trousers [28206] = 'fast cast+10', --Geomancy Pants [28335] = 'cursna+10', --Gende. Galoshes + [28459] = 'potency of cure effects received+5', --Chuq'aba Belt + [28484] = 'cure potency+3', --Nourish Earring + [28485] = 'cure potency+5', --Nourish Earring +1 + [28577] = 'potency of cure effects received+5', --Kunaji Ring [28582] = 'magic burst damage+5', --Locus Ring [28619] = 'cursna+15', --Mending Cape [28631] = 'elemental siphon+30', --Conveyance Cape From 5a2345f62e40170e17e10ffa0df307c359ccf2e1 Mon Sep 17 00:00:00 2001 From: from20020516 Date: Tue, 17 Jul 2018 17:36:25 +0900 Subject: [PATCH 0181/1002] fixes to clear table win_numbers. --- addons/Bonanza/Bonanza.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/Bonanza/Bonanza.lua b/addons/Bonanza/Bonanza.lua index 90d55bac7a..0508fea742 100644 --- a/addons/Bonanza/Bonanza.lua +++ b/addons/Bonanza/Bonanza.lua @@ -188,4 +188,5 @@ function scan_marbles() end end end + win_numbers = {} end From 50f954c28aa3f37a5a82ef79006f9d45af76fd9c Mon Sep 17 00:00:00 2001 From: Chiaia Date: Fri, 20 Jul 2018 07:34:04 -0400 Subject: [PATCH 0182/1002] Update rolltracker.lua --- addons/rolltracker/rolltracker.lua | 241 ++++++++++++++++------------- 1 file changed, 134 insertions(+), 107 deletions(-) diff --git a/addons/rolltracker/rolltracker.lua b/addons/rolltracker/rolltracker.lua index c7b3a4cdaf..ebaae5dbf4 100644 --- a/addons/rolltracker/rolltracker.lua +++ b/addons/rolltracker/rolltracker.lua @@ -25,9 +25,9 @@ --SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'RollTracker' -_addon.version = '1.7.0.0' +_addon.version = '1.8.0.0' _addon.author = 'Balloon' -_addon.command = 'rolltracker' +_addon.commands = {'rolltracker','rt'} require('luau') chat = require('chat') @@ -35,10 +35,11 @@ chars = require('chat.chars') packets = require('packets') defaults = {} -defaults.autostop = 0 +defaults.autostop = true defaults.bust = 1 defaults.effected = 1 defaults.fold = 1 +defaults.luckyinfo = true settings = config.load(defaults) @@ -46,31 +47,39 @@ windower.register_event('addon command',function (...) cmd = {...} if cmd[1] ~= nil then if cmd[1]:lower() == "help" then - print('To stop rolltracker stopping rolls type: //rolltracker autostop') - print('To restart rolltracker stopping doubleup type //rolltracker Doubleup') - end - - if cmd[1]:lower() == "autostop" then - override = true - print('Disabled Autostopping Double Up') + log('To toggle rolltracker from allowing/stopping rolls type: //rolltracker autostop') + elseif cmd[1]:lower() == "autostop" then + if settings.autostop then + settings.autostop = false + log('Will no longer stop Double-UP on a Lucky Roll.') + else + settings.autostop = true + log('Will stop Double-UP on a Lucky Roll.') + end + elseif cmd[1]:lower() == "luckyinfo" then + if settings.luckyinfo then + settings.luckyinfo = false + log('Lucky/Unlucky Info will no longer be displayed.') + else + settings.luckyinfo = true + log('Lucky/Unlucky Info will now be displayed.') + end end - - if cmd[1]:lower() == "doubleup" then - override = false - print('Enable Autostoppping Doubleup') - end + config.save(settings, 'all') end end) --This is done because GearSwap swaps out too fast, and sometimes things aren't reported in memory. --Therefore, we store it within rolltracker so we can do the check locally. --- Parsing: windower.register_event('incoming chunk', function(id, data) if id == 0x050 then local packet = packets.parse('incoming', data) local slot = windower.ffxi.get_items(packet['Inventory Bag'])[packet['Inventory Index']] gearTable[packet['Equipment Slot']] = slot ~= nil and slot.id or 0 - end + elseif id == 0x0DD then + local packetParty = packets.parse('incoming', data) + + end end) function getGear(slot) @@ -98,38 +107,38 @@ windower.register_event('load', function() p5 = string.char(0x1E, 6) } local rollInfoTemp = { - -- Okay, this goes 1-11 boost, Bust effect, Effect, Lucky, +1 Phantom Roll Effect, Bonus Equipment and Effect, - ['Chaos'] = {64,80,96,256,112,128,160,32,176,192,320,"-9.76", '% Attack!', 4, 32},--/1024 - ['Fighter\'s'] = {2,2,3,4,12,5,6,7,1,9,18,'-4','% Double-Attack!', 5, 1}, - ['Wizard\'s'] = {4,6,8,10,25,12,14,17,2,20,30, "-10", ' MAB', 5, 2}, - ['Evoker\'s'] = {1,1,1,1,3,2,2,2,1,3,4,'-1', ' Refresh!',5, 1}, - ['Rogue\'s'] = {2,2,3,4,12,5,6,6,1,8,14,'-6', '% Critical Hit Rate!', 5, 1}, - ['Corsair\'s'] = {10, 11, 11, 12, 20, 13, 15, 16, 8, 17, 24, '-6', '% Experience Bonus',5, 2}, - ['Hunter\'s'] = {10,13,15,40,18,20,25,5,28,30,50,'-15', ' Accuracy Bonus',4, 5}, - ['Magus\'s'] = {5,20,6,8,9,3,10,13,14,15,25,'-8',' Magic Defense Bonus',2, 2}, - ['Healer\'s'] = {3,4,12,5,6,7,1,8,9,10,16,'-4','% Cure Potency',3, 1}, - ['Drachen'] = {10,13,15,40,18,20,25,5,28,30,50,'0',' Pet: Accuracy Bonus',4, 5}, - ['Choral'] = {8,42,11,15,19,4,23,27,31,35,50,'+25', '- Spell Interruption Rate',2, 4}, - ['Monk\'s'] = {8,10,32,12,14,15,4,20,22,24,40,'-?', ' Subtle Blow', 3, 4}, - ['Beast'] = {6,8,9,25,11,13,16,3,17,19,31,'0', '% Pet: Attack Bonus',4, 3}, - ['Samurai'] = {7,32,10,12,14,4,16,20,22,24,40,'-10',' Store TP Bonus',2, 4}, - ['Warlock\'s'] = {2,3,4,12,5,6,7,1,8,9,15,'-5',' Magic Accuracy Bonus',4, 1}, - ['Puppet'] = {5,8,35,11,14,18,2,22,26,30,40,'-8',' Pet: Magic Attack Bonus',3, 3}, - ['Gallant\'s'] = {48,60,200,72,88,104,32,120,140,160,240,'-11.72','% Defense Bonus', 3, 24},--/1024 - ['Dancer\'s'] = {3,4,12,5,6,7,1,8,9,10,16,'-4',' Regen',3, 2}, - ['Bolter\'s'] = {0.3,0.3,0.8,0.4,0.4,0.5,0.5,0.6,0.2,0.7,1.0,'0','% Movement Speed',3, 0.2}, - ['Caster\'s'] = {6,15,7,8,9,10,5,11,12,13,20,'-10','% Fast Cast',2, 3,{7, 11140, 27269, 27269, 10}}, - ['Tactician\'s'] = {10,10,10,10,30,10,10,0,20,20,40,'-10',' Regain',5, 2, {5, 11100, 26930, 26931, 10}}, - ['Miser\'s'] = {30,50,70,90,200,110,20,130,150,170,250,'0',' Save TP',5, 15}, - ['Ninja'] = {10,13,15,40,18,20,25,5,28,30,50,'-15',' Evasion Bonus',4, 5}, - ['Scholar\'s'] = {'?','?','?','?','?','?','?','?','?','?','?','?',' Conserve MP',2, 0}, - ['Allies\''] = {6,7,17,9,11,13,15,17,17,5,17,'?','% Skillchain Damage',3, 1,{6,11120, 27084, 27085, 5}}, - ['Companion\'s'] = {{4,20},{20,50},{6,20},{8,20},{10,30},{12,30},{14,30},{16,40},{18,40},{3,10},{25,60},'0',' Pet: Regen/Regain',2, {2,5}}, - ['Avenger\'s'] = {'?','?','?','?','?','?','?','?','?','?','?','?',' Counter Rate',4, 0}, - ['Blitzer\'s'] = {2,3.4,4.5,11.3,5.3,6.4,7.2,8.3,1.5,10.2,12.1,'-?', '% Attack delay reduction',4, 1, {4,11080, 26772, 26773, 5}}, - ['Courser\'s'] = {'?','?','?','?','?','?','?','?','?','?','?','?',' Snapshot',3, 0}, --11160, 27443, 27444 - ['Runeist\'s'] = {'?','?','?','?','?','?','?','?','?','?','?','?',' Magic Evasion',4, 0}, - ['Naturalist\'s'] = {6,7,15,8,9,10,5,11,12,13,20,'-5','% Enhancing Magic Duration',3, 1} + -- Okay, this goes 1-11 boost, Bust effect, Effect, Lucky, Unlucky, +1 Phantom Roll Effect, Job Bonus, Bonus Equipment and Effect, + ['Allies\''] = {6,7,17,9,11,13,15,17,17,5,17,'?','% Skillchain Damage',3,10, 1,{nil,0},{6,11120, 27084, 27085, 5}},--Needs Eval + ['Avenger\'s'] = {'?','?','?','?','?','?','?','?','?','?','?','?',' Counter Rate',4,8, 0,{nil,0}}, + ['Beast'] = {64,80,96,256,112,128,160,32,176,192,320,'0','% Pet: Attack Bonus',4,8, 32,{'bst',100}},--/1024 Confirmed + ['Blitzer\'s'] = {2,3.4,4.5,11.3,5.3,6.4,7.2,8.3,1.5,10.2,12.1,'-3','% Attack delay reduction',4,9, 1,{nil,0},{4,11080, 26772, 26773, 5}},--Limited Testing for Bust, Needs more data for sure probably /1024 + ['Bolter\'s'] = {0.3,0.3,0.8,0.4,0.4,0.5,0.5,0.6,0.2,0.7,1.0,'0','% Movement Speed',3,9, 0.2,{nil,0}}, + ['Caster\'s'] = {6,15,7,8,9,10,5,11,12,13,20,'-10','% Fast Cast',2,7, 3,{nil,0},{7, 11140, 27269, 27269, 10}}, + ['Chaos'] = {64,80,96,256,112,128,160,32,176,192,320,"-9.76",'% Attack!', 4,8, 32,{'drk',100}},--/1024 Confirmed + ['Choral'] = {8,42,11,15,19,4,23,27,31,35,50,'+25','- Spell Interruption Rate',2,6, 4,{'brd',25}},--SE listed Values and hell if I'm testing this + ['Companion\'s'] = {{4,20},{20,50},{6,20},{8,20},{10,30},{12,30},{14,30},{16,40},{18,40},{3,10},{25,60},'0',' Pet: Regen/Regain',2,10, {2,5},{nil,0}}, + ['Corsair\'s'] = {10, 11, 11, 12, 20, 13, 15, 16, 8, 17, 24,'-6','% Experience Bonus',5,9, 2,{'cor',5}},--Needs Eval on Bust/Job Bonus + ['Courser\'s'] = {'?','?','?','?','?','?','?','?','?','?','?','?',' Snapshot',3,9, 0,{nil,0}}, --11160, 27443, 27444 + ['Dancer\'s'] = {3,4,12,5,6,7,1,8,9,10,16,'-4',' Regen',3,7, 2,{'dnc',4}},--Confirmed + ['Drachen'] = {10,13,15,40,18,20,25,5,28,30,50,'0',' Pet: Accuracy Bonus',4,8, 5,{'drg',15}},--Confirmed + ['Evoker\'s'] = {1,1,1,1,3,2,2,2,1,3,4,'-1',' Refresh!',5,9, 1,{'smn',1}},--Confirmed + ['Fighter\'s'] = {2,2,3,4,12,5,6,7,1,9,18,'-4','% Double-Attack!',5,9, 1,{'war',5}}, + ['Gallant\'s'] = {48,60,200,72,88,104,32,120,140,160,240,'-11.72','% Defense Bonus',3,7, 24,{'pld',120}},--/1024 Confirmed + ['Healer\'s'] = {3,4,12,5,6,7,1,8,9,10,16,'-4','% Cure Potency Received',3,7, 1,{'whm',4}},--Confirmed + ['Hunter\'s'] = {10,13,15,40,18,20,25,5,28,30,50,'-15',' Accuracy Bonus',4,8, 5,{'rng',15}},--Confirmed + ['Magus\'s'] = {5,20,6,8,9,3,10,13,14,15,25,'-8',' Magic Defense Bonus',2,6, 2,{'blu',8}}, + ['Miser\'s'] = {30,50,70,90,200,110,20,130,150,170,250,'0',' Save TP',5,7, 15,{nil,0}}, + ['Monk\'s'] = {8,10,32,12,14,15,4,20,22,24,40,'-?',' Subtle Blow', 3,7, 4,{'mnk',10}}, + ['Naturalist\'s'] = {6,7,15,8,9,10,5,11,12,13,20,'-5','% Enhancing Magic Duration',3,7, 1,{'geo',5}},--Confirmed + ['Ninja'] = {10,13,15,40,18,20,25,5,28,30,50,'-15',' Evasion Bonus',4,8, 5,{'nin',15}},--Confirmed + ['Puppet'] = {5,8,35,11,14,18,2,22,26,30,40,'-8',' Pet: MAB/MAcc',3,7, 3,{'pup',12}}, + ['Rogue\'s'] = {2,2,3,4,12,5,6,6,1,8,14,'-6','% Critical Hit Rate!',5,9, 1,{'thf',5}}, + ['Runeist\'s'] = {10,13,15,40,18,20,25,5,28,30,50,'-15',' Evasion Bonus',4,8, 5,{'run',15}},--Needs Eval + ['Samurai'] = {8,32,10,12,14,4,16,20,22,24,40,'-10',' Store TP Bonus',2,6, 4,{'sam',10}},--Confirmed 1(Was bad),2,3,4,5,6,7,8,11 (I Wing Test) + ['Scholar\'s'] = {2,10,3,4,4,1,5,6,7,7,12,'-3','% Conserve MP',2,6, 1,{'sch',3}}, --Needs Eval Source ATM: JP Wiki + ['Tactician\'s'] = {10,10,10,10,30,10,10,0,20,20,40,'-10',' Regain',5,8, 2,{nil,0},{5, 11100, 26930, 26931, 10}},--Confirmed + ['Warlock\'s'] = {10,13,15,40,18,20,25,5,28,30,50,'-15',' Magic Accuracy Bonus',4,8, 5,{'rdm',15}},-- + ['Wizard\'s'] = {4,6,8,10,25,12,14,17,2,20,30, "-10",' MAB',5,9, 2,{'blm',10}}, } rollInfo = {} @@ -138,13 +147,11 @@ windower.register_event('load', function() end settings = config.load(defaults) - --Wanted to change this to true/false in config file, but it wouldn't update to everyone -- This is an inelegant solution. - override = settings.autostop == 1 and true or false end) windower.register_event('load', 'login', function() isLucky = false - ringBonus = false + rollPlusBonus = false lastRoll = 0 player = windower.ffxi.get_player() end) @@ -155,16 +162,11 @@ windower.register_event('incoming text', function(old, new, color) return true end - --Hides normal + --Hides Vanilla if old:match('.* receives the effect of .* Roll.') ~= nil then return true end - --Hides Older Battlemod versions --Antiquated - if old:match('%('..'%w+'..'%).* Roll ') then - new = old - end - return new, color end) @@ -175,8 +177,7 @@ windower.register_event('action', function(act) rollActor = act.actor_id local rollID = act.param local rollNum = act.targets[1].actions[1].param - - + -- anonymous function that checks if the player.id is in the targets without wrapping it in another layer of for loops. if function(act) @@ -207,13 +208,17 @@ windower.register_event('action', function(act) isLucky = false if rollNum == rollInfo[rollID][15] or rollNum == 11 then isLucky = true + log('Lucky roll') luckChat = string.char(31,158).." (Lucky!)" + elseif rollNum == rollInfo[rollID][16] then + luckChat = string.char(31,167).." (Unlucky!)" end + if rollNum == 12 and #rollMembers > 0 then windower.add_to_chat(1, string.char(31,167)..amountHit..'Bust! '..chat.controls.reset..chars.implies..' '..membersHit..' '..chars.implies..' ('..rollInfo[rollID][rollNum+1]..rollInfo[rollID][14]..')') else - windower.add_to_chat(1, amountHit..membersHit..chat.controls.reset..' '..chars.implies..' '..rollInfo[rollID][1]..' Roll '..chars['circle' .. rollNum]..luckChat..string.char(31,13)..' (+'..rollBonus..')'..BustRate(rollNum, id)) + windower.add_to_chat(1, amountHit..membersHit..chat.controls.reset..' '..chars.implies..' '..rollInfo[rollID][1]..' Roll '..chars['circle' .. rollNum]..luckChat..string.char(31,13)..' (+'..rollBonus..')'..BustRate(rollNum, rollActor)..ReportRollInfo(rollID, rollActor)) end end end @@ -231,68 +236,75 @@ function RollEffect(rollid, rollnum) if lastRoll ~= rollid then lastRoll = rollid - ringBonus = false + rollPlusBonus = false gearBonus = false + jobBonus = false end - --I'm handling one roll a bit odd, so I need to deal with it seperately. - --Which is stupid, I know, but look at how I've done most of this + --I'm handling one roll a bit odd, so I need to deal with it separately. + --Which is stupid, I know, but look at how I've done most of this. if rollName == "Companion\'s" then local hpVal = rollVal[1] local tpVal = rollVal[2] - if gearTable[9] == 26038 or ringBonus then - hpVal = hpVal + (rollInfo[rollid][16][1]*7) - tpVal = tpVal + (rollInfo[rollid][16][2]*7) - ringBonus = true - elseif gearTable[13] == 28548 or gearTable[14]== 28548 or ringBonus then - hpVal = hpVal + (rollInfo[rollid][16][1]*5) - tpVal = tpVal + (rollInfo[rollid][16][2]*5) - ringBonus = true - elseif gearTable[13] == 28547 or gearTable[14] == 28547 or ringBonus then - hpVal = hpVal + (rollInfo[rollid][16][1]*3) - tpVal = tpVal + (rollInfo[rollid][16][2]*3) - ringBonus = true + if gearTable[9] == 26038 or rollPlusBonus then + hpVal = hpVal + (rollInfo[rollid][17][1]*7) + tpVal = tpVal + (rollInfo[rollid][17][2]*7) + rollPlusBonus = true + elseif gearTable[13] == 28548 or gearTable[14]== 28548 or rollPlusBonus then + hpVal = hpVal + (rollInfo[rollid][17][1]*5) + tpVal = tpVal + (rollInfo[rollid][17][2]*5) + rollPlusBonus = true + elseif gearTable[13] == 28547 or gearTable[14] == 28547 or rollPlusBonus then + hpVal = hpVal + (rollInfo[rollid][17][1]*3) + tpVal = tpVal + (rollInfo[rollid][17][2]*3) + rollPlusBonus = true end return "Pet:"..hpVal.." Regen".." +"..tpVal.." Regain" end --If there's no Roll Val can't add to it if rollVal ~= '?' then - if gearTable[9] == 26038 or ringBonus then - rollVal = rollVal + (rollInfo[rollid][16]*7) - ringBonus = true - elseif gearTable[13] == 28548 or gearTable[14] == 28548 or ringBonus then - rollVal = rollVal + (rollInfo[rollid][16]*5) - ringBonus = true - elseif gearTable[13] == 28547 or gearTable[14] == 28547 or ringBonus then - rollVal = rollVal + (rollInfo[rollid][16]*3) - ringBonus = true + if gearTable[9] == 26038 or rollPlusBonus then + rollVal = rollVal + (rollInfo[rollid][17]*7) + rollPlusBonus = true + elseif gearTable[13] == 28548 or gearTable[14] == 28548 or rollPlusBonus then + rollVal = rollVal + (rollInfo[rollid][17]*5) + rollPlusBonus = true + elseif gearTable[13] == 28547 or gearTable[14] == 28547 or rollPlusBonus then + rollVal = rollVal + (rollInfo[rollid][17]*3) + rollPlusBonus = true + end + end + + --Handle Job Bonus + if (rollInfo[rollid][18][1] ~= nil) then + --Add Job is in party check + if jobBonus then + rollVal = rollVal + rollInfo[rollid][18][2] + else + jobBonus = true + rollVal = rollVal + rollInfo[rollid][18][2] end end --Handle Emp +2, 109 and 119 gear bonus - if(rollInfo[rollid][17] ~= nil) then - local bonusVal = gearTable[rollInfo[rollid][17][1]] == rollInfo[rollid][17][2] or gearTable[rollInfo[rollid][17][1]] == rollInfo[rollid][17][3] or gearTable[rollInfo[rollid][17][1]] == rollInfo[rollid][17][4] and rollInfo[rollid][17][5] or 0 + if (rollInfo[rollid][19] ~= nil) then + local bonusVal = (gearTable[rollInfo[rollid][19][1]] == rollInfo[rollid][19][2] or gearTable[rollInfo[rollid][19][1]] == rollInfo[rollid][19][3] or gearTable[rollInfo[rollid][19][1]] == rollInfo[rollid][19][4]) and rollInfo[rollid][19][5] or 0 if gearBonus == true then - rollVal = rollVal + rollInfo[rollid][17][5] - else + rollVal = rollVal + rollInfo[rollid][19][5] + else gearBonus = true rollVal = rollVal + bonusVal end - end + end - -- Convert Bolters to Movement Speed based on 5.0 being 100% - if(rollName == "Bolter\'s") then + -- Convert Bolter's to Movement Speed based on 5.0 being 100% + if (rollName == "Bolter\'s") then rollVal = '%.0f':format(100*((5+rollVal) / 5 - 1)) end - --Convert Chaos to % with 2 decimials - if(rollName == "Chaos") then - rollVal = '%.2f':format(rollVal/1024 * 100) - end - - --Convert Gallant's to % with 2 decimials - if(rollName == "Gallant\'s") then + --Convert Beast/Chaos/Gallant's to % with 2 decimals + if (rollName == "Chaos") or (rollName == "Gallant\'s") or (rollName == "Beast") then rollVal = '%.2f':format(rollVal/1024 * 100) end @@ -300,26 +312,41 @@ function RollEffect(rollid, rollnum) end -function BustRate(num, rollerID) - if num <= 5 or num == 11 or rollerID ~= player.id or settings.bust == 0 then +function BustRate(rollNum, rollActor) + if rollNum <= 5 or rollNum == 11 or rollActor ~= player.id or settings.bust == 0 then return '' end - return '\7 [Chance to Bust]: ' .. '%.1f':format((num-5)*16.67) .. '%' + return '\7 [Chance to Bust]: ' .. '%.1f':format((rollNum-5)*16.67) .. '%' +end + +--Display Lucky/Unlucky #s and check if it's already been reported once. +reportedOnce = false +function ReportRollInfo(rollID, rollActor) + if rollActor ~= player.id or not settings.luckyinfo then + return '' + elseif reportedOnce then + reportedOnce = false + return '' + else + reportedOnce = true + return '\7 '..rollInfo[rollID][1]..' Roll\'s Lucky #: ' ..rollInfo[rollID][15]..' Unlucky #: '..rollInfo[rollID][16] + end end --Checks to see if the below event has ran more than twice to enable busting ranMultiple = false windower.register_event('outgoing text', function(original, modified) + cleaned = windower.convert_auto_trans(original) modified = original - if original:match('/jobability \"Double.*Up') then - if isLucky and not override and rollActor == player.id then + if cleaned:match('/jobability \"?Double.*Up') or cleaned:match('/ja \"?Double.*Up') then + if isLucky and settings.autostop and rollActor == player.id then windower.add_to_chat(159,'Attempting to Doubleup on a Lucky Roll: Re-double up to continue.') isLucky = false modified = "" end end - - if settings.fold == 1 and original:match('/jobability \"Fold') then + + if settings.fold == 1 and (cleaned:match('/jobability \"?Fold') or cleaned:match('/ja \"?Fold')) then local count = 0 local canBust = false @@ -327,7 +354,7 @@ windower.register_event('outgoing text', function(original, modified) local cor_buffs = S(player.buffs) * buffId canBust = cor_buffs:contains(res.buffs:with('name', 'Bust').id) or cor_buffs:length() > 1 if canBust or ranMultiple then - modified = original + modified = cleaned ranMultiple = false else windower.add_to_chat(159, 'No \'Bust\'. Fold again to continue.') From 846ae0ef737bc6b657b8e71ee73745aad5415e89 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Fri, 27 Jul 2018 05:59:18 +0200 Subject: [PATCH 0183/1002] Yush: Fixed file lookup --- addons/Yush/Yush.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/Yush/Yush.lua b/addons/Yush/Yush.lua index 78ac383f72..a4329dd087 100644 --- a/addons/Yush/Yush.lua +++ b/addons/Yush/Yush.lua @@ -1,5 +1,5 @@ _addon.author = 'Arcon' -_addon.version = '2.1.1.0' +_addon.version = '2.1.1.1' _addon.language = 'English' _addon.command = 'yush' @@ -156,7 +156,7 @@ windower.register_event('load', 'login', 'job change', 'logout', function() end if not file then - path = 'Binds' + path = 'binds.lua' file = loadfile(basepath .. path) end From 682c149ab71f98d802c498d6250d5f0e85b62771 Mon Sep 17 00:00:00 2001 From: joshk6656 Date: Fri, 27 Jul 2018 18:32:25 -0500 Subject: [PATCH 0184/1002] Fix multiple _unknown2's in use item. --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index a8de30a672..b8094a4fe7 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -445,7 +445,7 @@ fields.outgoing[0x037] = L{ {ctype='unsigned char', label='Slot', fn=inv+{0}}, -- 0E {ctype='unsigned char', label='_unknown2'}, -- 0F Takes values {ctype='unsigned char', label='Bag', fn=bag}, -- 10 - {ctype='data[3]', label='_unknown2'} -- 11 + {ctype='data[3]', label='_unknown3'} -- 11 } -- Sort Item From 5649df6d4d4fac66a101d5a71c79d03f7c49c745 Mon Sep 17 00:00:00 2001 From: Nifim Date: Mon, 30 Jul 2018 17:30:04 -0700 Subject: [PATCH 0185/1002] Add owners name to pets add actor's owners_name to action text for pets. --- addons/battlemod/battlemod.lua | 4 ++-- addons/battlemod/parse_action_packet.lua | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index e5e18b7c46..75730475dc 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -317,9 +317,9 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec skill = 'like level '..am.param_1..' ('..ratings_arr[am.param_2-63]..')' end end - + local outstr = (res.action_messages[am.message_id][language] - :gsub('$\123actor\125',color_it(actor.name or '',color_arr[actor.owner or actor.type])) + :gsub('$\123actor\125',color_it((actor.name or '') .. (actor.owner_name and '('..actor.owner_name..')') or "",color_arr[actor.owner or actor.type])) :gsub('$\123status\125',status or '') :gsub('$\123item\125',color_it(item or '',color_arr.itemcol)) :gsub('$\123target\125',color_it(target.name or '',color_arr[target.owner or target.type])) diff --git a/addons/battlemod/parse_action_packet.lua b/addons/battlemod/parse_action_packet.lua index 4200b1e589..daca1850ef 100644 --- a/addons/battlemod/parse_action_packet.lua +++ b/addons/battlemod/parse_action_packet.lua @@ -241,7 +241,7 @@ function parse_action_packet(act) :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 or 'ERROR 116') - :gsub('${actor}',color_it(act.actor.name or 'ERROR 117',color_arr[act.actor.owner or act.actor.type])) + :gsub('${actor}',color_it((act.actor.name or 'ERROR 117' ) .. (act.actor.owner_name and '('..act.actor.owner_name..')') or "" ,color_arr[act.actor.owner or act.actor.type])) :gsub('${target}',targ) :gsub('${lb}','\7') :gsub('${number}',act.action.number or m.param) @@ -411,10 +411,10 @@ end function player_info(id) local player_table = windower.ffxi.get_mob_by_id(id) - local typ,owner,filt + local typ,owner,filt,owner_name if player_table == nil then - return {name=nil,id=nil,is_npc=nil,type='debug',owner=nil,race=nil} + 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 @@ -443,6 +443,7 @@ function player_info(id) filt = 'my_pet' end owner = i + owner_name = v.mob.name 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 @@ -450,6 +451,7 @@ function player_info(id) filt = 'my_fellow' end owner = i + owner_name = v.mob.name break end end @@ -483,7 +485,7 @@ function player_info(id) end end if not typ then typ = 'debug' end - return {name=player_table.name,id=id,is_npc = player_table.is_npc,type=typ,filter=filt,owner=(owner or nil),race = player_table.race} + return {name=player_table.name,id=id,is_npc = player_table.is_npc,type=typ,filter=filt,owner=(owner or nil), owner_name=(owner_name or nil),race = player_table.race} end function get_spell(act) From b30af6b3d97a7c3948989722e69170542bcd326d Mon Sep 17 00:00:00 2001 From: Nifim Date: Mon, 30 Jul 2018 20:03:06 -0700 Subject: [PATCH 0186/1002] Added Setting, Corrected Pet check Added a setting for showing owners names, it is false by defualt. Changed pet check to use index and allow all indexes greater then 1791 --- addons/battlemod/battlemod.lua | 3 +-- addons/battlemod/parse_action_packet.lua | 8 ++++---- addons/battlemod/statics.lua | 1 + 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index 75730475dc..3c77491257 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -317,9 +317,8 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec skill = 'like level '..am.param_1..' ('..ratings_arr[am.param_2-63]..')' end end - local outstr = (res.action_messages[am.message_id][language] - :gsub('$\123actor\125',color_it((actor.name or '') .. (actor.owner_name and '('..actor.owner_name..')') or "",color_arr[actor.owner or actor.type])) + :gsub('$\123actor\125',color_it((actor.name or '') .. (actor.owner_name or ""),color_arr[actor.owner or actor.type])) :gsub('$\123status\125',status or '') :gsub('$\123item\125',color_it(item or '',color_arr.itemcol)) :gsub('$\123target\125',color_it(target.name or '',color_arr[target.owner or target.type])) diff --git a/addons/battlemod/parse_action_packet.lua b/addons/battlemod/parse_action_packet.lua index daca1850ef..ee3756d49a 100644 --- a/addons/battlemod/parse_action_packet.lua +++ b/addons/battlemod/parse_action_packet.lua @@ -241,7 +241,7 @@ function parse_action_packet(act) :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 or 'ERROR 116') - :gsub('${actor}',color_it((act.actor.name or 'ERROR 117' ) .. (act.actor.owner_name and '('..act.actor.owner_name..')') or "" ,color_arr[act.actor.owner or act.actor.type])) + :gsub('${actor}',color_it((act.actor.name or 'ERROR 117' ) .. (act.actor.owner_name or "") ,color_arr[act.actor.owner or act.actor.type])) :gsub('${target}',targ) :gsub('${lb}','\7') :gsub('${number}',act.action.number or m.param) @@ -432,7 +432,7 @@ function player_info(id) if not filt then if player_table.is_npc then - if player_table.id%4096>2047 then + if player_table.index>1791 then typ = 'other_pets' filt = 'other_pets' owner = 'other' @@ -443,7 +443,7 @@ function player_info(id) filt = 'my_pet' end owner = i - owner_name = v.mob.name + owner_name = showownernames and '(' .. v.mob.name .. ')' 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 @@ -451,7 +451,7 @@ function player_info(id) filt = 'my_fellow' end owner = i - owner_name = v.mob.name + owner_name = showownernames and '(' .. v.mob.name .. ')' break end end diff --git a/addons/battlemod/statics.lua b/addons/battlemod/statics.lua index 7acf2ac55a..ffe54e6ca6 100644 --- a/addons/battlemod/statics.lua +++ b/addons/battlemod/statics.lua @@ -506,6 +506,7 @@ default_settings = [[ false true true + false AOE ${numb} ]]..string.char(129,168)..[[ ${target} ${actor} ${abil} ]]..string.char(129,168)..[[ ${target} (${status}) [${actor}] ${numb} ${abil} ]]..string.char(129,168)..[[ ${target} From 8607c1f88df94cbffda91fbf9348e4ffb36cdda0 Mon Sep 17 00:00:00 2001 From: Nifim Date: Mon, 30 Jul 2018 20:04:38 -0700 Subject: [PATCH 0187/1002] Update version increment version --- addons/battlemod/battlemod.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index 3c77491257..2af118c68d 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -12,7 +12,7 @@ require 'generic_helpers' require 'parse_action_packet' require 'statics' -_addon.version = '3.23' +_addon.version = '3.24' _addon.name = 'BattleMod' _addon.author = 'Byrth, maintainer: SnickySnacks' _addon.commands = {'bm','battlemod'} From b188c67171b348f51254cf92850e1fae51a8c5cd Mon Sep 17 00:00:00 2001 From: Chiaia Date: Sat, 4 Aug 2018 04:03:33 -0400 Subject: [PATCH 0188/1002] Update rolltracker.lua --- addons/rolltracker/rolltracker.lua | 53 +++++++++++++++--------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/addons/rolltracker/rolltracker.lua b/addons/rolltracker/rolltracker.lua index ebaae5dbf4..a314fc05f6 100644 --- a/addons/rolltracker/rolltracker.lua +++ b/addons/rolltracker/rolltracker.lua @@ -35,7 +35,7 @@ chars = require('chat.chars') packets = require('packets') defaults = {} -defaults.autostop = true +defaults.autostopper = true defaults.bust = 1 defaults.effected = 1 defaults.fold = 1 @@ -47,13 +47,14 @@ windower.register_event('addon command',function (...) cmd = {...} if cmd[1] ~= nil then if cmd[1]:lower() == "help" then - log('To toggle rolltracker from allowing/stopping rolls type: //rolltracker autostop') - elseif cmd[1]:lower() == "autostop" then - if settings.autostop then - settings.autostop = false + log('To toggle rolltracker from allowing/stopping rolls type: //rolltracker autostopper') + log('To toggle rolltracker from showing/hiding Lucky Info type: //rolltracker luckyinfo') + elseif cmd[1]:lower() == "autostopper" then + if settings.autostopper then + settings.autostopper = false log('Will no longer stop Double-UP on a Lucky Roll.') else - settings.autostop = true + settings.autostopper = true log('Will stop Double-UP on a Lucky Roll.') end elseif cmd[1]:lower() == "luckyinfo" then @@ -71,7 +72,7 @@ end) --This is done because GearSwap swaps out too fast, and sometimes things aren't reported in memory. --Therefore, we store it within rolltracker so we can do the check locally. -windower.register_event('incoming chunk', function(id, data) +windower.register_event('incoming chunk', function(id, data) if id == 0x050 then local packet = packets.parse('incoming', data) local slot = windower.ffxi.get_items(packet['Inventory Bag'])[packet['Inventory Index']] @@ -89,7 +90,7 @@ end windower.register_event('load', function() - --We need a gear table, and we need to initialise it when we load + --We need a gear table, and we need to initialise it when we load --So that if someone doesn't swap gear, at least it still works. gearTable = { [0]=getGear('main'),[1]=getGear('sub'),[2]=getGear('range'),[3]=getGear('ammo'), @@ -145,7 +146,7 @@ windower.register_event('load', function() for key, val in pairs(rollInfoTemp) do rollInfo[res.job_abilities:with('english', key .. ' Roll').id] = {key, unpack(val)} end - + settings = config.load(defaults) end) @@ -177,11 +178,11 @@ windower.register_event('action', function(act) rollActor = act.actor_id local rollID = act.param local rollNum = act.targets[1].actions[1].param - + -- anonymous function that checks if the player.id is in the targets without wrapping it in another layer of for loops. - if + if function(act) - for i = 1, #act.targets do + for i = 1, #act.targets do if act.targets[i].id == player.id then return true end @@ -194,7 +195,7 @@ windower.register_event('action', function(act) for partyMem in pairs(party) do for effectedTarget = 1, #act.targets do --if mob is nil then the party member is not in zone, will fire an error. - if type(party[partyMem]) == 'table' and party[partyMem].mob and act.targets[effectedTarget].id == party[partyMem].mob.id then + if type(party[partyMem]) == 'table' and party[partyMem].mob and act.targets[effectedTarget].id == party[partyMem].mob.id then rollMembers[effectedTarget] = partyColour[partyMem] .. party[partyMem].name .. chat.controls.reset end end @@ -202,18 +203,18 @@ windower.register_event('action', function(act) local membersHit = table.concat(rollMembers, ', ') --fake 'ternary' assignment. if settings.effected is 1 then it'll show numbers, otherwise it won't. - local amountHit = settings.effected == 1 and '[' .. #rollMembers .. '] ' or '' + local amountHit = settings.effected == 1 and '[' .. #rollMembers .. '] ' or '' local rollBonus = RollEffect(rollID, rollNum+1) local luckChat = '' isLucky = false - if rollNum == rollInfo[rollID][15] or rollNum == 11 then + if rollNum == rollInfo[rollID][15] or rollNum == 11 then isLucky = true - log('Lucky roll') + windower.add_to_chat(158,'Lucky roll!') luckChat = string.char(31,158).." (Lucky!)" - elseif rollNum == rollInfo[rollID][16] then + elseif rollNum == rollInfo[rollID][16] then luckChat = string.char(31,167).." (Unlucky!)" end - + if rollNum == 12 and #rollMembers > 0 then windower.add_to_chat(1, string.char(31,167)..amountHit..'Bust! '..chat.controls.reset..chars.implies..' '..membersHit..' '..chars.implies..' ('..rollInfo[rollID][rollNum+1]..rollInfo[rollID][14]..')') @@ -233,8 +234,8 @@ function RollEffect(rollid, rollnum) --There's gotta be a better way to do this. local rollName = rollInfo[rollid][1] local rollVal = rollInfo[rollid][rollnum] - - if lastRoll ~= rollid then + + if lastRoll ~= rollid then lastRoll = rollid rollPlusBonus = false gearBonus = false @@ -259,7 +260,7 @@ function RollEffect(rollid, rollnum) tpVal = tpVal + (rollInfo[rollid][17][2]*3) rollPlusBonus = true end - return "Pet:"..hpVal.." Regen".." +"..tpVal.." Regain" + return "Pet:"..hpVal.." Regen".." +"..tpVal.." Regain" end --If there's no Roll Val can't add to it @@ -297,12 +298,12 @@ function RollEffect(rollid, rollnum) rollVal = rollVal + bonusVal end end - + -- Convert Bolter's to Movement Speed based on 5.0 being 100% if (rollName == "Bolter\'s") then rollVal = '%.0f':format(100*((5+rollVal) / 5 - 1)) end - + --Convert Beast/Chaos/Gallant's to % with 2 decimals if (rollName == "Chaos") or (rollName == "Gallant\'s") or (rollName == "Beast") then rollVal = '%.2f':format(rollVal/1024 * 100) @@ -339,7 +340,7 @@ windower.register_event('outgoing text', function(original, modified) cleaned = windower.convert_auto_trans(original) modified = original if cleaned:match('/jobability \"?Double.*Up') or cleaned:match('/ja \"?Double.*Up') then - if isLucky and settings.autostop and rollActor == player.id then + if isLucky and settings.autostopper and rollActor == player.id then windower.add_to_chat(159,'Attempting to Doubleup on a Lucky Roll: Re-double up to continue.') isLucky = false modified = "" @@ -361,9 +362,9 @@ windower.register_event('outgoing text', function(original, modified) ranMultiple = true modified = "" end - + return modified end return modified - + end) From 7113dc68c52bb91daaaab0296758713801c500f1 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Sat, 4 Aug 2018 04:04:48 -0400 Subject: [PATCH 0189/1002] Update rolltracker.lua --- addons/rolltracker/rolltracker.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/rolltracker/rolltracker.lua b/addons/rolltracker/rolltracker.lua index a314fc05f6..b688d09ddf 100644 --- a/addons/rolltracker/rolltracker.lua +++ b/addons/rolltracker/rolltracker.lua @@ -47,9 +47,9 @@ windower.register_event('addon command',function (...) cmd = {...} if cmd[1] ~= nil then if cmd[1]:lower() == "help" then - log('To toggle rolltracker from allowing/stopping rolls type: //rolltracker autostopper') + log('To toggle rolltracker from allowing/stopping rolls type: //rolltracker autostop') log('To toggle rolltracker from showing/hiding Lucky Info type: //rolltracker luckyinfo') - elseif cmd[1]:lower() == "autostopper" then + elseif cmd[1]:lower() == "autostop" then if settings.autostopper then settings.autostopper = false log('Will no longer stop Double-UP on a Lucky Roll.') From d0a4fa6b9a4494b9b7722e55fd2bb0ecbff5bc67 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Sat, 4 Aug 2018 04:24:16 -0400 Subject: [PATCH 0190/1002] Update readme.md --- addons/rolltracker/readme.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/addons/rolltracker/readme.md b/addons/rolltracker/readme.md index ba7dbfc67f..631cac540d 100644 --- a/addons/rolltracker/readme.md +++ b/addons/rolltracker/readme.md @@ -1 +1,20 @@ -Author: Balloon(Cerberus) Roll Tracker, for COR This addon instantly displays your roll number, it's effect, and whether the roll is lucky or not. (As opposed to the 5 second delay you find with the chatlog. If you have rolled a lucky roll, it will also prompt you and automatically stop you from doubling up on it (which can be bypassed by either doubling up again, or typing //rolltracker autostop Enjoy. +Author: Balloon(Cerberus) + +Roll Tracker, for COR + +This addon instantly displays your roll number, it's effect, and whether the roll is lucky or not. (As opposed to the 5 second delay you find with the chatlog. + +If you have rolled a lucky roll, it will also prompt you and automatically stop you from doubling up on it (which can be bypassed by either doubling up again, or typing //rolltracker autostop. This currently doesn't work if you are also using Gearswap. + +To have the Lucky and Unlucky numbers of a roll displayed once per roll type //rolltracker luckyinfo + +Enjoy. + + + + + + + + + From 6dd9a1cf35d177a013acc084224045dcc5616ceb Mon Sep 17 00:00:00 2001 From: Chiaia Date: Sat, 4 Aug 2018 04:26:21 -0400 Subject: [PATCH 0191/1002] Update readme.md --- addons/rolltracker/readme.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/addons/rolltracker/readme.md b/addons/rolltracker/readme.md index 631cac540d..d536dc0d24 100644 --- a/addons/rolltracker/readme.md +++ b/addons/rolltracker/readme.md @@ -9,12 +9,3 @@ If you have rolled a lucky roll, it will also prompt you and automatically stop To have the Lucky and Unlucky numbers of a roll displayed once per roll type //rolltracker luckyinfo Enjoy. - - - - - - - - - From ce0238fc882034b34000e32ec32943f1e7ec8a7b Mon Sep 17 00:00:00 2001 From: Ivaar <7287342+Ivaar@users.noreply.github.com> Date: Sun, 19 Aug 2018 00:05:17 -0700 Subject: [PATCH 0192/1002] GearSwap v0.934 - Fixed /item command handling --- addons/GearSwap/flow.lua | 11 +++------ addons/GearSwap/gearswap.lua | 2 +- addons/GearSwap/helper_functions.lua | 37 ++++++++++++++++++++++------ addons/GearSwap/triggers.lua | 7 ++---- addons/GearSwap/version_history.txt | 3 +++ 5 files changed, 40 insertions(+), 20 deletions(-) diff --git a/addons/GearSwap/flow.lua b/addons/GearSwap/flow.lua index 1856e6cc6d..c65e9941fe 100644 --- a/addons/GearSwap/flow.lua +++ b/addons/GearSwap/flow.lua @@ -252,15 +252,12 @@ function equip_sets_exit(swap_type,ts,val1) if val1.target and val1.target.id and val1.target.index and val1.prefix and unify_prefix[val1.prefix] then if val1.prefix == '/item' then -- Item use packet handling here - if val1.target.spawn_type == 2 then - --0x36 packet + if bit.band(val1.target.spawn_type, 2) == 2 and find_inventory_item(val1.id) then + -- 0x36 packet command_registry[ts].proposed_packet = assemble_menu_item_packet(val1.target.id,val1.target.index,val1.id) - elseif find_usable_item(val1.id,true) then --val1.target.id == player.id then - --0x37 packet + elseif find_usable_item(val1.id) then + -- 0x37 packet command_registry[ts].proposed_packet = assemble_use_item_packet(val1.target.id,val1.target.index,val1.id) - else - --0x36 packet - command_registry[ts].proposed_packet = assemble_menu_item_packet(val1.target.id,val1.target.index,val1.id) end if not command_registry[ts].proposed_packet then command_registry:delete_entry(ts) diff --git a/addons/GearSwap/gearswap.lua b/addons/GearSwap/gearswap.lua index 6cbf69c4ae..b6797d6196 100644 --- a/addons/GearSwap/gearswap.lua +++ b/addons/GearSwap/gearswap.lua @@ -25,7 +25,7 @@ --SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'GearSwap' -_addon.version = '0.933' +_addon.version = '0.934' _addon.author = 'Byrth' _addon.commands = {'gs','gearswap'} diff --git a/addons/GearSwap/helper_functions.lua b/addons/GearSwap/helper_functions.lua index 35ebf103d8..2058b23b17 100644 --- a/addons/GearSwap/helper_functions.lua +++ b/addons/GearSwap/helper_functions.lua @@ -496,7 +496,7 @@ function assemble_use_item_packet(target_id,target_index,item_id) outstr = outstr..string.char( (target_id%256), math.floor(target_id/256)%256, math.floor( (target_id/65536)%256) , math.floor( (target_id/16777216)%256) ) outstr = outstr..string.char(0,0,0,0) outstr = outstr..string.char( (target_index%256), math.floor(target_index/256)%256) - inventory_index,bag_id = find_usable_item(item_id,true) + inventory_index,bag_id = find_usable_item(item_id) if inventory_index then outstr = outstr..string.char(inventory_index%256)..string.char(0,bag_id,0,0,0) else @@ -548,7 +548,7 @@ function assemble_menu_item_packet(target_id,target_index,...) -- Inventory Index for the one unit for i,v in pairs(counts) do - inventory_index,bag_id = find_usable_item(i,false) + inventory_index = find_inventory_item(i) if inventory_index then outstr = outstr..string.char(inventory_index%256) else @@ -566,6 +566,24 @@ function assemble_menu_item_packet(target_id,target_index,...) return outstr end +----------------------------------------------------------------------------------- +--Name: find_inventory_item(item_id) +--Desc: Finds a npc trade item in normal inventory. Assumes items array +-- is accurate already. +--Args: +---- item_id - The resource line for the current item +----------------------------------------------------------------------------------- +--Returns: +---- inventory_index - The item's use inventory index (if it exists) +---- bag_id - The item's bag ID (if it exists) +----------------------------------------------------------------------------------- +function find_inventory_item(item_id) + for i,v in pairs(items.inventory) do + if type(v) == 'table' and v.id == item_id and v.status == 0 then + return i + end + end +end ----------------------------------------------------------------------------------- --Name: find_usable_item(item_id,bool) @@ -573,16 +591,16 @@ end -- is accurate already. --Args: ---- item_id - The resource line for the current item ----- bool - Indicates whether the item must show up in your control-I menu as usable ----------------------------------------------------------------------------------- --Returns: ---- inventory_index - The item's use inventory index (if it exists) ---- bag_id - The item's bag ID (if it exists) ----------------------------------------------------------------------------------- -function find_usable_item(item_id,bool) + +function find_usable_item(item_id) for _,bag in ipairs(usable_item_bags) do for i,v in pairs(items[to_windower_bag_api(bag.en)]) do - if type(v) == 'table' and v.id == item_id and (v.status == 5 or v.status == 0) and (not bool or is_usable_item(v)) then + if type(v) == 'table' and v.id == item_id and is_usable_item(v,bag.id) then return i, bag.id end end @@ -594,13 +612,18 @@ end --Desc: Determines whether the item table belongs to a usable item. --Args: ---- i_tab - current item table +---- bag_id - The item's bag ID ----------------------------------------------------------------------------------- --Returns: ---- true or false to indicate whether the item is usable ----------------------------------------------------------------------------------- -function is_usable_item(i_tab) +function is_usable_item(i_tab,bag_id) local ext = extdata.decode(i_tab) - if res.items[i_tab.id].type == 7 or (ext.type == 'Enchanted Equipment' and ext.usable) or res.items[i_tab.id].category == 'Usable' then return true end + if ext.type == 'Enchanted Equipment' and ext.usable then + return i_tab.status == 5 + elseif i_tab.status == 0 and bag_id < 4 then + return true + end return false end diff --git a/addons/GearSwap/triggers.lua b/addons/GearSwap/triggers.lua index b9b361adb7..fd78e4eadc 100644 --- a/addons/GearSwap/triggers.lua +++ b/addons/GearSwap/triggers.lua @@ -135,15 +135,12 @@ windower.register_event('outgoing text',function(original,modified,blocked,ffxi, if spell.prefix == '/item' then -- Item use packet handling here - if spell.target.spawn_type == 2 then + if bit.band(spell.target.spawn_type, 2) == 2 and find_inventory_item(spell.id) then --0x36 packet command_registry[ts].proposed_packet = assemble_menu_item_packet(spell.target.id,spell.target.index,spell.id) - elseif find_usable_item(spell.id,true) then + elseif find_usable_item(spell.id) then --0x37 packet command_registry[ts].proposed_packet = assemble_use_item_packet(spell.target.id,spell.target.index,spell.id) - else - --0x36 packet - command_registry[ts].proposed_packet = assemble_menu_item_packet(spell.target.id,spell.target.index,spell.id) end else command_registry[ts].proposed_packet = assemble_action_packet(spell.target.id,spell.target.index,outgoing_action_category_table[unify_prefix[spell.prefix]],spell.id,initialize_arrow_offset(spell.target)) diff --git a/addons/GearSwap/version_history.txt b/addons/GearSwap/version_history.txt index 623bfedc58..301a001192 100644 --- a/addons/GearSwap/version_history.txt +++ b/addons/GearSwap/version_history.txt @@ -1,4 +1,7 @@ ------------------------------------------------- + +GearSwap 0.934 - Fixed /item command handling. +------------------------------------------------- GearSwap 0.933 - Adjusted how item use packets are chosen. ------------------------------------------------- GearSwap 0.932 - Fixed bug that prevented gearswap from identifying items by their bag when worn. From 43e319f819cc963e5bab7352f9582a8940e71ba2 Mon Sep 17 00:00:00 2001 From: funkworkz Date: Wed, 22 Aug 2018 21:12:50 -0500 Subject: [PATCH 0193/1002] Update setbgm.lua New theme for Iroha's BCNM (as well as Heroines' Combat II) --- addons/setbgm/setbgm.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/setbgm/setbgm.lua b/addons/setbgm/setbgm.lua index 3b12db51fc..383a9f73d1 100644 --- a/addons/setbgm/setbgm.lua +++ b/addons/setbgm/setbgm.lua @@ -54,7 +54,7 @@ songs = { [50]='Feast of the Ladies', [51]='Abyssea - Scarlet Skies, Shadowed Plains', [52]='Melodies Errant', [53]='Shinryu', [54]='Everlasting Bonds', [55]='Provenance Watcher', [56]='Where it All Begins', [57]='Steel Sings, Blades Dance', [58]='A New Direction', [59]='The Pioneers', [60]='Into Lands Primeval - Ulbuka', [61]="Water's Umbral Knell", [62]='Keepers of the Wild', [63]='The Sacred City of Adoulin', [64]='Breaking Ground', [65]='Hades', [66]='Arciela', [67]='Mog Resort', [68]='Worlds Away', [69]="Distant Worlds (Nanaa Mihgo's version)", [70]='Monstrosity', [71]="The Pioneers (Nanaa Mihgo's version)", [72]='The Serpentine Labyrinth', [73]='The Divine', [74]='Clouds Over Ulbuka', [75]='The Price', [76]='Forever Today', [77]='Distant Worlds (Instrumental)', [78]='Forever Today (Instrumental)', [79]='Iroha', - [80]='The Boundless Black', [81]='Isle of the Gods', [82]='Wail of the Void', [83]="Rhapsodies of Vana'diel", [84]="Mount", [85]="Ambuscade", [86]="FFRK Shadow Lord", [87]="Omen", [88]="Dynamis - Divergence", [89]="Dynamis - Divergence (Wave 3)", + [80]='The Boundless Black', [81]='Isle of the Gods', [82]='Wail of the Void', [83]="Rhapsodies of Vana'diel", [84]="Mount", [85]="Ambuscade", [86]="FFRK Shadow Lord", [87]="Omen", [88]="Dynamis - Divergence", [89]="Dynamis - Divergence (Wave 3)", [90]="Iroha's Theme (BCNM)", [101]='Battle Theme', [102]='Battle in the Dungeon #2', [103]='Battle Theme #2', [104]='A Road Once Traveled', [105]='Mhaura', [106]='Voyager', [107]="The Kingdom of San d'Oria", [108]="Vana'diel March", [109]='Ronfaure', [110]='The Grand Duchy of Jeuno', [111]='Blackout', [112]='Selbina', [113]='Sarutabaruta', [114]='Batallia Downs', [115]='Battle in the Dungeon', [116]='Gustaberg', [117]="Ru'Lude Gardens", [118]='Rolanberry Fields', [119]='Awakening', [120]="Vana'diel March #2", [121]='Shadow Lord', [122]='One Last Time', [123]='Hopelessness', [124]='Recollection', [125]='Tough Battle', [126]='Mog House', [127]='Anxiety', [128]='Airship', [129]='Hook, Line and Sinker', From 12151f3104195c3519e3112cea0a2c49ddea2015 Mon Sep 17 00:00:00 2001 From: Byrth Date: Sun, 26 Aug 2018 16:34:21 -0400 Subject: [PATCH 0194/1002] boxdestroyer v1.0.4 Added compatibility with thief tools. --- addons/boxdestroyer/boxdestroyer.lua | 89 +++++++++++++++---- .../make_messages/make_messages.py | 2 +- addons/boxdestroyer/messages.lua | 2 +- 3 files changed, 73 insertions(+), 20 deletions(-) diff --git a/addons/boxdestroyer/boxdestroyer.lua b/addons/boxdestroyer/boxdestroyer.lua index e7ecdc591b..c658d5b2c1 100644 --- a/addons/boxdestroyer/boxdestroyer.lua +++ b/addons/boxdestroyer/boxdestroyer.lua @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- addon information _addon.name = 'boxdestroyer' -_addon.version = '1.0.3' +_addon.version = '1.0.4' _addon.command = 'boxdestroyer' _addon.author = 'Seth VanHeulen (Acacia@Odin)' @@ -61,9 +61,12 @@ observed_default = { ['range'] = false, ['equal'] = false, ['second_multiple'] = false, - ['first_multiple'] = false + ['first_multiple'] = false, + ['thief_tools_active'] = false } +thief_tools = {[1022] = true} + -- global variables box = {} @@ -312,14 +315,13 @@ function check_incoming_chunk(id, original, modified, injected, blocked) local message_id = original:unpack('H', 27) % 0x8000 if box[box_id] == nil then - box[box_id] = default + box[box_id] = table.copy(default) end if observed[box_id] == nil then observed[box_id] = table.copy(observed_default) end if get_id(zone_id,'greater_less') == message_id then - -- It is unclear how these messages (caused by Thief's tools) work box[box_id] = greater_less(box_id, param1 == 0, param0) elseif get_id(zone_id,'second_even_odd') == message_id then -- tells whether the second digit is even or odd @@ -330,22 +332,44 @@ function check_incoming_chunk(id, original, modified, injected, blocked) box[box_id] = even_odd(box_id, 10, param0) observed[box_id].first_even_odd = true elseif get_id(zone_id,'range') == message_id then - -- lower bound (param0) = solution - RANDINT(5,20) - -- upper bound (param1) = solution + RANDINT(5,20) - -- param0 + 21 > solution > param0 + 4 - -- param1 - 4 > solution > param1 - 21 - -- if the bound is less than 10 or greater than 99, the message changes to "greater" or "less" respectively - box[box_id] = greater_less(box_id, true, math.max(param1-21,param0+4) ) - box[box_id] = greater_less(box_id, false, math.min(param0+21,param1-4) ) - observed[box_id].range = true + if observed[box_id].thief_tools_active then + -- Thief tools are the same as normal ranges but with larger bounds. + -- lower bound (param0) = solution - RANDINT(8,32) + -- upper bound (param1) = solution + RANDINT(8,32) + -- param0 + 33 > solution > param0 + 7 + -- param1 - 7 > solution > param1 - 33 + -- if the bound is less than 10 or greater than 99, the message changes to "greater" or "less" respectively + box[box_id] = greater_less(box_id, true, math.max(param1-33,param0+7) ) + box[box_id] = greater_less(box_id, false, math.min(param0+33,param1-7) ) + observed[box_id].thief_tools_active = false + else + -- lower bound (param0) = solution - RANDINT(5,20) + -- upper bound (param1) = solution + RANDINT(5,20) + -- param0 + 21 > solution > param0 + 4 + -- param1 - 4 > solution > param1 - 21 + -- if the bound is less than 10 or greater than 99, the message changes to "greater" or "less" respectively + box[box_id] = greater_less(box_id, true, math.max(param1-21,param0+4) ) + box[box_id] = greater_less(box_id, false, math.min(param0+21,param1-4) ) + observed[box_id].range = true + end elseif get_id(zone_id,'less') == message_id then -- Less is a range with 9 as the lower bound - box[box_id] = greater_less(box_id, false, math.min(9+21,param0-4) ) - observed[box_id].range = true + if observed[box_id].thief_tools_active then + box[box_id] = greater_less(box_id, false, math.min(9+33,param0-7) ) + observed[box_id].thief_tools_active = false + else + box[box_id] = greater_less(box_id, false, math.min(9+21,param0-4) ) + observed[box_id].range = true + end elseif get_id(zone_id,'greater') == message_id then -- Greater is a range with 100 as the upper bound - box[box_id] = greater_less(box_id, true, math.max(100-21,param0+4) ) - observed[box_id].range = true + if observed[box_id].thief_tools_active then + box[box_id] = greater_less(box_id, true, math.max(100-33,param0+7) ) + observed[box_id].thief_tools_active = false + else + box[box_id] = greater_less(box_id, true, math.max(100-21,param0+4) ) + observed[box_id].range = true + end elseif get_id(zone_id,'equal') == message_id then -- single number that is either the first or second digit of the solution local new = equal(box_id, true, param0) @@ -377,14 +401,16 @@ function check_incoming_chunk(id, original, modified, injected, blocked) observed[box_id].first_multiple = true elseif get_id(zone_id,'success') == message_id or get_id(zone_id,'failure') == message_id then box[box_id] = nil + elseif get_id(zone_id,'tool_failure') == message_id then + observed[box_id].thief_tools_active = false end elseif id == 0x34 then local box_id = original:unpack('I', 5) if windower.ffxi.get_mob_by_id(box_id).name == 'Treasure Casket' then local chances = original:byte(9) if box[box_id] == nil then - box[box_id] = default - observed[box_id] = observed_default + box[box_id] = table.copy(default) + observed[box_id] = table.copy(observed_default) end if chances > 0 and chances < 7 then display(box_id, chances) @@ -397,6 +423,33 @@ function check_incoming_chunk(id, original, modified, injected, blocked) end end +function watch_for_keys(id, original, modified, injected, blocked) + if blocked then + elseif (id == 0x036 or id == 0x037) and + windower.ffxi.get_mob_by_id(modified:unpack('I',0x05)).name == 'Treasure Casket' and + (windower.ffxi.get_player().main_job == 'THF' or windower.ffxi.get_player().sub_job == 'THF') then + + local box_id = modified:unpack('I',0x05) + if not box[box_id] then + box[box_id] = table.copy(default) + observed[box_id] = table.copy(observed_default) + end + + if id == 0x037 and thief_tools[windower.ffxi.get_items(modified:byte(0x11))[modified:byte(0xF)].id] then + observed[box_id].thief_tools_active = true + elseif id == 0x036 then + for i = 1,9 do + if thief_tools[windower.ffxi.get_items(0)[modified:byte(0x30+i)].id] then + observed[box_id].thief_tools_active = true + break + end + end + end + end +end + -- register event callbacks windower.register_event('incoming chunk', check_incoming_chunk) + +windower.register_event('outgoing chunk', watch_for_keys) diff --git a/addons/boxdestroyer/make_messages/make_messages.py b/addons/boxdestroyer/make_messages/make_messages.py index 081f248196..932ea3b7f8 100644 --- a/addons/boxdestroyer/make_messages/make_messages.py +++ b/addons/boxdestroyer/make_messages/make_messages.py @@ -71,7 +71,7 @@ def write_lua(messages): line = messages[zone_id]+',' print(" [{}] = {}".format(zone_id, line), file=o) print('}',file=o) - print('offsets = {greater_less=1, failure=2, success=4, second_even_odd=5, first_even_odd=6, range=7, less=8, greater=9, equal=10, second_multiple=11, first_multiple=12}',file=o) + print('offsets = {greater_less=1, failure=2, success=4, second_even_odd=5, first_even_odd=6, range=7, less=8, greater=9, equal=10, second_multiple=11, first_multiple=12, tool_failure=13}',file=o) o.close() write_lua(search_dialog(zones, search)) diff --git a/addons/boxdestroyer/messages.lua b/addons/boxdestroyer/messages.lua index 8bf36ffe49..986f4c868d 100644 --- a/addons/boxdestroyer/messages.lua +++ b/addons/boxdestroyer/messages.lua @@ -58,4 +58,4 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination [212] = 10637, [213] = 10446, } -offsets = {greater_less=1, failure=2, success=4, second_even_odd=5, first_even_odd=6, range=7, less=8, greater=9, equal=10, second_multiple=11, first_multiple=12} +offsets = {greater_less=1, failure=2, success=4, second_even_odd=5, first_even_odd=6, range=7, less=8, greater=9, equal=10, second_multiple=11, first_multiple=12, tool_failure=13} From 892efd04abf00fbd08b0a47fc44bcd590b932590 Mon Sep 17 00:00:00 2001 From: Byrth Date: Sun, 26 Aug 2018 20:28:55 -0400 Subject: [PATCH 0195/1002] Boxdestroyer minor update --- addons/boxdestroyer/boxdestroyer.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/addons/boxdestroyer/boxdestroyer.lua b/addons/boxdestroyer/boxdestroyer.lua index c658d5b2c1..054d1d5767 100644 --- a/addons/boxdestroyer/boxdestroyer.lua +++ b/addons/boxdestroyer/boxdestroyer.lua @@ -355,9 +355,11 @@ function check_incoming_chunk(id, original, modified, injected, blocked) elseif get_id(zone_id,'less') == message_id then -- Less is a range with 9 as the lower bound if observed[box_id].thief_tools_active then + box[box_id] = greater_less(box_id, true, math.max(9, param0-33) ) box[box_id] = greater_less(box_id, false, math.min(9+33,param0-7) ) observed[box_id].thief_tools_active = false else + box[box_id] = greater_less(box_id, true, math.max(9, param0-21) ) box[box_id] = greater_less(box_id, false, math.min(9+21,param0-4) ) observed[box_id].range = true end @@ -365,9 +367,11 @@ function check_incoming_chunk(id, original, modified, injected, blocked) -- Greater is a range with 100 as the upper bound if observed[box_id].thief_tools_active then box[box_id] = greater_less(box_id, true, math.max(100-33,param0+7) ) + box[box_id] = greater_less(box_id, false, math.min(100,param0+33) ) observed[box_id].thief_tools_active = false else box[box_id] = greater_less(box_id, true, math.max(100-21,param0+4) ) + box[box_id] = greater_less(box_id, false, math.min(100,param0+21) ) observed[box_id].range = true end elseif get_id(zone_id,'equal') == message_id then From 6cd68bc17d31297cd2894c1576e9ba75903ae2f1 Mon Sep 17 00:00:00 2001 From: Byrth Date: Mon, 27 Aug 2018 11:45:19 -0400 Subject: [PATCH 0196/1002] Fixing boundary conditions in v1.0.4 It turns out that the message turns to "less" or "greater" if the range bound lands on 10 or 99. --- addons/boxdestroyer/boxdestroyer.lua | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/addons/boxdestroyer/boxdestroyer.lua b/addons/boxdestroyer/boxdestroyer.lua index 054d1d5767..a75e025564 100644 --- a/addons/boxdestroyer/boxdestroyer.lua +++ b/addons/boxdestroyer/boxdestroyer.lua @@ -338,7 +338,7 @@ function check_incoming_chunk(id, original, modified, injected, blocked) -- upper bound (param1) = solution + RANDINT(8,32) -- param0 + 33 > solution > param0 + 7 -- param1 - 7 > solution > param1 - 33 - -- if the bound is less than 10 or greater than 99, the message changes to "greater" or "less" respectively + -- if the bound is less than 11 or greater than 98, the message changes to "greater" or "less" respectively box[box_id] = greater_less(box_id, true, math.max(param1-33,param0+7) ) box[box_id] = greater_less(box_id, false, math.min(param0+33,param1-7) ) observed[box_id].thief_tools_active = false @@ -347,7 +347,7 @@ function check_incoming_chunk(id, original, modified, injected, blocked) -- upper bound (param1) = solution + RANDINT(5,20) -- param0 + 21 > solution > param0 + 4 -- param1 - 4 > solution > param1 - 21 - -- if the bound is less than 10 or greater than 99, the message changes to "greater" or "less" respectively + -- if the bound is less than 11 or greater than 98, the message changes to "greater" or "less" respectively box[box_id] = greater_less(box_id, true, math.max(param1-21,param0+4) ) box[box_id] = greater_less(box_id, false, math.min(param0+21,param1-4) ) observed[box_id].range = true @@ -356,21 +356,21 @@ function check_incoming_chunk(id, original, modified, injected, blocked) -- Less is a range with 9 as the lower bound if observed[box_id].thief_tools_active then box[box_id] = greater_less(box_id, true, math.max(9, param0-33) ) - box[box_id] = greater_less(box_id, false, math.min(9+33,param0-7) ) + box[box_id] = greater_less(box_id, false, math.min(10+33,param0-7) ) observed[box_id].thief_tools_active = false else box[box_id] = greater_less(box_id, true, math.max(9, param0-21) ) - box[box_id] = greater_less(box_id, false, math.min(9+21,param0-4) ) + box[box_id] = greater_less(box_id, false, math.min(10+21,param0-4) ) observed[box_id].range = true end elseif get_id(zone_id,'greater') == message_id then -- Greater is a range with 100 as the upper bound if observed[box_id].thief_tools_active then - box[box_id] = greater_less(box_id, true, math.max(100-33,param0+7) ) + box[box_id] = greater_less(box_id, true, math.max(99-33,param0+7) ) box[box_id] = greater_less(box_id, false, math.min(100,param0+33) ) observed[box_id].thief_tools_active = false else - box[box_id] = greater_less(box_id, true, math.max(100-21,param0+4) ) + box[box_id] = greater_less(box_id, true, math.max(99-21,param0+4) ) box[box_id] = greater_less(box_id, false, math.min(100,param0+21) ) observed[box_id].range = true end From cb3451f804803043c9210e4f0c184e7584f68d85 Mon Sep 17 00:00:00 2001 From: Sjshovan Date: Thu, 6 Sep 2018 20:34:52 -0400 Subject: [PATCH 0197/1002] Increment version to 0.9.4 Fix: Music wouldn't change if addon loaded while on mount. Fix: Music wouldn't change if addon unloaded while on mount. Fix: Muzzle type `Silent` was playing incorrect track. Update: Licences now display correct addon name. Update: Muzzle type 'Normal' changed to 'Mount'. Update: Muzzle type 'Choco' changed to 'Chocobo'. Update: mountmuzzle.lua refactored and condensed. Update: README Commands updated. Update: README Installation updated. Update: README Table of Contents updated. Update: README Known Issues updated. Update: README TODOs updated. Add: New commands added (about, unload). Add: Shorthand aliases added to all commands. Add: Aliases added to README. --- addons/MountMuzzle/LICENSE | 2 +- addons/MountMuzzle/README.md | 87 ++++++++++++-- addons/MountMuzzle/constants.lua | 37 +++--- addons/MountMuzzle/helpers.lua | 15 ++- addons/MountMuzzle/mountmuzzle.lua | 176 +++++++++++++++++++---------- 5 files changed, 230 insertions(+), 87 deletions(-) diff --git a/addons/MountMuzzle/LICENSE b/addons/MountMuzzle/LICENSE index 99eebd69de..1b2e964655 100644 --- a/addons/MountMuzzle/LICENSE +++ b/addons/MountMuzzle/LICENSE @@ -9,7 +9,7 @@ modification, are permitted provided that the following conditions are met: * 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 MountMuzzle nor the + * Neither the name of Mount Muzzle nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/addons/MountMuzzle/README.md b/addons/MountMuzzle/README.md index 8006ca1624..84c3891442 100644 --- a/addons/MountMuzzle/README.md +++ b/addons/MountMuzzle/README.md @@ -1,5 +1,5 @@ **Author:** [Sjshovan (Apogee)](https://github.com/Ap0gee) -**Version:** v0.9.3 +**Version:** v0.9.4 # Mount Muzzle @@ -11,6 +11,7 @@ - [Prerequisites](#prerequisites) - [Installation](#installation) +- [Aliases](#aliases) - [Usage](#usage) - [Commands](#commands) - [Support](#support) @@ -26,13 +27,39 @@ ___ ___ ### Installation + +**Windower:** +1. Navigate to the `Addons` section at the top of Windower. +2. Locate the `MountMuzzle` addon. +3. Click the download button. +4. Ensure the addon is switched on. + +**Manual:** 1. Navigate to . 2. Click on `Releases`. 3. Click on the `Source code (zip)` link within the latest release to download. 4. Extract the zipped folder to `Windower4/addons/`. -5. Rename the folder to remove the version tag (`-v0.9.3`). The folder should be named `MountMuzzle`. - +5. Rename the folder to remove the version tag (`-v0.9.4`). The folder should be named `MountMuzzle`. + ___ +### Aliases +The following aliases are available to Mount Muzzle commands: + +**mountmuzzle:** muzzle | mm +**list:** l +**set:** s +**get:** g +**default:** d +**unload:** u +**reload:** r +**about:** a +**silent:** s +**mount:** m +**chocobo:** c +**zone:** z +**help:** h + + ___ ### Usage Manually load the addon by using one of the following commands: @@ -61,6 +88,7 @@ Displays the available muzzle types. Below are the equivalent ways of calling th //mountmuzzle list //muzzle list //mm list + //mm l **set _\_** @@ -69,6 +97,7 @@ Sets the current muzzle to the given muzzle type. This command takes a single ar //mountmuzzle set //muzzle set //mm set + //mm s Here are some usage examples for the **set _\_** command: `mm set silent` and `muzzle set zone` etc... @@ -79,6 +108,7 @@ Displays the current muzzle that is set. Below are the equivalent ways of callin //mountmuzzle get //muzzle get //mm get + //mm g **default** @@ -87,7 +117,17 @@ Sets the current muzzle to the default muzzle type: `Silent`. Below are the equi //mountmuzzle default //muzzle default //mm default + //mm d + +**unload** +Unloads the Mount Muzzle addon. Below are the equivalent ways of calling the command: + + //mountmuzzle unload + //muzzle unload + //mm unload + //mm u + **reload** Reloads the Mount Muzzle addon. Below are the equivalent ways of calling the command: @@ -95,7 +135,17 @@ Reloads the Mount Muzzle addon. Below are the equivalent ways of calling the com //mountmuzzle reload //muzzle reload //mm reload + //mm r +**about** + +Displays information about the Mount Muzzle addon. Below are the equivalent ways of calling the command: + + //mountmuzzle about + //muzzle about + //mm about + //mm a + ___ ### Support **Having Issues with this addon?** @@ -113,19 +163,36 @@ ___ ___ ### Change Log +**v0.9.4** - 9/06/2018 +- **Fix:** Music wouldn't change if addon loaded while on mount. +- **Fix:** Music wouldn't change if addon unloaded while on mount. +- **Fix:** Muzzle type 'Silent' was playing incorrect track. +- **Update:** Licences now display correct addon name. +- **Update:** Muzzle type 'Normal' changed to 'Mount'. +- **Update:** Muzzle type 'Choco' changed to 'Chocobo'. +- **Update:** mountmuzzle.lua refactored and condensed. +- **Update:** README Commands updated. +- **Update:** README Installation updated. +- **Update:** README Table of Contents updated. +- **Update:** README Known Issues updated. +- **Update:** README TODOS updated. +- **Add:** New commands added (about, unload). +- **Add:** Shorthand aliases added to all commands. +- **Add:** Aliases added to README. + **v0.9.3** - 5/31/2018 - **Remove:** Removed /data/settings.xml file. - **Update:** licences now display correct author name. -- **Update:** README refactored in attempt to meet merge criteria. - **Update:** helpers.lua now requires only colors from constants.lua. - **Update:** constants.lua now returns table of globals for modular support. - **Update:** mountmuzzle.lua refactored in attempt to meet merge criteria. +- **Update:** README refactored in attempt to meet merge criteria. **v0.9.2** - 5/24/2018 - **Fix:** Zone music gets silenced if player enters reive on mount with zone muzzle selected. - **Fix:** Player reaches error if no arguments are given upon invoking the addon. - **Update:** Convert tab characters to spaces, simplify code. -- **Update:** README Usage instructions updated. +- **Update:** README Usage Instructions updated. - **Update:** README Known Issues updated. - **Add:** Table of Contents added to README. - **Add:** Prerequisites added to README. @@ -136,7 +203,7 @@ ___ **v0.9.1** - 5/22/2018 - **Fix:** Chosen music does not start upon login if mounted. - **Fix:** Chosen music does not persist upon changing zones. -- **Add:** Known issues added to README. +- **Add:** Known Issues added to README. - **Add:** TODOS added to README. **v0.9.0** - 5/21/2018 @@ -146,12 +213,14 @@ ___ ### Known Issues - **Issue:** If Mount Muzzle is selected to automatically load and the player is mounted upon login, there is a significant delay before the chosen music will begin to play. -- **Issue:** Upon changing zones the default music can be heard for a moment before the chosen music begins to play. +- **Issue:** Upon changing zones the default music can be heard for a moment before the chosen music begins to play. +- **Issue:** Unable to correctly set mount music to original if Mount Muzzle is unloaded while mounted. ___ -### TODOS +### TODOs -- **Todo:** Investigate alternative methods for music change as packet injection/swap allows the player to hear the default music upon zone change and login, regardless of chosen music. +- **TODO:** Investigate alternative methods for music change as packet injection/swap allows the player to hear the default music upon zone change and login, regardless of chosen music. +- **TODO:** Investigate methods for determining which mount type the player is on when loading/unloading Mount Muzzle. ___ ### License diff --git a/addons/MountMuzzle/constants.lua b/addons/MountMuzzle/constants.lua index faab1affde..b39385dbb3 100644 --- a/addons/MountMuzzle/constants.lua +++ b/addons/MountMuzzle/constants.lua @@ -10,7 +10,7 @@ modification, are permitted provided that the following conditions are met: * 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 MountMuzzle nor the + * Neither the name of Mount Muzzle nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. @@ -24,12 +24,15 @@ 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. -]] +--]] packets = { inbound = { music_change = { id = 0x05F + }, + zone_update = { + id = 0x00A } }, outbound = { @@ -46,18 +49,24 @@ packets = { player = { statuses = { mounted = 85 + }, + buffs = { + reiveMark = 511, + mounted = 252 } } music = { songs = { - silent = 90, - normal = 84, - choco = 212, + silent = 91, + mount = 84, + chocobo = 212, zone = 0, }, types = { - mount = 4 + mount = 4, + idle_day = 0, + idle_night = 1 } } @@ -76,14 +85,14 @@ muzzles = { song = music.songs.silent, description = 'No Music (Default)' }, - normal = { - name = 'normal', - song = music.songs.normal, - description = 'Original Music' + mount = { + name = 'mount', + song = music.songs.mount, + description = 'Mount Music' }, - choco = { - name = 'choco', - song = music.songs.choco, + chocobo = { + name = 'chocobo', + song = music.songs.chocobo, description = 'Chocobo Music' }, zone = { @@ -98,5 +107,5 @@ return { player = player, music = music, colors = colors, - muzzles = muzzles + muzzles = muzzles } \ No newline at end of file diff --git a/addons/MountMuzzle/helpers.lua b/addons/MountMuzzle/helpers.lua index 682fec120f..000a65e929 100644 --- a/addons/MountMuzzle/helpers.lua +++ b/addons/MountMuzzle/helpers.lua @@ -10,7 +10,7 @@ modification, are permitted provided that the following conditions are met: * 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 MountMuzzle nor the + * Neither the name of Mount Muzzle nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. @@ -24,7 +24,7 @@ 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. -]] +--]] local colors = require("constants").colors @@ -33,6 +33,7 @@ function buildHelpCommandEntry(command, description) local command = command:color(colors.secondary) local sep = "=>":color(colors.primary) local description = description:color(colors.info) + return "%s %s %s %s":format(short_name, command, sep, description) end @@ -40,32 +41,36 @@ function buildHelpTypeEntry(name, description) local name = name:color(colors.secondary) local sep = "=>":color(colors.primary) local description = description:color(colors.info) + return "%s %s %s":format(name, sep, description) end function buildHelpTitle(context) local context = context:color(colors.danger) + return "%s Help: %s":color(colors.primary):format(_addon.name, context) end function buildHelpSeperator(character, count) local sep = '' + for i = 1, count do sep = sep .. character end + return sep:color(colors.warn) end function buildCommandResponse(message, success) - local response_template = '%s: %s' local response_color = colors.success local response_type = 'Success' - + if not success then response_type = 'Error' response_color = colors.danger end - return response_template:format(response_type:color(response_color), message) + + return "%s: %s":format(response_type:color(response_color), message) end function displayResponse(response, color) diff --git a/addons/MountMuzzle/mountmuzzle.lua b/addons/MountMuzzle/mountmuzzle.lua index 03aead5591..3694501638 100644 --- a/addons/MountMuzzle/mountmuzzle.lua +++ b/addons/MountMuzzle/mountmuzzle.lua @@ -10,7 +10,7 @@ modification, are permitted provided that the following conditions are met: * 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 MountMuzzle nor the + * Neither the name of Mount Muzzle nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. @@ -24,21 +24,21 @@ 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.name = 'Mount Muzzle' -_addon.author = 'Sjshovan (Apogee) sjshovan@gmail.com' -_addon.version = '0.9.3' +_addon.name = 'Mount Muzzle' +_addon.description = 'Change or remove the default mount music.' +_addon.author = 'Sjshovan (Apogee) sjshovan@gmail.com' +_addon.version = '0.9.4' _addon.commands = {'mountmuzzle', 'muzzle', 'mm'} local _logger = require('logger') -local _config = require('config') +local _config = require('config') local _packets = require('packets') -require("constants") +require('constants') require('helpers') -local mounted = false local needs_inject = false local defaults = { @@ -56,21 +56,40 @@ local help = { buildHelpCommandEntry('set ', 'Set the current muzzle to the given muzzle type.'), buildHelpCommandEntry('get', 'Display the current muzzle.'), buildHelpCommandEntry('default', 'Set the current muzzle to the default (Silent).'), + buildHelpCommandEntry('unload', 'Unload Mount Muzzle.'), buildHelpCommandEntry('reload', 'Reload Mount Muzzle.'), + buildHelpCommandEntry('about', 'Display information about Mount Muzzle.'), buildHelpCommandEntry('help', 'Display Mount Muzzle commands.'), buildHelpSeperator('=', 26), }, - types = { buildHelpSeperator('=', 23), buildHelpTitle('Types'), buildHelpSeperator('=', 23), buildHelpTypeEntry(muzzles.silent.name:ucfirst(), muzzles.silent.description), - buildHelpTypeEntry(muzzles.normal.name:ucfirst(), muzzles.normal.description), - buildHelpTypeEntry(muzzles.choco.name:ucfirst(), muzzles.choco.description), + buildHelpTypeEntry(muzzles.mount.name:ucfirst(), muzzles.mount.description), + buildHelpTypeEntry(muzzles.chocobo.name:ucfirst(), muzzles.chocobo.description), buildHelpTypeEntry(muzzles.zone.name:ucfirst(), muzzles.zone.description), buildHelpSeperator('=', 23), }, + about = { + buildHelpSeperator('=', 23), + buildHelpTitle('About'), + buildHelpSeperator('=', 23), + buildHelpTypeEntry('Name', _addon.name), + buildHelpTypeEntry('Description', _addon.description), + buildHelpTypeEntry('Author', _addon.author), + buildHelpTypeEntry('Version', _addon.version), + buildHelpSeperator('=', 23), + }, + aliases = { + muzzles = { + s = muzzles.silent.name, + m = muzzles.mount.name, + c = muzzles.chocobo.name, + z = muzzles.zone.name + } + } } function display_help(table_help) @@ -83,17 +102,17 @@ function getMuzzle() return settings.muzzle end -function setMuzzle(muzzle) - settings.muzzle = muzzle - settings:save() +function getMuzzleNameFromAlias(alias) + return help.aliases.muzzles[alias] end -function muzzleValid(muzzle) - return muzzles[muzzle] ~= nil +function getPlayerBuffs() + return T(windower.ffxi.get_player().buffs) end function resolveCurrentMuzzle() local current_muzzle = getMuzzle() + if not muzzleValid(current_muzzle) then current_muzzle = muzzles.silent.name setMuzzle(current_muzzle) @@ -102,20 +121,52 @@ function resolveCurrentMuzzle() colors.warn ) end + return muzzles[current_muzzle] end -function requestInject() - needs_inject = true +function setMuzzle(muzzle) + settings.muzzle = muzzle + settings:save() +end + +function playerInReive() + return getPlayerBuffs():contains(player.buffs.reiveMark) +end + +function playerMounted() + return getPlayerBuffs() +end + +function playerIsMounted() + local _player = windower.ffxi.get_player() + + if _player then + return _player.status == player.statuses.mounted or getPlayerBuffs():contains(player.buffs.mounted) + end + + return false +end + +function muzzleValid(muzzle) + return muzzles[muzzle] ~= nil end function injectMuzzleMusic() + injectMusic(music.types.mount, resolveCurrentMuzzle().song) +end + +function injectMusic(bgmType, songID) _packets.inject(_packets.new('incoming', packets.inbound.music_change.id, { - ['BGM Type'] = music.types.mount, - ['Song ID'] = resolveCurrentMuzzle().song, + ['BGM Type'] = bgmType, + ['Song ID'] = songID, })) end +function requestInject() + needs_inject = true +end + function handleInjectionNeeds() if needs_inject and playerIsMounted() then injectMuzzleMusic() @@ -123,63 +174,83 @@ function handleInjectionNeeds() end end -function playerIsMounted() - local _player = windower.ffxi.get_player() - if _player then - return mounted or _player.status == player.statuses.mounted - end - return false +function tryInject() + requestInject() + handleInjectionNeeds() end -windower.register_event('login', requestInject) -windower.register_event('load', requestInject) -windower.register_event('zone change', requestInject) +windower.register_event('login', function() + tryInject() +end) + +windower.register_event('load', function() + tryInject() +end) + +windower.register_event('unload', function() + injectMusic(music.types.mount, muzzles.zone.song) +end) + +windower.register_event('zone change', function() + tryInject() +end) windower.register_event('addon command', function(command, ...) if command then command = command:lower() else - display_help(help.commands) - return + return display_help(help.commands) end local command_args = {...} - local respond = false local response_message = '' local success = true - - if command == 'list' then + + if command == 'list' or command == 'l' then display_help(help.types) - elseif command == 'set' then + elseif command == 'set' or command == 's' then respond = true - - local muzzle = tostring (command_args[1]):lower() + + local muzzle = tostring(command_args[1]):lower() + local from_alias = getMuzzleNameFromAlias(muzzle) + + if (from_alias ~= nil) then + muzzle = from_alias + end if not muzzleValid(muzzle) then success = false response_message = 'Muzzle type not recognized.' else - needs_inject = true + requestInject() setMuzzle(muzzle) response_message = 'Updated current muzzle to %s.':format(muzzle:ucfirst():color(colors.secondary)) end - elseif command == 'get' then + elseif command == 'get' or command == 'g' then respond = true response_message = 'Current muzzle is %s.':format(getMuzzle():ucfirst():color(colors.secondary)) - elseif command == 'default' then + elseif command == 'default' or command == 'd' then respond = true - needs_inject = true + requestInject() setMuzzle(muzzles.silent.name) response_message = 'Updated current muzzle to the default (%s).':format('Silent':color(colors.secondary)) - elseif command == 'reload' then + elseif command == 'reload' or command == 'r' then windower.send_command('lua r mountmuzzle') + + elseif command == 'unload' or command == 'u' then + respond = true + response_message = 'Thank you for using Mount Muzzle. Goodbye.' + windower.send_command('lua unload mountmuzzle') + elseif command == 'about' or command == 'a' then + display_help(help.about) + elseif command == 'help' or command == 'h' then display_help(help.commands) else @@ -191,30 +262,19 @@ windower.register_event('addon command', function(command, ...) buildCommandResponse(response_message, success) ) end - + handleInjectionNeeds() end) -windower.register_event('outgoing chunk', function(id, data) - if id == packets.outbound.action.id then - local packet = _packets.parse('outgoing', data) - if packet.Category == packets.outbound.action.categories.mount then - mounted = true - elseif packet.Category == packets.outbound.action.categories.unmount then - mounted = false - end - end -end) - windower.register_event('incoming chunk', function(id, data) - if id == packets.inbound.music_change.id and playerIsMounted() then + if id == packets.inbound.music_change.id then local packet = _packets.parse('incoming', data) - + if packet['BGM Type'] == music.types.mount then packet['Song ID'] = resolveCurrentMuzzle().song return _packets.build(packet) end + + tryInject() end - - handleInjectionNeeds() end) \ No newline at end of file From 01a25143d96ef571406bf0fc4449e3cde3f47406 Mon Sep 17 00:00:00 2001 From: Sjshovan Date: Thu, 6 Sep 2018 20:37:59 -0400 Subject: [PATCH 0198/1002] Update: addons.xml updated. --- addons/addons.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/addons.xml b/addons/addons.xml index 5c673373b9..2b703b4c79 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -336,9 +336,9 @@ https://discord.gg/b275nMv - MountMuzzle + Mount Muzzle Sjshovan (Apogee) - Allows the user to change or remove the default mount music. + Change or remove the default mount music. https://github.com/Windower/Lua/issues https://discord.gg/b275nMv From b82d323627bd5c9d3f1b2004cc6305d8e1d77c6e Mon Sep 17 00:00:00 2001 From: Sjshovan Date: Fri, 7 Sep 2018 13:25:42 -0400 Subject: [PATCH 0199/1002] Update: condense mountmuzzle.lua --- addons/MountMuzzle/mountmuzzle.lua | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/addons/MountMuzzle/mountmuzzle.lua b/addons/MountMuzzle/mountmuzzle.lua index 3694501638..2c76959545 100644 --- a/addons/MountMuzzle/mountmuzzle.lua +++ b/addons/MountMuzzle/mountmuzzle.lua @@ -102,10 +102,6 @@ function getMuzzle() return settings.muzzle end -function getMuzzleNameFromAlias(alias) - return help.aliases.muzzles[alias] -end - function getPlayerBuffs() return T(windower.ffxi.get_player().buffs) end @@ -134,10 +130,6 @@ function playerInReive() return getPlayerBuffs():contains(player.buffs.reiveMark) end -function playerMounted() - return getPlayerBuffs() -end - function playerIsMounted() local _player = windower.ffxi.get_player() @@ -179,11 +171,7 @@ function tryInject() handleInjectionNeeds() end -windower.register_event('login', function() - tryInject() -end) - -windower.register_event('load', function() +windower.register_event('login', 'load', 'zone change', function() tryInject() end) @@ -191,10 +179,6 @@ windower.register_event('unload', function() injectMusic(music.types.mount, muzzles.zone.song) end) -windower.register_event('zone change', function() - tryInject() -end) - windower.register_event('addon command', function(command, ...) if command then command = command:lower() @@ -214,7 +198,7 @@ windower.register_event('addon command', function(command, ...) respond = true local muzzle = tostring(command_args[1]):lower() - local from_alias = getMuzzleNameFromAlias(muzzle) + local from_alias = help.aliases.muzzles[muzzle] if (from_alias ~= nil) then muzzle = from_alias From fcbd34e3855fac7d3ae649733e290ef1747384ef Mon Sep 17 00:00:00 2001 From: mujihina Date: Sat, 8 Sep 2018 09:30:50 -0700 Subject: [PATCH 0200/1002] Update slips.lua Adding to slip22: melon slicer 21967 fancy gilet 25774 fancy trunks 25838 fancy top 25775 fancy shorts 25839 --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 6b08fb1339..841aa5247e 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757}, -- 191 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453,}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454,}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966}, -- 76 : Zanmato +1 is the last + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839,}, -- 76 : Fancy Shorts is the last [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25589, 25762, 25763, 25810, 25811, 25869, 25870, 25935, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, }, --160 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330,}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665,}, --115 From 013aaddb615fa09240f7299aa28293a1a6007f0a Mon Sep 17 00:00:00 2001 From: Chiaia Date: Sun, 9 Sep 2018 00:33:37 -0400 Subject: [PATCH 0201/1002] Rad Umbra DMG/Recovers --- addons/scoreboard/scoreboard.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/scoreboard/scoreboard.lua b/addons/scoreboard/scoreboard.lua index 61260ddd0d..461dfd072e 100644 --- a/addons/scoreboard/scoreboard.lua +++ b/addons/scoreboard/scoreboard.lua @@ -444,7 +444,7 @@ function action_handler(raw_actionpacket) 293,294,295,296,297,298,299, 300,301,302,385,386,387,388, 389,390,391,392,393,394,395, - 396,397,398,732}:contains(add.message_id) then + 396,397,398,732,767,768,769,770}:contains(add.message_id) then actor_name = string.format("Skillchain(%s%s)", actor_name:sub(1, 3), actor_name:len() > 3 and '.' or '') end From 1133047db2b7769fe2d1f1cec6039b6cd3805340 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Sun, 9 Sep 2018 00:56:14 -0400 Subject: [PATCH 0202/1002] Update scoreboard.lua --- addons/scoreboard/scoreboard.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/scoreboard/scoreboard.lua b/addons/scoreboard/scoreboard.lua index 461dfd072e..97e1369d70 100644 --- a/addons/scoreboard/scoreboard.lua +++ b/addons/scoreboard/scoreboard.lua @@ -2,7 +2,7 @@ _addon.name = 'Scoreboard' _addon.author = 'Suji' -_addon.version = '1.11' +_addon.version = '1.12' _addon.commands = {'sb', 'scoreboard'} require('tables') From 9ec609e54a632d30324b02c700ff0174754a3c8a Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Wed, 12 Sep 2018 11:28:57 +0200 Subject: [PATCH 0203/1002] Added dummy resource for new resource IDs --- addons/libs/resources.lua | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/addons/libs/resources.lua b/addons/libs/resources.lua index a33b9cf463..6b32814797 100644 --- a/addons/libs/resources.lua +++ b/addons/libs/resources.lua @@ -69,7 +69,23 @@ end resource_mt.__class = 'Resource' +local dummy = function(id) + return setmetatable({ + id = id, + en = '', + enl = '', + ens = '', + ja = '', + jal = '', + jas = '', + }, resource_entry_mt) +end + resource_mt.__index = function(t, k) + if type(k) == 'number' then + return dummy(k) + end + local res = slots[t] and slots[t]:contains(k) and resource_group:endapply(k) if not res then From 856d3b1f688c18a8d4c7e31c3a22d9fec704fd61 Mon Sep 17 00:00:00 2001 From: Byrth Date: Sat, 15 Sep 2018 17:16:55 -0400 Subject: [PATCH 0204/1002] Revert "Added dummy resource for new resource IDs" This reverts commit 9ec609e54a632d30324b02c700ff0174754a3c8a. --- addons/libs/resources.lua | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/addons/libs/resources.lua b/addons/libs/resources.lua index 6b32814797..a33b9cf463 100644 --- a/addons/libs/resources.lua +++ b/addons/libs/resources.lua @@ -69,23 +69,7 @@ end resource_mt.__class = 'Resource' -local dummy = function(id) - return setmetatable({ - id = id, - en = '', - enl = '', - ens = '', - ja = '', - jal = '', - jas = '', - }, resource_entry_mt) -end - resource_mt.__index = function(t, k) - if type(k) == 'number' then - return dummy(k) - end - local res = slots[t] and slots[t]:contains(k) and resource_group:endapply(k) if not res then From 6088a175052d96e6a095f940223f088eda131c91 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Sat, 20 Oct 2018 00:59:06 +0200 Subject: [PATCH 0205/1002] Fixed double quote escaping --- addons/libs/xml.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/xml.lua b/addons/libs/xml.lua index 72919b471e..075b34e4c6 100644 --- a/addons/libs/xml.lua +++ b/addons/libs/xml.lua @@ -40,7 +40,7 @@ local escapes = T{ ['&'] = 'amp', ['>'] = 'gt', ['<'] = 'lt', - ['"'] = 'quote', + ['"'] = 'quot', ['\''] = 'apos' } From 404eb20f2dd6e7bc75e721db1a51f62a51d9089f Mon Sep 17 00:00:00 2001 From: Sigil Baram Date: Thu, 1 Nov 2018 01:42:59 -0400 Subject: [PATCH 0206/1002] Filter out UC trusts from results Since UC trusts aren't learned in the traditional fashion --- addons/SpellBook/SpellBook.lua | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/addons/SpellBook/SpellBook.lua b/addons/SpellBook/SpellBook.lua index 5cb0d16ad4..311f287e06 100644 --- a/addons/SpellBook/SpellBook.lua +++ b/addons/SpellBook/SpellBook.lua @@ -1,6 +1,6 @@ _addon.name = 'SpellBook' _addon.author = 'SigilBaram' -_addon.version = '1.0.0' +_addon.version = '1.0.1' _addon.commands = {'spellbook','spbk'} require('tables') @@ -199,9 +199,12 @@ function spells_by_type(player, spell_type, learnable_only) for spell_id,spell in pairs(res.spells) do if ((spell_type.type == 'all' and spell.type ~= 'Trust') or - spell.type == spell_type.type) and not table.empty(spell.levels) and - not player_spells[spell_id] and (is_learnable(player, spell) or - not learnable_only) and not spell.unlearnable then + spell.type == spell_type.type) and + not table.empty(spell.levels) and + not player_spells[spell_id] and + (is_learnable(player, spell) or not learnable_only) and + not (spell_type.type == 'Trust' and spell.name:match('.*%(UC%)')) and + not spell.unlearnable then missing_spells:append(format_spell(spell)) spell_count = spell_count + 1 From b39105462bcbcf5c3aae2dc121fbe5651328ca02 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Tue, 6 Nov 2018 05:04:49 +0100 Subject: [PATCH 0207/1002] Treasury: Adjusted for multiply occurring items --- addons/Treasury/Treasury.lua | 38 +++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/addons/Treasury/Treasury.lua b/addons/Treasury/Treasury.lua index 773e207159..64f785a9ad 100644 --- a/addons/Treasury/Treasury.lua +++ b/addons/Treasury/Treasury.lua @@ -19,22 +19,39 @@ defaults.Verbose = false settings = config.load(defaults) -ids = T{} +all_ids = T{} for item in res.items:it() do - ids[item.name:lower()] = item.id - ids[item.name_log:lower()] = item.id + local name = item.name:lower() + if not all_ids[name] then + all_ids[name] = S{} + end + local name_log = item.name_log:lower() + if not all_ids[name_log] then + all_ids[name_log] = S{} + end + all_ids[name]:add(item.id) + all_ids[name_log]:add(item.id) end -s = S{'pass', 'lot', 'drop'} code = {} code.pass = S{} code.lot = S{} code.drop = S{} +local flatten = function(s) + return s:reduce(function(s1, s2) + return s1 + s2 + end, S{}) +end + +local extract_ids = function(names) + return flatten(names:map(table.get+{all_ids} .. string.lower)) +end + config.register(settings, function(settings_table) - code.pass = settings_table.Pass:map(table.get+{ids} .. string.lower) - code.lot = settings_table.Lot:map(table.get+{ids} .. string.lower) - code.drop = settings_table.Drop:map(table.get+{ids} .. string.lower) + code.pass = extract_ids(settings_table.Pass) + code.lot = extract_ids(settings_table.Lot) + code.drop = extract_ids(settings_table.Drop) end) lotpassdrop_commands = T{ @@ -143,7 +160,7 @@ function find_id(name) return S{4096, 4097, 4098, 4099, 4100, 4101, 4102, 4103} else - return S(ids:key_filter(windower.wc_match-{name})) + return flatten(S(all_ids:key_filter(windower.wc_match-{name}))) end end @@ -228,7 +245,7 @@ windower.register_event('addon command', function(command1, command2, ...) error('No items found that match: %s':format(name)) return end - lotpassdrop(command1, command2, ids) + lotpassdrop(command1, command2, ids) if global then windower.send_ipc_message('treasury %s %s %s':format(command1, command2, ids:concat(' '))) @@ -320,12 +337,11 @@ windower.register_event('addon command', function(command1, command2, ...) print(' \\cs(255,255,255)autostack [on|off]\\cr - Enables/disables (or toggles) the autostack feature') print(' \\cs(255,255,255)delay \\cr - Allows you to change the delay of actions (default: 0)') - end end) --[[ -Copyright © 2014-2015, Windower +Copyright © 2014-2018, Windower All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: From 06adf8a58682da7b09ef9b33e3540d83775c159f Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Tue, 6 Nov 2018 05:05:10 +0100 Subject: [PATCH 0208/1002] Treasury: Version bump --- addons/Treasury/Treasury.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/Treasury/Treasury.lua b/addons/Treasury/Treasury.lua index 64f785a9ad..6ed443debc 100644 --- a/addons/Treasury/Treasury.lua +++ b/addons/Treasury/Treasury.lua @@ -1,6 +1,6 @@ _addon.name = 'Treasury' _addon.author = 'Ihina' -_addon.version = '1.2.0.2' +_addon.version = '1.2.1.0' _addon.commands = {'treasury', 'tr'} res = require('resources') From 66504a541f811763b47a424a717bc79112de7dab Mon Sep 17 00:00:00 2001 From: Ivaar <7287342+Ivaar@users.noreply.github.com> Date: Sun, 11 Nov 2018 09:20:46 -0800 Subject: [PATCH 0209/1002] Boxdestroyer: Updated message ids for Nov update --- addons/boxdestroyer/messages.lua | 116 +++++++++++++++---------------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/addons/boxdestroyer/messages.lua b/addons/boxdestroyer/messages.lua index 986f4c868d..2a7f65d0c1 100644 --- a/addons/boxdestroyer/messages.lua +++ b/addons/boxdestroyer/messages.lua @@ -1,61 +1,61 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination" for the associated zone IDs - [100] = 8058, - [101] = 7504, - [102] = 7909, - [103] = 8084, - [104] = 8649, - [105] = 7700, - [106] = 8074, - [107] = 7535, - [108] = 7604, - [109] = 8467, - [110] = 7591, - [111] = 8568, - [112] = 8170, - [113] = 7927, - [114] = 7769, - [115] = 7865, - [116] = 7561, - [117] = 7568, - [118] = 8110, - [119] = 8347, - [120] = 7507, - [121] = 8087, - [122] = 7433, - [123] = 7870, - [124] = 7821, - [125] = 7631, - [126] = 8054, - [127] = 7350, - [128] = 7505, - [130] = 7568, - [153] = 11394, - [158] = 7380, - [159] = 8443, - [160] = 7407, - [166] = 10577, - [167] = 10591, - [169] = 7537, - [172] = 7411, - [173] = 10516, - [174] = 11393, - [176] = 7602, - [177] = 11217, - [178] = 11398, - [190] = 8251, - [191] = 8371, - [192] = 7407, - [193] = 8383, - [194] = 8263, - [195] = 7594, - [196] = 8303, - [197] = 7348, - [198] = 8269, - [200] = 7525, - [204] = 7513, - [205] = 11480, - [208] = 8282, - [212] = 10637, - [213] = 10446, + [100] = 8059, + [101] = 7505, + [102] = 7910, + [103] = 8085, + [104] = 8650, + [105] = 7701, + [106] = 8075, + [107] = 7536, + [108] = 7605, + [109] = 8468, + [110] = 7592, + [111] = 8569, + [112] = 8171, + [113] = 7928, + [114] = 7770, + [115] = 7866, + [116] = 7562, + [117] = 7569, + [118] = 8111, + [119] = 8348, + [120] = 7508, + [121] = 8088, + [122] = 7434, + [123] = 7871, + [124] = 7822, + [125] = 7632, + [126] = 8055, + [127] = 7351, + [128] = 7506, + [130] = 7569, + [153] = 11395, + [158] = 7381, + [159] = 8444, + [160] = 7408, + [166] = 10578, + [167] = 10592, + [169] = 7538, + [172] = 7412, + [173] = 10517, + [174] = 11394, + [176] = 7603, + [177] = 11218, + [178] = 11399, + [190] = 8252, + [191] = 8372, + [192] = 7408, + [193] = 8384, + [194] = 8264, + [195] = 7595, + [196] = 8304, + [197] = 7349, + [198] = 8270, + [200] = 7526, + [204] = 7514, + [205] = 11481, + [208] = 8283, + [212] = 10638, + [213] = 10447, } offsets = {greater_less=1, failure=2, success=4, second_even_odd=5, first_even_odd=6, range=7, less=8, greater=9, equal=10, second_multiple=11, first_multiple=12, tool_failure=13} From 5fc48e68d1d3cfff64fef672970064626ed8f935 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Thu, 15 Nov 2018 16:26:21 -0500 Subject: [PATCH 0210/1002] Update checkparam.lua --- addons/checkparam/checkparam.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua index 8949f30d85..f923a23b4f 100644 --- a/addons/checkparam/checkparam.lua +++ b/addons/checkparam/checkparam.lua @@ -176,6 +176,7 @@ end integrate = { --[[integrate same property.information needed for development. @from20020516]] ['quad atk'] = 'quadruple attack', + ['quad attack'] = 'quadruple attack', ['triple atk'] = 'triple attack', ['double atk'] = 'double attack', ['dblatk'] = 'double attack', From c0eae39ef77eb446df11ece2ed4cf41e39e40fa0 Mon Sep 17 00:00:00 2001 From: Jeromy Cannon Date: Sun, 18 Nov 2018 17:40:48 -0600 Subject: [PATCH 0211/1002] corrected spelling --- addons/GearSwap/libs/Mote-Mappings.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/GearSwap/libs/Mote-Mappings.lua b/addons/GearSwap/libs/Mote-Mappings.lua index 68b71000f5..c1b681cd8e 100644 --- a/addons/GearSwap/libs/Mote-Mappings.lua +++ b/addons/GearSwap/libs/Mote-Mappings.lua @@ -234,7 +234,7 @@ areas.Cities = S{ "Bastok Mines", "Metalworks", "Aht Urhgan Whitegate", - "Tavanazian Safehold", + "Tavnazian Safehold", "Nashmau", "Selbina", "Mhaura", From 03081b9dd5b97cab28e58e7a69cc1ade5e877eef Mon Sep 17 00:00:00 2001 From: Ap0gee Date: Sun, 25 Nov 2018 20:51:56 -0500 Subject: [PATCH 0212/1002] Update addons.xml Remove space in addon name to facilitate gui discovery. --- addons/addons.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/addons.xml b/addons/addons.xml index 21901caada..534f46eb7a 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -336,7 +336,7 @@ https://discord.gg/b275nMv - Mount Muzzle + MountMuzzle Sjshovan (Apogee) Change or remove the default mount music. https://github.com/Windower/Lua/issues From 07b195402dcd5fb5ff23487f93f0888caf54a877 Mon Sep 17 00:00:00 2001 From: mujihina Date: Thu, 29 Nov 2018 17:11:22 -0800 Subject: [PATCH 0213/1002] Update slips.lua Add missing items: - slip 02 +11 items (unity shirts) - slip22 +8 - slip23 +4 --- addons/libs/slips.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 841aa5247e..b6dfd6e304 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -14,7 +14,7 @@ slips.default_storages = {'inventory', 'safe', 'storage', 'locker', 'satchel', ' slips.storages = L{29312, 29313, 29314, 29315, 29316, 29317, 29318, 29319, 29320, 29321, 29322, 29323, 29324, 29325, 29326, 29327, 29328, 29329, 29330, 29331, 29332, 29333, 29334, 29335, 29336, 29337, 29338,} slips.items = { [slips.storages[1]] = L{16084, 14546, 14961, 15625, 15711, 16085, 14547, 14962, 15626, 15712, 16086, 14548, 14963, 15627, 15713, 16087, 14549, 14964, 15628, 15714, 16088, 14550, 14965, 15629, 15715, 16089, 14551, 14966, 15630, 15716, 16090, 14552, 14967, 15631, 15717, 16091, 14553, 14968, 15632, 15718, 16092, 14554, 14969, 15633, 15719, 16093, 14555, 14970, 15634, 15720, 16094, 14556, 14971, 15635, 15721, 16095, 14557, 14972, 15636, 15722, 16096, 14558, 14973, 15637, 15723, 16097, 14559, 14974, 15638, 15724, 16098, 14560, 14975, 15639, 15725, 16099, 14561, 14976, 15640, 15726, 16100, 14562, 14977, 15641, 15727, 16101, 14563, 14978, 15642, 15728, 16102, 14564, 14979, 15643, 15729, 16103, 14565, 14980, 15644, 15730, 16106, 14568, 14983, 15647, 15733, 16107, 14569, 14984, 15648, 15734, 16108, 14570, 14985, 15649, 15735, 16602, 17741, 18425, 18491, 18588, 18717, 18718, 18850, 18943, 16069, 14530, 14940, 15609, 15695, 16062, 14525, 14933, 15604, 15688, 16064, 14527, 14935, 15606, 15690, 18685, 18065, 17851, 18686, 18025, 18435, 18113, 17951, 17715, 18485, 18408, 18365, 18583, 18417, 18388, 16267, 16268, 16269, 16228, 16229, 15911, 15799, 15800, 15990, 17745, 18121, 16117, 14577, 17857}, -- 168 - [slips.storages[2]] = L{12421, 12549, 12677, 12805, 12933, 13911, 14370, 14061, 14283, 14163, 12429, 12557, 12685, 12813, 12941, 13924, 14371, 14816, 14296, 14175, 13934, 14387, 14821, 14303, 14184, 13935, 14388, 14822, 14304, 14185, 13876, 13787, 14006, 14247, 14123, 13877, 13788, 14007, 14248, 14124, 13908, 14367, 14058, 14280, 14160, 13909, 14368, 14059, 14281, 14161, 16113, 14573, 14995, 15655, 15740, 16115, 14575, 14997, 15657, 15742, 16114, 14574, 14996, 15656, 15741, 16116, 14576, 14998, 15658, 15743, 12818, 18198, 12946, 18043, 12690, 17659, 12296, 12434, 15471, 15472, 15473, 15508, 15509, 15510, 15511, 15512, 15513, 15514, 17710, 17595, 18397, 18360, 18222, 17948, 18100, 15475, 15476, 15477, 15488, 15961, 14815, 14812, 14813, 15244, 15240, 14488, 14905, 15576, 15661, 15241, 14489, 14906, 15577, 15662, 13927, 14378, 14076, 14308, 14180, 13928, 14379, 14077, 14309, 14181, 10438, 10276, 10320, 10326, 10367, 10439, 10277, 10321, 10327, 10368, 10440, 10278, 10322, 10328, 10369, 10441, 10279, 10323, 10329, 10370}, -- 144 + [slips.storages[2]] = L{12421, 12549, 12677, 12805, 12933, 13911, 14370, 14061, 14283, 14163, 12429, 12557, 12685, 12813, 12941, 13924, 14371, 14816, 14296, 14175, 13934, 14387, 14821, 14303, 14184, 13935, 14388, 14822, 14304, 14185, 13876, 13787, 14006, 14247, 14123, 13877, 13788, 14007, 14248, 14124, 13908, 14367, 14058, 14280, 14160, 13909, 14368, 14059, 14281, 14161, 16113, 14573, 14995, 15655, 15740, 16115, 14575, 14997, 15657, 15742, 16114, 14574, 14996, 15656, 15741, 16116, 14576, 14998, 15658, 15743, 12818, 18198, 12946, 18043, 12690, 17659, 12296, 12434, 15471, 15472, 15473, 15508, 15509, 15510, 15511, 15512, 15513, 15514, 17710, 17595, 18397, 18360, 18222, 17948, 18100, 15475, 15476, 15477, 15488, 15961, 14815, 14812, 14813, 15244, 15240, 14488, 14905, 15576, 15661, 15241, 14489, 14906, 15577, 15662, 13927, 14378, 14076, 14308, 14180, 13928, 14379, 14077, 14309, 14181, 10438, 10276, 10320, 10326, 10367, 10439, 10277, 10321, 10327, 10368, 10440, 10278, 10322, 10328, 10369, 10441, 10279, 10323, 10329, 10370, 25734, 25735, 25736, 25737, 25738, 25739, 25740, 25741, 25742, 25743, 25744}, -- 155 [slips.storages[3]] = L{16155, 11282, 15021, 16341, 11376, 16156, 11283, 15022, 16342, 11377, 16157, 11284, 15023, 16343, 11378, 16148, 14590, 15011, 16317, 15757, 16143, 14591, 15012, 16318, 15758, 16146, 14588, 15009, 16315, 15755, 16147, 14589, 15010, 16316, 15756, 15966, 15967, 19041, 17684, 17685, 11636, 15844, 15934, 16258, 18735, 18734, 16291, 16292, 19042, 15935, 16293, 16294, 15936, 18618, 11588, 11545, 16158, 16159, 16160, 16149, 14583, 15007, 16314, 15751, 16141, 14581, 15005, 16312, 15749, 16142, 14582, 15006, 16313, 15750, 10876, 10450, 10500, 11969, 10600, 10877, 10451, 10501, 11970, 10601, 10878, 10452, 10502, 11971, 10602, 19132, 18551, 11798, 11362, 11363, 11625, 15959, 16259}, -- 97 [slips.storages[4]] = L{12511, 12638, 13961, 14214, 14089, 12512, 12639, 13962, 14215, 14090, 13855, 12640, 13963, 14216, 14091, 13856, 12641, 13964, 14217, 14092, 12513, 12642, 13965, 14218, 14093, 12514, 12643, 13966, 14219, 14094, 12515, 12644, 13967, 14220, 14095, 12516, 12645, 13968, 14221, 14096, 12517, 12646, 13969, 14222, 14097, 13857, 12647, 13970, 14223, 14098, 12518, 12648, 13971, 14099, 14224, 13868, 13781, 13972, 14225, 14100, 13869, 13782, 13973, 14226, 14101, 12519, 12649, 13974, 14227, 14102, 12520, 12650, 13975, 14228, 14103, 15265, 14521, 14928, 15600, 15684, 15266, 14522, 14929, 15601, 15685, 15267, 14523, 14930, 15602, 15686, 16138, 14578, 15002, 15659, 15746, 16139, 14579, 15003, 15660, 15747, 16140, 14580, 15004, 16311, 15748, 16678, 17478, 17422, 17423, 16829, 16764, 17643, 16798, 16680, 16766, 17188, 17812, 17771, 17772, 16887, 17532, 17717, 18702, 17858, 19203, 21461, 21124, 20776, 27786, 27926, 28066, 28206, 28346, 27787, 27927, 28067, 28207, 28347}, -- 138 [slips.storages[5]] = L{15225, 14473, 14890, 15561, 15352, 15226, 14474, 14891, 15562, 15353, 15227, 14475, 14892, 15563, 15354, 15228, 14476, 14893, 15564, 15355, 15229, 14477, 14894, 15565, 15356, 15230, 14478, 14895, 15566, 15357, 15231, 14479, 14896, 15567, 15358, 15232, 14480, 14897, 15568, 15359, 15233, 14481, 14898, 15569, 15360, 15234, 14482, 14899, 15570, 15361, 15235, 14483, 14900, 15362, 15571, 15236, 14484, 14901, 15572, 15363, 15237, 14485, 14902, 15573, 15364, 15238, 14486, 14903, 15574, 15365, 15239, 14487, 14904, 15575, 15366, 11464, 11291, 15024, 16345, 11381, 11467, 11294, 15027, 16348, 11384, 11470, 11297, 15030, 16351, 11387, 11475, 11302, 15035, 16357, 11393, 11476, 11303, 15036, 16358, 11394, 11477, 11304, 15037, 16359, 11395}, -- 105 @@ -34,8 +34,8 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757}, -- 191 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453,}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454,}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839,}, -- 76 : Fancy Shorts is the last - [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25589, 25762, 25763, 25810, 25811, 25869, 25870, 25935, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, }, --160 + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517}, -- 84 + [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25589, 25762, 25763, 25810, 25811, 25869, 25870, 25935, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272}, --164 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330,}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665,}, --115 [slips.storages[26]] = L{23063, 23130, 23197, 23264, 23331, 23064, 23131, 23198, 23265, 23332, 23065, 23132, 23199, 23266, 23333, 23066, 23133, 23200, 23267, 23334, 23067, 23134, 23201, 23268, 23335, 23068, 23135, 23202, 23269, 23336, 23069, 23136, 23203, 23270, 23337, 23070, 23137, 23204, 23271, 23338, 23071, 23138, 23205, 23272, 23339, 23072, 23139, 23206, 23273, 23340, 23073, 23140, 23207, 23274, 23341, 23074, 23141, 23208, 23274, 23342, 23075, 23142, 23209, 23276, 23343, 23076, 23143, 23210, 23277, 23344, 23077, 23144, 23211, 23278, 23345, 23078, 23145, 23212, 23279, 23346, 23079, 23146, 23213, 23280, 23347, 23080, 23147, 23214, 23281, 23348, 23081, 23148, 23215, 23282, 23349, 23082, 23149, 23216, 23283, 23350, 23083, 23150, 23217, 23284, 23351, 23084, 23151, 23218, 23285, 23352,}, --110 From c1313fdb40dd50aa9da1758caeee18669000bb4b Mon Sep 17 00:00:00 2001 From: mujihina Date: Tue, 11 Dec 2018 00:54:43 -0800 Subject: [PATCH 0214/1002] Update slips.lua Dec update: Storage Slip 22: Karakul Cap / Aern Dagger / Aern Sword / Aern Axe / Aern Spear / Aern Staff (*NOT INCLUDED IN CHANGE) Storage Slip 23: Qutrub Knife Qutrub knife does not exist in current items database, so not adding it to slip23 for now. --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index b6dfd6e304..ef06644cb0 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757}, -- 191 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453,}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454,}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517}, -- 84 + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065,}, -- 90 [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25589, 25762, 25763, 25810, 25811, 25869, 25870, 25935, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272}, --164 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330,}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665,}, --115 From 89ffcc9ab0f9b20b8d11e402eea3dd69284f6dd1 Mon Sep 17 00:00:00 2001 From: mujihina Date: Tue, 11 Dec 2018 14:42:00 -0800 Subject: [PATCH 0215/1002] Update slips.lua Slip 23: add Qutrub Knife --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index ef06644cb0..22e0c7befa 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -35,7 +35,7 @@ slips.items = { [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453,}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454,}, -- 110 [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065,}, -- 90 - [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25589, 25762, 25763, 25810, 25811, 25869, 25870, 25935, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272}, --164 + [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25589, 25762, 25763, 25810, 25811, 25869, 25870, 25935, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576,}, --165 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330,}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665,}, --115 [slips.storages[26]] = L{23063, 23130, 23197, 23264, 23331, 23064, 23131, 23198, 23265, 23332, 23065, 23132, 23199, 23266, 23333, 23066, 23133, 23200, 23267, 23334, 23067, 23134, 23201, 23268, 23335, 23068, 23135, 23202, 23269, 23336, 23069, 23136, 23203, 23270, 23337, 23070, 23137, 23204, 23271, 23338, 23071, 23138, 23205, 23272, 23339, 23072, 23139, 23206, 23273, 23340, 23073, 23140, 23207, 23274, 23341, 23074, 23141, 23208, 23274, 23342, 23075, 23142, 23209, 23276, 23343, 23076, 23143, 23210, 23277, 23344, 23077, 23144, 23211, 23278, 23345, 23078, 23145, 23212, 23279, 23346, 23079, 23146, 23213, 23280, 23347, 23080, 23147, 23214, 23281, 23348, 23081, 23148, 23215, 23282, 23349, 23082, 23149, 23216, 23283, 23350, 23083, 23150, 23217, 23284, 23351, 23084, 23151, 23218, 23285, 23352,}, --110 From 0657d69136f1186139c37d9df6c5f3fd44f9ce06 Mon Sep 17 00:00:00 2001 From: thelostsoul Date: Sat, 22 Dec 2018 13:16:20 -0500 Subject: [PATCH 0216/1002] fixes #1723 - correcting wrong "current_job" static variable use --- addons/battlemod/battlemod.lua | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index 2af118c68d..be21ae31fb 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -54,7 +54,7 @@ windower.register_event('addon command', function(command, ...) cancelmulti = not cancelmulti windower.add_to_chat(121,'Battlemod: Multi-canceling flipped! - '..tostring(cancelmulti)) elseif command:lower() == 'reload' then - options_load() + reload() elseif command:lower() == 'unload' then windower.send_command('@lua u battlemod') elseif command:lower() == 'simplify' then @@ -143,6 +143,11 @@ function flip_block_cannot() block_cannot = not block_cannot end +function reload() + current_job = 'NONE' + options_load() +end + function options_load() if windower.ffxi.get_player() then Self = windower.ffxi.get_player() @@ -198,7 +203,7 @@ function options_load() end function filterload(job) - if Current_job == job then return end + 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) @@ -210,7 +215,7 @@ function filterload(job) config.save(filter) windower.add_to_chat(4,'Loaded default Battlemod filters') end - Current_job = job + current_job = job end ActionPacket.open_listener(parse_action_packet) From 4ee0614357b6bec02a8abc653a1e8ed91a7e1dd4 Mon Sep 17 00:00:00 2001 From: Michael Harrington Date: Wed, 2 Jan 2019 11:20:09 -0500 Subject: [PATCH 0217/1002] inlining reload function for consistency --- addons/battlemod/battlemod.lua | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index be21ae31fb..c33a506071 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -54,7 +54,8 @@ windower.register_event('addon command', function(command, ...) cancelmulti = not cancelmulti windower.add_to_chat(121,'Battlemod: Multi-canceling flipped! - '..tostring(cancelmulti)) elseif command:lower() == 'reload' then - reload() + current_job = 'NONE' + options_load() elseif command:lower() == 'unload' then windower.send_command('@lua u battlemod') elseif command:lower() == 'simplify' then @@ -143,11 +144,6 @@ function flip_block_cannot() block_cannot = not block_cannot end -function reload() - current_job = 'NONE' - options_load() -end - function options_load() if windower.ffxi.get_player() then Self = windower.ffxi.get_player() From ecfefe85d2894d052897945334a5925edebf067b Mon Sep 17 00:00:00 2001 From: Sjshovan Date: Sat, 5 Jan 2019 08:04:59 -0500 Subject: [PATCH 0218/1002] Increment version to 0.9.5 Fix: Client sometimes crashes/locks when exiting game. Update: Silent muzzle song id changed to help prevent future game updates from overriding. Update: README Known Issues updated. Update: README TODOS updated. --- addons/MountMuzzle/README.md | 17 ++++++++++++----- addons/MountMuzzle/constants.lua | 2 +- addons/MountMuzzle/mountmuzzle.lua | 7 ++----- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/addons/MountMuzzle/README.md b/addons/MountMuzzle/README.md index 84c3891442..6345213471 100644 --- a/addons/MountMuzzle/README.md +++ b/addons/MountMuzzle/README.md @@ -1,5 +1,5 @@ **Author:** [Sjshovan (Apogee)](https://github.com/Ap0gee) -**Version:** v0.9.4 +**Version:** v0.9.5 # Mount Muzzle @@ -39,7 +39,7 @@ ___ 2. Click on `Releases`. 3. Click on the `Source code (zip)` link within the latest release to download. 4. Extract the zipped folder to `Windower4/addons/`. -5. Rename the folder to remove the version tag (`-v0.9.4`). The folder should be named `MountMuzzle`. +5. Rename the folder to remove the version tag (`-v0.9.5`). The folder should be named `MountMuzzle`. ___ ### Aliases @@ -163,6 +163,12 @@ ___ ___ ### Change Log +**v0.9.5** - 1/05/2019 +- **Fix:** Client sometimes crashes/locks when exiting game. +- **Update:** Silent muzzle song id changed to help prevent future game updates from overriding. +- **Update:** README Known Issues updated. +- **Update:** README TODOS updated. + **v0.9.4** - 9/06/2018 - **Fix:** Music wouldn't change if addon loaded while on mount. - **Fix:** Music wouldn't change if addon unloaded while on mount. @@ -182,7 +188,7 @@ ___ **v0.9.3** - 5/31/2018 - **Remove:** Removed /data/settings.xml file. -- **Update:** licences now display correct author name. +- **Update:** Licences now display correct author name. - **Update:** helpers.lua now requires only colors from constants.lua. - **Update:** constants.lua now returns table of globals for modular support. - **Update:** mountmuzzle.lua refactored in attempt to meet merge criteria. @@ -214,13 +220,14 @@ ___ - **Issue:** If Mount Muzzle is selected to automatically load and the player is mounted upon login, there is a significant delay before the chosen music will begin to play. - **Issue:** Upon changing zones the default music can be heard for a moment before the chosen music begins to play. -- **Issue:** Unable to correctly set mount music to original if Mount Muzzle is unloaded while mounted. - +- **Issue:** Unable to correctly set mount music to original if Mount Muzzle is unloaded while mounted. +- **Issue:** Unable to alter mount music upon addon unload through the Windower `exit` command, which causes client to crash. No known viable alternatives. ___ ### TODOs - **TODO:** Investigate alternative methods for music change as packet injection/swap allows the player to hear the default music upon zone change and login, regardless of chosen music. - **TODO:** Investigate methods for determining which mount type the player is on when loading/unloading Mount Muzzle. +- **TODO:** Investigate ways to prevent packet injection client crash/lock within unload event if triggered through Windower `exit` command. ___ ### License diff --git a/addons/MountMuzzle/constants.lua b/addons/MountMuzzle/constants.lua index b39385dbb3..dfd66a7d6c 100644 --- a/addons/MountMuzzle/constants.lua +++ b/addons/MountMuzzle/constants.lua @@ -58,7 +58,7 @@ player = { music = { songs = { - silent = 91, + silent = 9999, mount = 84, chocobo = 212, zone = 0, diff --git a/addons/MountMuzzle/mountmuzzle.lua b/addons/MountMuzzle/mountmuzzle.lua index 2c76959545..95ab08037b 100644 --- a/addons/MountMuzzle/mountmuzzle.lua +++ b/addons/MountMuzzle/mountmuzzle.lua @@ -29,7 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'Mount Muzzle' _addon.description = 'Change or remove the default mount music.' _addon.author = 'Sjshovan (Apogee) sjshovan@gmail.com' -_addon.version = '0.9.4' +_addon.version = '0.9.5' _addon.commands = {'mountmuzzle', 'muzzle', 'mm'} local _logger = require('logger') @@ -175,10 +175,6 @@ windower.register_event('login', 'load', 'zone change', function() tryInject() end) -windower.register_event('unload', function() - injectMusic(music.types.mount, muzzles.zone.song) -end) - windower.register_event('addon command', function(command, ...) if command then command = command:lower() @@ -230,6 +226,7 @@ windower.register_event('addon command', function(command, ...) elseif command == 'unload' or command == 'u' then respond = true response_message = 'Thank you for using Mount Muzzle. Goodbye.' + injectMusic(music.types.mount, muzzles.zone.song) windower.send_command('lua unload mountmuzzle') elseif command == 'about' or command == 'a' then From 6239a64ccf9071e42943a40b875c9f311671a4b5 Mon Sep 17 00:00:00 2001 From: coldmix <3292347+coldmix@users.noreply.github.com> Date: Sun, 6 Jan 2019 09:06:37 +0800 Subject: [PATCH 0219/1002] Add HQ Crystal toggle --- addons/craft/craft.lua | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/addons/craft/craft.lua b/addons/craft/craft.lua index aa8dc4c09c..ab8a2940b7 100644 --- a/addons/craft/craft.lua +++ b/addons/craft/craft.lua @@ -56,6 +56,7 @@ local display = false local jiggle = false local support = false local zone = nil +local hqsynth = false local conditions = { move = false, @@ -120,6 +121,17 @@ local clusters = { ['Dark Crystal'] = 'Dark Cluster', } +local hqcrystal = { + ['Fire Crystal'] = 'Inferno Crystal', + ['Ice Crystal'] = 'Glacier Crystal', + ['Wind Crystal'] = 'Cyclone Crystal', + ['Earth Crystal'] = 'Terra Crystal', + ['Lightng. Crystal'] = 'Plasma Crystal', + ['Water Crystal'] = 'Torrent Crystal', + ['Light Crystal'] = 'Aurora Crystal', + ['Dark Crystal'] = 'Twilight Crystal', +} + local help_commands = [[ craft - Command List: 1. help - Displays this message. @@ -170,6 +182,7 @@ local help_commands_2 = [[ also displayed.) 14. display - Toggles whether outgoing crafting packets are displayed in the chat log. +15. hqcrystal - Toggle whether to use HQ Crystal ]] local help_notes = [[ @@ -421,7 +434,11 @@ local function build_recipe(item) inventory = windower.ffxi.get_items() appropriated = {} local p = packets.new('outgoing', 0x096) - local id, index = fetch_ingredient(recipe['crystal']) + local crystal = recipe['crystal'] + if hqsynth then + crystal = hqcrystal[crystal] + end + local id, index = fetch_ingredient(crystal) if not index then return id end p['Crystal'] = id p['Crystal Index'] = index @@ -555,6 +572,7 @@ local function handle_status() notice("auto support", support) notice("jiggle", jiggle) notice("queue size", queue:length()) + notice("hq crystal", hqsynth) end local function handle_delay(seconds) @@ -718,6 +736,17 @@ local function handle_find(query, details) end end +local function handle_hqsynth() + if hqsynth then + notice("Disabling HQ Crystal") + hqsynth = false + else + notice("Enabling HQ Crystal") + hqsynth = true + end +end + + handlers['clear'] = handle_clear handlers['repeat'] = handle_repeat handlers['r'] = handle_repeat @@ -734,6 +763,7 @@ handlers['help'] = handle_help handlers['jiggle'] = handle_jiggle handlers['support'] = handle_support handlers['find'] = handle_find +handlers['hqcrystal'] = handle_hqsynth local function handle_command(cmd, ...) local cmd = cmd or 'help' From 312f5748fea09faf307bbbe603a9458fb384c6d1 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Tue, 8 Jan 2019 09:03:43 -0500 Subject: [PATCH 0220/1002] doom ~= Doom --- addons/stna/stna.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/stna/stna.lua b/addons/stna/stna.lua index 2ad76704b5..8401376a5f 100644 --- a/addons/stna/stna.lua +++ b/addons/stna/stna.lua @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'STNA' -_addon.version = '1.07' +_addon.version = '1.08' _addon.author = 'Nitrous (Shiva)' _addon.command = 'stna' @@ -69,7 +69,7 @@ windower.register_event('addon command', function(...) for i = 1, 9 do if statusTable:contains(priority[i]) then windower.send_command('send @others /ma "'..statSpell[priority[i]]..'" '..player['name']) - if priority[i] == 'Doom' then + if priority[i] == 'doom' then windower.send_command('input /item "Holy Water" '..player['name']) --Auto Holy water for doom end return From a1d0555bd5547f8a75d45967367ae17dd85ac0bc Mon Sep 17 00:00:00 2001 From: mujihina Date: Sat, 12 Jan 2019 17:18:34 -0800 Subject: [PATCH 0221/1002] Update slips.lua Slip22: Floral Hagoita Slip23: Za'Dha Chopper --- addons/libs/slips.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 22e0c7befa..129214b02a 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,8 +34,8 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757}, -- 191 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453,}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454,}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065,}, -- 90 - [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25589, 25762, 25763, 25810, 25811, 25869, 25870, 25935, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576,}, --165 + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039,}, -- 91 + [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25589, 25762, 25763, 25810, 25811, 25869, 25870, 25935, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761,}, --166 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330,}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665,}, --115 [slips.storages[26]] = L{23063, 23130, 23197, 23264, 23331, 23064, 23131, 23198, 23265, 23332, 23065, 23132, 23199, 23266, 23333, 23066, 23133, 23200, 23267, 23334, 23067, 23134, 23201, 23268, 23335, 23068, 23135, 23202, 23269, 23336, 23069, 23136, 23203, 23270, 23337, 23070, 23137, 23204, 23271, 23338, 23071, 23138, 23205, 23272, 23339, 23072, 23139, 23206, 23273, 23340, 23073, 23140, 23207, 23274, 23341, 23074, 23141, 23208, 23274, 23342, 23075, 23142, 23209, 23276, 23343, 23076, 23143, 23210, 23277, 23344, 23077, 23144, 23211, 23278, 23345, 23078, 23145, 23212, 23279, 23346, 23079, 23146, 23213, 23280, 23347, 23080, 23147, 23214, 23281, 23348, 23081, 23148, 23215, 23282, 23349, 23082, 23149, 23216, 23283, 23350, 23083, 23150, 23217, 23284, 23351, 23084, 23151, 23218, 23285, 23352,}, --110 From 4b8e1ed913e6da88c03bdce7219359418d6727e1 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Mon, 14 Jan 2019 20:36:57 -0700 Subject: [PATCH 0222/1002] PC Update Indi Bubble Modified incoming 0x00D to label the byte for Geomancy indi bubble effect (previously unknown) --- addons/libs/packets/fields.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index b8094a4fe7..c19701312b 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1361,7 +1361,8 @@ fields.incoming[0x00D] = L{ {ctype='unsigned char', label='Linkshell Green'}, -- 25 {ctype='unsigned char', label='Linkshell Blue'}, -- 26 {ctype='unsigned char', label='_unknown5'}, -- 27 Probably junk from the LS color dword - {ctype='data[0x1B]', label='_unknown6'}, -- 28 DSP notes that the 6th bit of byte 54 is the Ballista flag + {ctype='data[0x1A]', label='_unknown6'}, -- 28 DSP notes that the 6th bit of byte 54 is the Ballista flag + {ctype='unsigned char', label='Indi Bubble'}, -- 42 Geomancer (GEO) Indi spell effect on players. 0 is no effect. {ctype='unsigned char', label='Face Flags'}, -- 43 0, 3, 4, or 8 {ctype='data[4]', label='_unknown7'}, -- 44 {ctype='unsigned char', label='Face'}, -- 48 From 4d986c0f3bbf49b8e79b2472baa032dea864774a Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Mon, 14 Jan 2019 21:22:40 -0700 Subject: [PATCH 0223/1002] Update fields.lua --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index c19701312b..8b786c29e5 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1362,7 +1362,7 @@ fields.incoming[0x00D] = L{ {ctype='unsigned char', label='Linkshell Blue'}, -- 26 {ctype='unsigned char', label='_unknown5'}, -- 27 Probably junk from the LS color dword {ctype='data[0x1A]', label='_unknown6'}, -- 28 DSP notes that the 6th bit of byte 54 is the Ballista flag - {ctype='unsigned char', label='Indi Bubble'}, -- 42 Geomancer (GEO) Indi spell effect on players. 0 is no effect. + {ctype='unsigned char', label='Indi Bubble'}, -- 42 Geomancer (GEO) Indi spell effect on players. 0 is no effect. {ctype='unsigned char', label='Face Flags'}, -- 43 0, 3, 4, or 8 {ctype='data[4]', label='_unknown7'}, -- 44 {ctype='unsigned char', label='Face'}, -- 48 From 190b709db594751e37db74fe598f573b4d33c9aa Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Wed, 16 Jan 2019 23:08:52 -0700 Subject: [PATCH 0224/1002] Incoming Currencies 1 (incoming 0x113) Incoming Currencies 1 (incoming 0x113) updated to include crystals and rems tales etc. --- addons/libs/packets/fields.lua | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 8b786c29e5..49511e18f1 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -3589,7 +3589,7 @@ fields.incoming[0x113] = L{ {ctype='signed int', label='Therion Ichor'}, -- A0 {ctype='signed int', label='Allied Notes'}, -- A4 {ctype='unsigned short', label='A.M.A.N. Vouchers Stored'}, -- A8 - {ctype='unsigned short', label='Unity Accolades'}, -- AA + {ctype='unsigned short', label="Login Points"}, -- AA {ctype='signed int', label='Cruor'}, -- AC {ctype='signed int', label='Resistance Credits'}, -- B0 {ctype='signed int', label='Dominion Notes'}, -- B4 @@ -3605,6 +3605,28 @@ fields.incoming[0x113] = L{ {ctype='signed int', label='Voidstones'}, -- C4 {ctype='signed int', label='Kupofried\'s Corundums'}, -- C8 {ctype='unsigned char', label='Moblin Pheromone Sacks'}, -- CC + {ctype='data[1]', label='_unknown2'}, -- CD + {ctype='unsigned char', label="Rems Tale Chapter 1"}, -- CE + {ctype='unsigned char', label="Rems Tale Chapter 2"}, -- CF + {ctype='unsigned char', label="Rems Tale Chapter 3"}, -- D0 + {ctype='unsigned char', label="Rems Tale Chapter 4"}, -- D1 + {ctype='unsigned char', label="Rems Tale Chapter 5"}, -- D2 + {ctype='unsigned char', label="Rems Tale Chapter 6"}, -- D3 + {ctype='unsigned char', label="Rems Tale Chapter 7"}, -- D4 + {ctype='unsigned char', label="Rems Tale Chapter 8"}, -- D5 + {ctype='unsigned char', label="Rems Tale Chapter 9"}, -- D6 + {ctype='unsigned char', label="Rems Tale Chapter 10"}, -- D7 + {ctype='data[8]', label="_unknown3"}, -- D8 + {ctype='signed int', label="Reclamation Marks"}, -- E0 + {ctype='signed int', label='Unity Accolades'}, -- E4 + {ctype='unsigned short', label="Fire Crystals"}, -- E8 + {ctype='unsigned short', label="Ice Crystals"}, -- EA + {ctype='unsigned short', label="Wind Crystals"}, -- EC + {ctype='unsigned short', label="Earth Crystals"}, -- EE + {ctype='unsigned short', label="Lightning Crystals"}, -- E0 + {ctype='unsigned short', label="Water Crystals"}, -- F2 + {ctype='unsigned short', label="Light Crystals"}, -- F4 + {ctype='unsigned short', label="Dark Crystals"}, -- F6 } -- Fish Bite Info From 4983c0ccf0724459297a8389fbcd21519db53ba7 Mon Sep 17 00:00:00 2001 From: Skeith45 Date: Wed, 30 Jan 2019 13:21:51 -0500 Subject: [PATCH 0225/1002] Fix EasyNuke macros for spells requiring spaces --- addons/EasyNuke/EasyNuke.lua | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/addons/EasyNuke/EasyNuke.lua b/addons/EasyNuke/EasyNuke.lua index 3335e1331c..30e37b419b 100644 --- a/addons/EasyNuke/EasyNuke.lua +++ b/addons/EasyNuke/EasyNuke.lua @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'EasyNuke' _addon.author = 'Nyarlko' -_addon.version = '1.0.7' +_addon.version = '1.0.8' _addon.command = "ez" require('sets') @@ -109,7 +109,7 @@ windower.register_event("unhandled command", function (command, arg) if arg > #spell_tables[current_element] then windower.add_to_chat(206,"Invalid Spell.") return end - windower.chat.input("/ma "..current_spell_table[arg].." <"..target_mode..">") + windower.chat.input("/ma \""..current_spell_table[arg].."\" <"..target_mode..">") elseif command == "boomga" or command == "bga" then local current_spell_table = spell_tables[current_element]["ga"] @@ -118,7 +118,7 @@ windower.register_event("unhandled command", function (command, arg) if arg > #spell_tables[current_element]["ga"] or spell_tables[current_element]["ga"] == nil then windower.add_to_chat(206,"Invalid Spell.") return end - windower.chat.input("/ma "..current_spell_table[arg].." <"..target_mode..">") + windower.chat.input("/ma \""..current_spell_table[arg].."\" <"..target_mode..">") elseif command == "boomra" or command == "bra" then local current_spell_table = spell_tables[current_element]["ra"] @@ -127,7 +127,7 @@ windower.register_event("unhandled command", function (command, arg) if arg > #spell_tables[current_element]["ra"] or spell_tables[current_element]["ra"] == nil then windower.add_to_chat(206,"Invalid Spell.") return end - windower.chat.input("/ma "..current_spell_table[arg].." <"..target_mode..">") + windower.chat.input("/ma \""..current_spell_table[arg].."\" <"..target_mode..">") end end) @@ -140,7 +140,7 @@ windower.register_event('addon command', function (command, arg) if arg > #spell_tables[current_element] then windower.add_to_chat(206,"Invalid Spell.") return end - windower.chat.input("/ma "..current_spell_table[arg].." <"..target_mode..">") + windower.chat.input("/ma \""..current_spell_table[arg].."\" <"..target_mode..">") elseif command == "boomga" or command == "bga" then local current_spell_table = spell_tables[current_element]["ga"] @@ -149,7 +149,7 @@ windower.register_event('addon command', function (command, arg) if arg > #spell_tables[current_element]["ga"] or spell_tables[current_element]["ga"] == nil then windower.add_to_chat(206,"Invalid Spell.") return end - windower.chat.input("/ma "..current_spell_table[arg].." <"..target_mode..">") + windower.chat.input("/ma \""..current_spell_table[arg].."\" <"..target_mode..">") elseif command == "boomra" or command == "bra" then local current_spell_table = spell_tables[current_element]["ra"] @@ -158,7 +158,7 @@ windower.register_event('addon command', function (command, arg) if arg > #spell_tables[current_element]["ra"] or spell_tables[current_element]["ra"] == nil then windower.add_to_chat(206,"Invalid Spell.") return end - windower.chat.input("/ma "..current_spell_table[arg].." <"..target_mode..">") + windower.chat.input("/ma \""..current_spell_table[arg].."\" <"..target_mode..">") elseif command == "target" then if arg then From 43289f92b63e53a0ef982a9ffa5a4eca992537cc Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Fri, 8 Feb 2019 21:29:10 +0100 Subject: [PATCH 0226/1002] Fields: Included 0x058 incoming --- addons/libs/packets/fields.lua | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 49511e18f1..6564f46b0b 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2662,6 +2662,13 @@ enums.spawntype = { [0x0A] = 'Self', } +-- Assist Response +fields.incoming[0x058] = L{ + {ctype='unsigned int', label='Player', fn=id}, -- 04 + {ctype='unsigned int', label='Target', fn=id}, -- 08 + {ctype='unsigned short', label='Player Index', fn=index}, -- 0C +} + -- Emote fields.incoming[0x05A] = L{ {ctype='unsigned int', label='Player ID', fn=id}, -- 04 From a847aa366a3b8f95053905596744844915049ebc Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Fri, 8 Feb 2019 21:29:27 +0100 Subject: [PATCH 0227/1002] SetTarget: Initial commit --- addons/SetTarget/SetTarget.lua | 26 ++++++++++++++++++++++++++ addons/addons.xml | 31 +++++++++++++++++++------------ 2 files changed, 45 insertions(+), 12 deletions(-) create mode 100644 addons/SetTarget/SetTarget.lua diff --git a/addons/SetTarget/SetTarget.lua b/addons/SetTarget/SetTarget.lua new file mode 100644 index 0000000000..7d32772e2c --- /dev/null +++ b/addons/SetTarget/SetTarget.lua @@ -0,0 +1,26 @@ +local packets = require('packets') + +_addon.name = 'SetTarget' +_addon.author = 'Arcon' +_addon.commands = {'settarget', 'st'} +_addon.version = '1.0.0.0' + +windower.register_event('addon command', function(id) + id = tonumber(id) + if id == nil then + return + end + + local target = windower.ffxi.get_mob_by_id(id) + if not target then + return + end + + local player = windower.ffxi.get_player() + + packets.inject(packets.new('incoming', 0x058, { + ['Player'] = player.id, + ['Target'] = target.id, + ['Player Index'] = player.index, + })) +end) diff --git a/addons/addons.xml b/addons/addons.xml index 534f46eb7a..ea4208223d 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -51,7 +51,7 @@ Arcon Automatically joins or declines party invites. Configurable with blacklist/whitelist mode and auto-decline settings. https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Leviathan/Arcon + https://discord.gg/b275nMv AutoRA @@ -169,7 +169,7 @@ Arcon Shows the distance to your current target. https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Leviathan/Arcon + https://discord.gg/b275nMv DistancePlus @@ -300,14 +300,14 @@ Arcon Allows opening links to certain websites from within the game, with an optional search parameter. https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Leviathan/Arcon + https://discord.gg/b275nMv Logger Arcon Logs the chat log to a file. https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Leviathan/Arcon + https://discord.gg/b275nMv Lookup @@ -321,7 +321,7 @@ Arcon Automatically passes an item on all accounts if lotted by another. https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Leviathan/Arcon + https://discord.gg/b275nMv MacroChanger @@ -536,12 +536,19 @@ https://github.com/Windower/Lua/issues https://discord.gg/b275nMv + + SetTarget + Arcon + Sets the target to a given ID. + https://github.com/Windower/Lua/issues + https://discord.gg/b275nMv + SpeedChecker Arcon Displays a small box indicating your current movement speed modifier (+/- X%). https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Leviathan/Arcon + https://discord.gg/b275nMv SpellCheck @@ -597,21 +604,21 @@ Arcon Displays information about your current target in memory. https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Leviathan/Arcon + https://discord.gg/b275nMv Text Arcon Allows creating and manipulating on-screen text objects through Windower commands. https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Leviathan/Arcon + https://discord.gg/b275nMv Treasury Arcon Lots or passes items based on configurable lists, drops unwanted items from the inventory and automatically stacks items when they drop. https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Leviathan/Arcon + https://discord.gg/b275nMv thtracker @@ -632,7 +639,7 @@ Arcon Shows a target's HP percentage next to their health bar as well as party/alliance members's TP. https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Leviathan/Arcon + https://discord.gg/b275nMv translate @@ -653,7 +660,7 @@ Arcon Updates and reloads all plugins and addons when typing //update. https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Leviathan/Arcon + https://discord.gg/b275nMv VisibleFavor @@ -681,7 +688,7 @@ Arcon A file-based macro engine https://github.com/Windower/Lua/issues - http://www.ffxiah.com/player/Leviathan/Arcon + https://discord.gg/b275nMv zonetimer From 361e0860ac608055dd1faccee97934c3b70fc7f1 Mon Sep 17 00:00:00 2001 From: Ivaar <7287342+Ivaar@users.noreply.github.com> Date: Sat, 16 Feb 2019 17:06:43 -0800 Subject: [PATCH 0228/1002] Boxdestroyer/Digger: Updated message ids for February --- addons/boxdestroyer/messages.lua | 94 ++++++++++++------------ addons/digger/messages.lua | 120 +++++++++++++++---------------- 2 files changed, 107 insertions(+), 107 deletions(-) diff --git a/addons/boxdestroyer/messages.lua b/addons/boxdestroyer/messages.lua index 2a7f65d0c1..51cf56e9b9 100644 --- a/addons/boxdestroyer/messages.lua +++ b/addons/boxdestroyer/messages.lua @@ -1,61 +1,61 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination" for the associated zone IDs - [100] = 8059, + [100] = 8061, [101] = 7505, - [102] = 7910, - [103] = 8085, - [104] = 8650, - [105] = 7701, - [106] = 8075, - [107] = 7536, - [108] = 7605, - [109] = 8468, - [110] = 7592, - [111] = 8569, - [112] = 8171, + [102] = 7912, + [103] = 8087, + [104] = 8652, + [105] = 7703, + [106] = 8077, + [107] = 7538, + [108] = 7607, + [109] = 8470, + [110] = 7594, + [111] = 8571, + [112] = 8173, [113] = 7928, - [114] = 7770, - [115] = 7866, - [116] = 7562, - [117] = 7569, - [118] = 8111, - [119] = 8348, - [120] = 7508, - [121] = 8088, + [114] = 7772, + [115] = 7868, + [116] = 7564, + [117] = 7571, + [118] = 8113, + [119] = 8350, + [120] = 7510, + [121] = 8090, [122] = 7434, - [123] = 7871, - [124] = 7822, - [125] = 7632, - [126] = 8055, + [123] = 7873, + [124] = 7824, + [125] = 7634, + [126] = 8057, [127] = 7351, [128] = 7506, - [130] = 7569, - [153] = 11395, - [158] = 7381, - [159] = 8444, - [160] = 7408, + [130] = 7570, + [153] = 11396, + [158] = 7382, + [159] = 8445, + [160] = 7409, [166] = 10578, [167] = 10592, - [169] = 7538, + [169] = 7539, [172] = 7412, [173] = 10517, - [174] = 11394, - [176] = 7603, - [177] = 11218, + [174] = 11395, + [176] = 7604, + [177] = 11219, [178] = 11399, - [190] = 8252, - [191] = 8372, - [192] = 7408, - [193] = 8384, - [194] = 8264, - [195] = 7595, - [196] = 8304, - [197] = 7349, - [198] = 8270, - [200] = 7526, - [204] = 7514, - [205] = 11481, - [208] = 8283, + [190] = 8253, + [191] = 8373, + [192] = 7409, + [193] = 8385, + [194] = 8265, + [195] = 7596, + [196] = 8305, + [197] = 7350, + [198] = 8271, + [200] = 7527, + [204] = 7515, + [205] = 11482, + [208] = 8284, [212] = 10638, - [213] = 10447, + [213] = 10448, } offsets = {greater_less=1, failure=2, success=4, second_even_odd=5, first_even_odd=6, range=7, less=8, greater=9, equal=10, second_multiple=11, first_multiple=12, tool_failure=13} diff --git a/addons/digger/messages.lua b/addons/digger/messages.lua index b190591272..8da59e02dc 100644 --- a/addons/digger/messages.lua +++ b/addons/digger/messages.lua @@ -1,61 +1,61 @@ messages = {} -messages[2] = {bayld=7364, ease=7356, fail=7281, full=7279, notes=7363, points=7361, standing=7362, success=6384} -messages[4] = {bayld=7358, ease=7350, fail=7275, full=7273, notes=7357, points=7355, standing=7356, success=6384} -messages[5] = {bayld=7315, ease=7307, fail=7232, full=7230, notes=7314, points=7312, standing=7313, success=6397} -messages[7] = {bayld=7309, ease=7301, fail=7226, full=7224, notes=7308, points=7306, standing=7307, success=6384} -messages[24] = {bayld=7645, ease=7637, fail=7562, full=7560, notes=7644, points=7642, standing=7643, success=6384} -messages[25] = {bayld=7165, ease=7157, fail=7082, full=7080, notes=7164, points=7162, standing=7163, success=6384} -messages[51] = {bayld=7143, ease=7135, fail=7060, full=7058, notes=7142, points=7140, standing=7141, success=6384} -messages[52] = {bayld=7143, ease=7135, fail=7060, full=7058, notes=7142, points=7140, standing=7141, success=6384} -messages[61] = {bayld=7143, ease=7135, fail=7060, full=7058, notes=7142, points=7140, standing=7141, success=6384} -messages[79] = {bayld=7143, ease=7135, fail=7060, full=7058, notes=7142, points=7140, standing=7141, success=6384} -messages[81] = {bayld=7824, ease=7816, fail=7741, full=7739, notes=7823, points=7821, standing=7822, success=6384} -messages[82] = {bayld=7456, ease=7448, fail=7373, full=7371, notes=7455, points=7453, standing=7454, success=6384} -messages[83] = {bayld=7143, ease=7135, fail=7060, full=7058, notes=7142, points=7140, standing=7141, success=6384} -messages[84] = {bayld=7163, ease=7155, fail=7080, full=7078, notes=7162, points=7160, standing=7161, success=6384} -messages[88] = {bayld=7449, ease=7441, fail=7366, full=7364, notes=7448, points=7446, standing=7447, success=6384} -messages[89] = {bayld=7143, ease=7135, fail=7060, full=7058, notes=7142, points=7140, standing=7141, success=6384} -messages[90] = {bayld=7240, ease=7232, fail=7157, full=7155, notes=7239, points=7237, standing=7238, success=6384} -messages[91] = {bayld=7163, ease=7155, fail=7080, full=7078, notes=7162, points=7160, standing=7161, success=6384} -messages[95] = {bayld=7170, ease=7162, fail=7087, full=7085, notes=7169, points=7167, standing=7168, success=6384} -messages[96] = {bayld=7143, ease=7135, fail=7060, full=7058, notes=7142, points=7140, standing=7141, success=6384} -messages[97] = {bayld=7701, ease=7693, fail=7618, full=7616, notes=7700, points=7698, standing=7699, success=6384} -messages[98] = {bayld=7701, ease=7693, fail=7618, full=7616, notes=7700, points=7698, standing=7699, success=6384} -messages[100] = {bayld=7324, ease=7316, fail=7241, full=7239, notes=7323, points=7321, standing=7322, success=6406} -messages[101] = {bayld=7324, ease=7316, fail=7241, full=7239, notes=7323, points=7321, standing=7322, success=6406} -messages[102] = {bayld=7306, ease=7298, fail=7223, full=7221, notes=7305, points=7303, standing=7304, success=6384} -messages[103] = {bayld=7324, ease=7316, fail=7241, full=7239, notes=7323, points=7321, standing=7322, success=6406} -messages[104] = {bayld=7798, ease=7790, fail=7715, full=7713, notes=7797, points=7795, standing=7796, success=6406} -messages[105] = {bayld=7324, ease=7316, fail=7241, full=7239, notes=7323, points=7321, standing=7322, success=6406} -messages[106] = {bayld=7324, ease=7316, fail=7241, full=7239, notes=7323, points=7321, standing=7322, success=6565} -messages[107] = {bayld=7324, ease=7316, fail=7241, full=7239, notes=7323, points=7321, standing=7322, success=6406} -messages[108] = {bayld=7306, ease=7298, fail=7223, full=7221, notes=7305, points=7303, standing=7304, success=6384} -messages[109] = {bayld=7324, ease=7316, fail=7241, full=7239, notes=7323, points=7321, standing=7322, success=6406} -messages[110] = {bayld=7324, ease=7316, fail=7241, full=7239, notes=7323, points=7321, standing=7322, success=6406} -messages[111] = {bayld=7324, ease=7316, fail=7241, full=7239, notes=7323, points=7321, standing=7322, success=6565} -messages[112] = {bayld=7341, ease=7333, fail=7258, full=7256, notes=7340, points=7338, standing=7339, success=6397} -messages[113] = {bayld=7644, ease=7636, fail=7561, full=7559, notes=7643, points=7641, standing=7642, success=6384} -messages[114] = {bayld=7644, ease=7636, fail=7561, full=7559, notes=7643, points=7641, standing=7642, success=6384} -messages[115] = {bayld=7143, ease=7135, fail=7060, full=7058, notes=7142, points=7140, standing=7141, success=6384} -messages[116] = {bayld=7302, ease=7294, fail=7219, full=7217, notes=7301, points=7299, standing=7300, success=6384} -messages[117] = {bayld=7324, ease=7316, fail=7241, full=7239, notes=7323, points=7321, standing=7322, success=6565} -messages[118] = {bayld=7343, ease=7335, fail=7260, full=7258, notes=7342, points=7340, standing=7341, success=6419} -messages[119] = {bayld=7324, ease=7316, fail=7241, full=7239, notes=7323, points=7321, standing=7322, success=6406} -messages[120] = {bayld=7332, ease=7324, fail=7249, full=7247, notes=7331, points=7329, standing=7330, success=6406} -messages[121] = {bayld=7644, ease=7636, fail=7561, full=7559, notes=7643, points=7641, standing=7642, success=6384} -messages[122] = {bayld=7302, ease=7294, fail=7219, full=7217, notes=7301, points=7299, standing=7300, success=6384} -messages[123] = {bayld=7644, ease=7636, fail=7561, full=7559, notes=7643, points=7641, standing=7642, success=6384} -messages[124] = {bayld=7644, ease=7636, fail=7561, full=7559, notes=7643, points=7641, standing=7642, success=6384} -messages[125] = {bayld=7302, ease=7294, fail=7219, full=7217, notes=7301, points=7299, standing=7300, success=6384} -messages[126] = {bayld=7302, ease=7294, fail=7219, full=7217, notes=7301, points=7299, standing=7300, success=6384} -messages[127] = {bayld=7302, ease=7294, fail=7219, full=7217, notes=7301, points=7299, standing=7300, success=6384} -messages[128] = {bayld=7302, ease=7294, fail=7219, full=7217, notes=7301, points=7299, standing=7300, success=6384} -messages[136] = {bayld=7143, ease=7135, fail=7060, full=7058, notes=7142, points=7140, standing=7141, success=6384} -messages[137] = {bayld=7665, ease=7657, fail=7582, full=7580, notes=7664, points=7662, standing=7663, success=6384} -messages[260] = {bayld=7143, ease=7135, fail=7060, full=7058, notes=7142, points=7140, standing=7141, success=6384} -messages[261] = {bayld=7143, ease=7135, fail=7060, full=7058, notes=7142, points=7140, standing=7141, success=6384} -messages[262] = {bayld=7143, ease=7135, fail=7060, full=7058, notes=7142, points=7140, standing=7141, success=6384} -messages[263] = {bayld=7143, ease=7135, fail=7060, full=7058, notes=7142, points=7140, standing=7141, success=6384} -messages[265] = {bayld=7143, ease=7135, fail=7060, full=7058, notes=7142, points=7140, standing=7141, success=6384} -messages[266] = {bayld=7143, ease=7135, fail=7060, full=7058, notes=7142, points=7140, standing=7141, success=6384} -messages[267] = {bayld=7143, ease=7135, fail=7060, full=7058, notes=7142, points=7140, standing=7141, success=6384} +messages[2] = {bayld=7368, ease=7360, fail=7285, full=7283, notes=7367, points=7365, standing=7366, success=6388} +messages[4] = {bayld=7362, ease=7354, fail=7279, full=7277, notes=7361, points=7359, standing=7360, success=6388} +messages[5] = {bayld=7319, ease=7311, fail=7236, full=7234, notes=7318, points=7316, standing=7317, success=6401} +messages[7] = {bayld=7313, ease=7305, fail=7230, full=7228, notes=7312, points=7310, standing=7311, success=6388} +messages[24] = {bayld=7649, ease=7641, fail=7566, full=7564, notes=7648, points=7646, standing=7647, success=6388} +messages[25] = {bayld=7169, ease=7161, fail=7086, full=7084, notes=7168, points=7166, standing=7167, success=6388} +messages[51] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} +messages[52] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} +messages[61] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} +messages[79] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} +messages[81] = {bayld=7828, ease=7820, fail=7745, full=7743, notes=7827, points=7825, standing=7826, success=6388} +messages[82] = {bayld=7460, ease=7452, fail=7377, full=7375, notes=7459, points=7457, standing=7458, success=6388} +messages[83] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} +messages[84] = {bayld=7167, ease=7159, fail=7084, full=7082, notes=7166, points=7164, standing=7165, success=6388} +messages[88] = {bayld=7453, ease=7445, fail=7370, full=7368, notes=7452, points=7450, standing=7451, success=6388} +messages[89] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} +messages[90] = {bayld=7244, ease=7236, fail=7161, full=7159, notes=7243, points=7241, standing=7242, success=6388} +messages[91] = {bayld=7167, ease=7159, fail=7084, full=7082, notes=7166, points=7164, standing=7165, success=6388} +messages[95] = {bayld=7174, ease=7166, fail=7091, full=7089, notes=7173, points=7171, standing=7172, success=6388} +messages[96] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} +messages[97] = {bayld=7705, ease=7697, fail=7622, full=7620, notes=7704, points=7702, standing=7703, success=6388} +messages[98] = {bayld=7705, ease=7697, fail=7622, full=7620, notes=7704, points=7702, standing=7703, success=6388} +messages[100] = {bayld=7328, ease=7320, fail=7245, full=7243, notes=7327, points=7325, standing=7326, success=6410} +messages[101] = {bayld=7328, ease=7320, fail=7245, full=7243, notes=7327, points=7325, standing=7326, success=6410} +messages[102] = {bayld=7310, ease=7302, fail=7227, full=7225, notes=7309, points=7307, standing=7308, success=6388} +messages[103] = {bayld=7328, ease=7320, fail=7245, full=7243, notes=7327, points=7325, standing=7326, success=6410} +messages[104] = {bayld=7802, ease=7794, fail=7719, full=7717, notes=7801, points=7799, standing=7800, success=6410} +messages[105] = {bayld=7328, ease=7320, fail=7245, full=7243, notes=7327, points=7325, standing=7326, success=6410} +messages[106] = {bayld=7328, ease=7320, fail=7245, full=7243, notes=7327, points=7325, standing=7326, success=6569} +messages[107] = {bayld=7328, ease=7320, fail=7245, full=7243, notes=7327, points=7325, standing=7326, success=6410} +messages[108] = {bayld=7310, ease=7302, fail=7227, full=7225, notes=7309, points=7307, standing=7308, success=6388} +messages[109] = {bayld=7328, ease=7320, fail=7245, full=7243, notes=7327, points=7325, standing=7326, success=6410} +messages[110] = {bayld=7328, ease=7320, fail=7245, full=7243, notes=7327, points=7325, standing=7326, success=6410} +messages[111] = {bayld=7328, ease=7320, fail=7245, full=7243, notes=7327, points=7325, standing=7326, success=6569} +messages[112] = {bayld=7345, ease=7337, fail=7262, full=7260, notes=7344, points=7342, standing=7343, success=6401} +messages[113] = {bayld=7648, ease=7640, fail=7565, full=7563, notes=7647, points=7645, standing=7646, success=6388} +messages[114] = {bayld=7648, ease=7640, fail=7565, full=7563, notes=7647, points=7645, standing=7646, success=6388} +messages[115] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} +messages[116] = {bayld=7306, ease=7298, fail=7223, full=7221, notes=7305, points=7303, standing=7304, success=6388} +messages[117] = {bayld=7328, ease=7320, fail=7245, full=7243, notes=7327, points=7325, standing=7326, success=6569} +messages[118] = {bayld=7347, ease=7339, fail=7264, full=7262, notes=7346, points=7344, standing=7345, success=6423} +messages[119] = {bayld=7328, ease=7320, fail=7245, full=7243, notes=7327, points=7325, standing=7326, success=6410} +messages[120] = {bayld=7336, ease=7328, fail=7253, full=7251, notes=7335, points=7333, standing=7334, success=6410} +messages[121] = {bayld=7648, ease=7640, fail=7565, full=7563, notes=7647, points=7645, standing=7646, success=6388} +messages[122] = {bayld=7306, ease=7298, fail=7223, full=7221, notes=7305, points=7303, standing=7304, success=6388} +messages[123] = {bayld=7648, ease=7640, fail=7565, full=7563, notes=7647, points=7645, standing=7646, success=6388} +messages[124] = {bayld=7648, ease=7640, fail=7565, full=7563, notes=7647, points=7645, standing=7646, success=6388} +messages[125] = {bayld=7306, ease=7298, fail=7223, full=7221, notes=7305, points=7303, standing=7304, success=6388} +messages[126] = {bayld=7306, ease=7298, fail=7223, full=7221, notes=7305, points=7303, standing=7304, success=6388} +messages[127] = {bayld=7306, ease=7298, fail=7223, full=7221, notes=7305, points=7303, standing=7304, success=6388} +messages[128] = {bayld=7306, ease=7298, fail=7223, full=7221, notes=7305, points=7303, standing=7304, success=6388} +messages[136] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} +messages[137] = {bayld=7669, ease=7661, fail=7586, full=7584, notes=7668, points=7666, standing=7667, success=6388} +messages[260] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} +messages[261] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} +messages[262] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} +messages[263] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} +messages[265] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} +messages[266] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} +messages[267] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} From 3a50a9e126d13919bafec3fffd7e701b92fd62d0 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Wed, 6 Mar 2019 18:05:48 +0100 Subject: [PATCH 0229/1002] AutoRA: Refactored the code --- addons/AutoRA/AutoRA.lua | 250 ++++++++++++++++----------------------- 1 file changed, 103 insertions(+), 147 deletions(-) diff --git a/addons/AutoRA/AutoRA.lua b/addons/AutoRA/AutoRA.lua index d68d89a914..22d8d03d9f 100644 --- a/addons/AutoRA/AutoRA.lua +++ b/addons/AutoRA/AutoRA.lua @@ -1,4 +1,106 @@ ---Copyright (c) 2013, Banggugyangu +_addon.author = 'Banggugyangu' +_addon.version = '3.0.0' +_addon.commands = {'autora', 'ara'} + +require('functions') +local config = require('config') + +local defaults = { + HaltOnTp = true, + Delay = 1.5 +} + +local settings = config.load(defaults) + +local auto = false +local player_id + +windower.send_command('bind ^d ara start') +windower.send_command('bind !d ara stop') + +local shoot = function() + windower.send_command('input /shoot ') +end + +local start = function() + auto = true + windower.add_to_chat(17, 'AutoRA STARTING~~~~~~~~~~~~~~') + + shoot() +end + +local stop = function() + auto = false + windower.add_to_chat(17, 'AutoRA STOPPING ~~~~~~~~~~~~~~') +end + +local haltontp = function() + settings.HaltOnTp = not settings.HaltOnTp + + if settings.HaltonTp then + windower.add_to_chat(17, 'AutoRA will halt upon reaching 1000 TP') + else + windower.add_to_chat(17, 'AutoRA will no longer halt upon reaching 1000 TP') + end +end + +local check = function() + if not auto then + return + end + + local player = windower.ffxi.get_player() + if not player or not player.target_index then + return + end + + if player.vitals.tp >= 1000 and settings.HaltOnTp then + auto = false + windower.add_to_chat(17, 'AutoRA HALTING AT 1000 TP ~~~~~~~~~~~~~~') + elseif player.status == 1 then + shoot() + end +end + +windower.register_event('action', function(action) + if auto and action.actor_id == player_id and action.category == 2 then + check:schedule(settings.Delay) + end +end) + +windower.register_event('addon command', function(command) + command = command and command:lower() or 'help' + + if command == 'start' then + start() + elseif command == 'stop' then + stop() + elseif command == 'shoot' then + shoot() + elseif command == 'reload' then + setDelay() + elseif command == 'haltontp' then + haltontp() + elseif command == 'help' then + windower.add_to_chat(17, 'AutoRA v' .. _addon.version .. 'commands:') + windower.add_to_chat(17, '//ara [options]') + windower.add_to_chat(17, ' start - Starts auto attack with ranged weapon') + windower.add_to_chat(17, ' stop - Stops auto attack with ranged weapon') + windower.add_to_chat(17, ' haltontp - Toggles automatic halt upon reaching 1000 TP') + windower.add_to_chat(17, ' help - Displays this help text') + windower.add_to_chat(17, ' ') + windower.add_to_chat(17, 'AutoRA will only automate ranged attacks if your status is "Engaged". Otherwise it will always fire a single ranged attack.') + windower.add_to_chat(17, 'To start auto ranged attacks without commands use the key: Ctrl+D') + windower.add_to_chat(17, 'To stop auto ranged attacks in the same manner: Atl+D') + end +end) + +windower.register_event('load', 'login', 'logout', function() + local player = windower.ffxi.get_player() + player_id = player and player.id +end) + +--Copyright © 2013, Banggugyangu --All rights reserved. --Redistribution and use in source and binary forms, with or without @@ -23,149 +125,3 @@ --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. - - -windower.register_event('load',function () - - version = '2.1.2' - delay = 0 - RW_delay = 0 - Ammo_delay = 0 - retrn = 0 - halt_on_tp = true - windower.send_command('unbind ^d') - windower.send_command('unbind !d') - windower.send_command('bind ^d ara start') - windower.send_command('bind !d ara stop') - windower.send_command('alias ara lua c autora') - -end) - -function start() - windower.add_to_chat(17, 'AutoRA STARTING~~~~~~~~~~~~~~') - player = windower.ffxi.get_player() - if player.status == 1 then - auto = 1 - elseif player.status == 0 then - auto = 0 - end - shoot() -end - -function stop() - windower.add_to_chat(17, 'AutoRA STOPPING ~~~~~~~~~~~~~~') - auto = 0 -end - -function shoot() - windower.send_command('input /shoot ') -end - -function shootOnce() - windower.send_command('input /shoot ') -end - ---Function Author: Byrth -function split(msg, match) - local length = msg:len() - local splitarr = {} - local u = 1 - while u <= length do - local nextanch = msg:find(match,u) - if nextanch ~= nil then - splitarr[#splitarr+1] = msg:sub(u,nextanch-match:len()) - if nextanch~=length then - u = nextanch+match:len() - else - u = lengthlua - end - else - splitarr[#splitarr+1] = msg:sub(u,length) - u = length+1 - end - end - return splitarr -end - -function haltontp() - - if halt_on_tp == true then - windower.add_to_chat(17, 'AutoRA will no longer halt upon reaching 1000 TP') - halt_on_tp = false - elseif halt_on_tp == false then - windower.add_to_chat(17, 'AutoRA will halt upon reaching 1000 TP') - halt_on_tp = true - end - -end - -windower.register_event('action',function (act) - local actor = act.actor_id - local category = act.category - local player = windower.ffxi.get_player() - - if ((actor == (player.id or player.index))) then - if category == 2 then - if player.vitals['tp'] < 1000 then - if auto == 1 then - if player.status == 1 then - auto = 1 - elseif player.status == 0 then - auto = 0 - return - end - end - if auto == 1 then - windower.send_command('@wait 1.5;input /shoot ') - elseif auto == 0 then - end - else - if halt_on_tp == true then - windower.add_to_chat(17, 'AutoRA HALTING AT 1000 TP ~~~~~~~~~~~~~~') - return - else - if auto == 1 then - if player.status == 1 then - auto = 1 - elseif player.status == 0 then - auto = 0 - return - end - end - if auto == 1 then - windower.send_command('@wait 1.5;input /shoot ') - elseif auto == 0 then - end - end - end - end - end -end) - ---Function Designer: Byrth -windower.register_event('addon command',function (...) - local term = table.concat({...}, ' ') - local splitarr = split(term,' ') - if splitarr[1]:lower() == 'start' then - start() - elseif splitarr[1]:lower() == 'stop' then - stop() - elseif splitarr[1]:lower() == 'shoot' then - shoot() - elseif splitarr[1]:lower() == 'reload' then - setDelay() - elseif splitarr[1]:lower() == 'haltontp' then - haltontp() - elseif splitarr[1]:lower() == 'help' then - windower.add_to_chat(17, 'AutoRA v'..version..'commands:') - windower.add_to_chat(17, '//ara [options]') - windower.add_to_chat(17, ' start - Starts auto attack with ranged weapon') - windower.add_to_chat(17, ' stop - Stops auto attack with ranged weapon') - windower.add_to_chat(17, ' haltontp - Toggles automatic halt upon reaching 1000 TP') - windower.add_to_chat(17, ' help - Displays this help text') - windower.add_to_chat(17, ' ') - windower.add_to_chat(17, 'AutoRA will only automate ranged attacks if your status is "Engaged". Otherwise it will always fire a single ranged attack.') - windower.add_to_chat(17, 'To start auto ranged attacks without commands use the key: Ctrl+d') - windower.add_to_chat(17, 'To stop auto ranged attacks in the same manner: Atl+d') - end -end) From 15a75bb993fc13e4030b5ea0c3b88572975349be Mon Sep 17 00:00:00 2001 From: joshk6656 Date: Fri, 8 Mar 2019 16:35:50 -0600 Subject: [PATCH 0230/1002] Allow support for unknown levels as ??? in DB --- addons/InfoBar/InfoBar.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/InfoBar/InfoBar.lua b/addons/InfoBar/InfoBar.lua index 8a0eacc5ad..cf71358b52 100644 --- a/addons/InfoBar/InfoBar.lua +++ b/addons/InfoBar/InfoBar.lua @@ -107,7 +107,7 @@ function get_db(target, zones, level) MOB_infobar.spawntime = spawntime or '' if isaggressive == 1 then MOB_infobar.isagressive = 'A' - if levelmax and (level - tonumber(levelmax)) <= 10 then + if levelmax and levelmax ~= '???' and (level - tonumber(levelmax)) <= 10 then box:bold(true) end else From f46c3b54b9f50494d7e7b2f93484bd24c85ce8ca Mon Sep 17 00:00:00 2001 From: joshk6656 Date: Fri, 8 Mar 2019 16:43:23 -0600 Subject: [PATCH 0231/1002] Add Escha mobs to DB. --- addons/InfoBar/database.db | Bin 2088960 -> 3449856 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/addons/InfoBar/database.db b/addons/InfoBar/database.db index d0409b44f3635e8046f400bc2c0fe0bd0634ecd5..2127d6e87d1be30626e5a37564737df981a115cf 100644 GIT binary patch delta 645986 zcmZ^M2S8KT{{K1mX5D)UNeCf?kc5bcsECMrng^~8H|~_Fs83(jNMqek?bxZO9*=_fGydu}iT@}5%=hvB>?5|7t;4J6WjcCC zi8u-%8|UNC27`bP7M_d0W~=y)xIvsEW(t1@?+Ay48expkng7Ax=DYbqp36t@WcCAl zgB@lY*>u*If5K71>(p~hf?J2XSIJ`&+6%f@sK-Kkiu&ed8k=EvN?j6WCCtL()Ad_Y zS_`_TXk3~*P5u5PU3$ZvqBh%@K>1(9IOvzpW32e1pGQak&^sw_nm)mVM?;RjZ#ES? zDJD_Jd-RemeM!os6-x^%%WPlRzF^Go4&Cy9x;8TIj&{-yN)rTH)hE$Sm+ukG#s+r- z-fyPa-zPXxv|#}S?zOwA(+hD5ee!&qNiDyyt-fn2@l>8bCsMdYZNV5i^_|{9XWGT8 zkGi*M`{+a`?KLMT#y&zHym>Kr%<7=L&kQbut}I=jokq6bV&duG6@8qb8&8*q+S?nl9c1IeFbO=qo6~E`umIT0}1j7)< z_)Mf%Q0|{d$SW*BdKoYPH2_u|j&e|k?hm{Z@$Ofo3cN=*#fiAD!NM`*0s1EtgoR{4 z<@%Ml?}k|buy7mFQM_-&yLXUjJMPco{!YBlN5Sin?m(XB(I^9cajy&E_cxR|7I2-B zzCk`e(!Y>*5T17;y^Z|1uMrLacsCxNLP8<>uaS-e7=??3`y(g_%Y`jNT8E6A@V*+q zp96jZ?x!H3F}gE=RY&AJDk;T1Di9YUPa)D*fc2n57zN%6X*r(9A)RA2Oq`7j7%#&c z$S@D70{5syKOcZ6@%$mu3{;@@{3g85#&3H(A4UN^@a+q{n}g?%@mz*VeqoGZ8bqu! z-Ti=7^LNEJbWFq)=rN5VI%?PjxE+`qeK~H_A^8q3ZMZ*(^f=OKWa@-M8gc&-z6VK~LR@og`DAHnbYC=4T`TY|I}aL4f; z4bpKWENC4n)U`qfus}IrjTj|^x-S00`w^IbJ$h$STT+6LXoz?L1?~XAT)exCcmKez zfcM9cVGq(iq`QzXO1g)UjvzmV)uczlw3wWDhfe7}L0&Y{h@E5HkMu0wZ9&?`m@*OQ z&5xAG%9+{6SPWWdjzdE4&B;jE3FdU9Hb~eJ=2RpV#*5?u`~ygUlQZ#)3eE9I7-Dl< zJY)D{)MpD)ED}0r#z>eIB)Kj(aYu|Si0_4L)05BfP|Eb==Q*V$^4@JS#3hSM=FF-p zEUlPTRWPTda8~ComVsx@e$g$KmX|H5Dy+og-BxRGwq&rDFmaQZAnX#-_#xhly+s#G zeG@HncQ|}3-REh~aoO#Z{V$K5&MY-~>4H;dZ`EJBFu0fy#^x7S7V^R!@mh|o8*=!_ z_n}T{KeV!ZNtFuzzgczVJM3E4K{sUW`*-y$-4Uk&_l*FzU1l0%2p3A#%S@Z3l{>5& zKu=03HFc-pL*_WzzTRaD)s&dbyp36`V+Mw?b_%}>Wqc!V&o*N=D^E^GE|)zgQtYk2 zx(7syefn2-3N`TLKgca6e-Rq_i#wI;(3Nsp{HuGB9rJ<`bC{UNa)e_-4j;$JR^&{v zEZEV;$GWn`Z7$eSeE{)5JeKL-h*|miQRmx!H7^q~Fom#~dzq zdkPp0E|NBxt{MaG9i8x!>P{rbhkn>#dW<{5Ls!SdNx~CCM}9X?WOW$4DzDcX2xRSO zm%`FL9&Ji&G-H(4pLuY;kNG@{!#@sxxVPG0{K01HZVoTWQPm|&iYT+ew1JjwGi{{* zY&C76*;`GU==m+CJ>=SAdLY=vtefrx#~~gRYsJ~(KrvbPQFuwXN2nDh3F%-^-r*1N zT0WU)0b{-g${AqO#WO;IaI-K%=qqFkiGoQ0{otpub9R)0c^FtyykyC!qT>wywj=HmPqZ#JFWCxzOxOT z$#;6`aK5vZT5BTRneVjG?0jcyTCBt4Nn?ympBQ2+y=5#7C+p3`GvYmBwK!7r2;T{> zqx?0(G$BWb;s53@^Zoo*p3hUj8oYufRl<7f^RUp=qVAziISH}S*y6H<1va0w&qpOpI=xRc{|TIFFY0>W+zzH zVeCmc*$HW6$xeu&?+h`m=-W;SvFhZ7he4TCP+3`AUTIlqSr~3T2FFf|J0*0azjT=Y zZN`{bD$>RH!=u*U7-MO#E_*$DjEU`p@%<$E}+MtOsZLSiqwGwcGte!fTt}*=`>! zbnQ-ym)LV?be&x>r5v2;V+(imqp@4#oOGB>H_^{Q(_J(tXlkTQji&eMc!TMDaHq+U z+?j#kG+&hmCt&9~&4YNrad1i~d#C9$k^f58A1!S{z3w!C2}hI!uwZH#|`F(nAlO+EBJUZ zdkDKZ(NnJr^a+%OHW_#|59M-h<&72mT=0-d*G#QvPw2p>uwH_|5AtbTVNa-> z&ox&ddB`G61IE{()-8!rlUSJAFJTkW0QUjNX0gA*gfDvVQD zN%4ZBsPkCDaiSZB6|iC0)-y=i(E zfvu_UGrdDk2PB|e2p2#ULrMxu3(KksO3XGfRm@#bQczw|R9;oQ#4<3~CZ-9w^X8Ql z&P$n4U0PllBh^1UJ>l3h(>saa7#X&@58n%x6jWDMFG(qjps8Bdz-0lL@iz{<*|qcQq;THP_$61x1cw+r46+c6^r@3S8_#nY)z zyhnn0T$ih7JD50G_z(Y#w_`i_?fCl^t8ST*K*f&nDHw2f7(3f|ZSsyuDa`5e_f*FZ zBb2SM61Xz@I|Gj!x-Qy!OUbvqWNfDSq7;#t8SDnDrwgtTxcW-@W6@T$;@ zKhE`RCM#x(TI$0cExzFGDF;$_EWy0lQNUm4OxdA}Z(${bie5Ag7beT%+Yo#vGw}iO zRxuwV%Y}alAz`zyP{7`AMHgwVwE5+nh7S1cEDz9{Iac&{!MnGNK;Al(RHaWVf01kRDWFQes;o{5Johi6Ha>=$8C}uX^ zNf;}=kgiY7q5L}>cG|PiVe^|IKp7wbisQhdIQeb3ZDjAV`D~hxr8(VcTpit1%h(;u zvCTZ@G<6Qa_Z7_dIp~A;OkPWrZ$shg_Myc0Om`XaFbd$b-<+60`#w)J(EIP1+ET~! zrrn`u&zipGIpLYjVB$RCh+yMO*y}8VXR_znROAg`ficq-JyeMuT%&Se?i?z(n&6^6 z7fnet>od~=y7i*ze){B7knR4Tn)ZfXId2-rJE(Ntz=kt%E=abUPr~heAk%eGgohIG z&&PT@Q{Cj>V{yfeDz2Pbuk$gN%bgkNT_DpJPcy$XwTTb+F0#*gVL@e85vNbTFilhW zyh)+{Uz$#Fn)5HT;ib<^ca2raUJ}Go@u;|7oFn!Vox)Gxn(l{gW17%UNak0;JRIX& zu#^UIH~XHQg)p{(m9nwohx}ds9Djh<@s+%QkLA62TRQ(e_tBHzb2riVJe4ZH=V_Gp zJ#R(n-}4Om>k2?VzJd?Oukds#xXkTz_Z9ppyTbi63LkW>_30Tj?h1EM|0_I(bXSnK z><8|lkw5U(^vDl9pDtYHJ!sz#&_cA)r)H}wBZ2l4o7PgkeV4@E&cCs#L}M| z9qn{&^{HLM@4nsWhzr+i{DIr!!*dEDZ7oLsIU$9wXa6FOMXk(XS$-BCUCMRp;%V&H zrYsKzH!`wpSwYpbdPqv`-B@zrCB~hygI@o})IPGrqLaWwo4z)A#8fk1!HjGoFcwCXMRmn7ZhGUA$>bYTURHp8I7oh$HI1f+zcbxVrteJmOO|?wSMA+qKP`US=c1k8 znkqV*c`f$9X~t98Y5tzLQ21Er#@Yi)t)~(dG=Xv&7PwSSTh6&+#1gzR-~^=G*Y<+G|*S2Oo1fnvvwGKaF;3>+`xI zL#M%V#`(PZcA&T}vp=%bAppixN3S={6dg6nzl%FD7i}>jE^}0NK58__Q;Oazgf?XO zA-)xT@_l?;V3zbu+V*{XqEcD7pt^WoVS**WLYuyi??9#B$9vV>b|_5a&D8$;_^#wt z@4mef@1r-=KX+e=Z%@mw#J8gfSK?b!=PM}Ia0PiajQ7LkcssrSLws90@k4xX%h-Css3_&8hv1iO{WBNVo>ZL9N?1BgTD&auOpvPmm6=H zUk^q$!)f+K=4HEH%882Oi$4^d^r2poE#>t&8dQWKBtW$xmqAMSU(oz|NVX_2iqkIY zMW6$tlzPKz7U?;iR7!aU>0?@Hl-7w0>O0b2uQ!`s^?AF|onG(4-~_IVGqIjbT+Qwk zy9kf5p5VfXtUdIpmZJKBKs%}aC;>b5fn=v={z~q3?aBjv<|FI-tCX&}LFc;Kp+o*N z*?mKUc&KlJ^a3aMU&*WK%%90)_5C1yK=*JT*yvV&CeKe)N7BSbs4FK{SS0BAB;dAt z*$D9UJR2)_jE|+-{TY#wJoT#Lpp{;!?TrnZQa>8_$L)?Pl(Z%OrdMhg1&pHo3H77E zfwbTyTQLxJYoC-B9rY1DDJ0FUAA$b4J?-g2uOt^49nvs9oW?n%99j`CmCz`M^nG`= z>3V3sMX%7ne_@~E_C1!(r}L$}kw3=Y;+KR3p{FoaxCNB^bs>-zXmu*r$By+saf%-s ze$*srC79F_c8CsPlOXY_~sAUt1*Li?l1$v6b`|5518rZR9j7 zSt@I%HpK|u1W5W5A)h~qVjjig@oUs80i_-)s5GjZ6cB6tVD*hKIo5?!FGOK<8W};<)>)J{k=>DD#TUxWuEj+{=G`O(R zG`AkA6u?InUVtBz8b(VIwO$0Uu)a_O^hc)nN?WN{WG?D!Iwf+Ep3an(P~S|chMw;r z-9n=}NXuw&hP1t-nN=~F`Ixv*Ol3acnszYy)CeE(4(z;8#KzZ`Vb`=QQf)PN%#vD1 zh)T2_D*Y^AKD$3cR03Q|puL@?)@{*Vd{a46u6Ax7^Vq|D#e{k&yP9)=#;6!|PiHAg z$eVNJ)mLG;MRI}R)t1|(&XPa6E+fSo^XtJ)`aI_5m9B2RH91o1wSa0vCe$y+G`0X< z9DoJET9`C1vA!Awn$j94wh1_bpm?0#HnPP6~3TTH5 zA)V$G7F1L(vJ4E=Z+(0mw9rfr(^oST$Pp;Zz}3fodfX!VjhJ5M6W53aVJ-iZ_lB&P z12xYKHjGu&FGaJdARBV!cMotAwd*Y98v|+ew}OVz_C*rJ(Ed6Tz0yxwA9|~gG=hh= zbdql2Bh__oV7I8U%EQnL+`&F)w?J^qg951u<+3T)E_H@|1GzTUZi8tT)^yN|~8myWg$*EE`mgN6G9178VYZ!|B0^!Z3j zC3M*zlN4K6TvlGTV(z%`oYAG1lj}pnUP?~qp>cUqKTf{!($ksY;x;mIttbndKra)) ziapFcypRWYzUu-H3 zv`JxIU4G)P>FxD*pE@ty8c0*wIdc}xc*~GfU-7JuF1+T_A8UH1BloJ+8(BXlRtayz z!ukTA%pPR@_;}b%9%9pJTZzvp1z0`AtTcx?^y&nuo2Uzz8f z3(|j)V1Qxjx4vxdqiDU`Nx4-{H|1p|*y)ds3B8Pgo|~sZB|ukRhi1Z>X1IsCry5?N zIjs!m4O2ExZvM2-Z+L#kr-u0bOso_B5-RuySQGoX$Qpn)HgSiExmdnK1!k@xy{syGe z)AiQJGOYozp*0qk&#X-taKo1cQs*cYN}MD0x6Els1%Kx=N6E3j+H9wjyOT{M763aO zFOcFRl4S&ysq#-@C8Xrp(mon8TWTP_JNYk4*_FI6-V7_Gk<~MCBm0l=8><)YIvO9Uy9){ zDzSX#QKf%e5cVH&IOv@PQfiWlS0javZ^*!^jlx7KSAn8sM&L}8GFRGWscOI!W6bjtZy@#!QtME^uEiAL= zv6W5WRD3ZikqPjp@-SEau=0}I>g$T_G~;ELtPAMZF`AtNu5W3!*oNdBZlRP+uA^Hk zan~KTp0TL+YVL>LAdwgUX! zZZ-~s-E!U5&_m@X-2K(|+HAa_0W=2^n?`fc{=>IRJ(I8Fo>=kRLVb3(l+xm|>Z-ye zLSRR7|6OFC;%7 zx?Cde5R%MdchJ~-v2xkH!bM>{EPf`|4g4CTm}PM;F_73mU`m!zZl zds<|T2qxkS8^F^+=M!!6fjv_HYnx1e?vZL~;hoZ2TD@0VO?QzrH?%k?bqE_IjqDWT zt9UE%K6tjA5)OmGZfibdnc1)s)Y!|Ffga@m$IVlTD1Bp4Y0*tBkHs?_KCZs z^c$h4Hh@d|+pbyAwHuHu54Af04v8+^DUGvCZh)@V*TV5f>uGlb&Ec~6Dr-mj7(QFv z#%`(0wd?SrEq(Z{E0up2x+jLGi|QnGqc<(QTcUx%#@tuf$$#J@+1+?}femGMupIi= zgVK6B@qlzc6+a|B81mdJnFWWL4*=Eb%fwZ}?`#+AD?B31;dFFLd|S(uMhL~34i=R# zpn7vq)l_eW@A{3x1F4N!Do^6p3`^=7o8pP5S?8s!=&af13S(7jHKnDzuoi8}RByYO zYp4~c^;5jB2qPQmxyK=icFK_y+G{fFDQTLwjX1I~n@&CsJ(u?W^i*$qv8J&j6}&5T zqfP;X9ymj=(xG>yE;RF9sWw<47-GQ9RkDr355g4wH1MH*nKcmC2>!z7XcnCUo09D` z^OTfI1Lhb^(KcV4C-k7_PN4z6o|f(sU5!5KG)M5!s?(5>7Q7(sqOYFE;(PU!v?X}E zL7xsAn|PCO1{?9;utQA3%@xBX4gR?G0lUckK3BJ6~<<<+uBmv6L$A&osX zz;NRn@W}ru$wOsNArKF1`rA!2v6DI?B35mr7$xb&mx{ zb6qE+>SfnjTp@fTOow@?KjiZ3u0TR#KGwF=9o6lfN`q!)>3^im=sMx;^n=A!jg!dt zi{zv9?<5yJ_pLP47*HA~Vwq9?=Tb5mE=j+Ivc8r)To(`<$J5bniHWrJLA#MI{acy` zdlYA;!s(Ju>#^rLV*mGnfoI`vL^9`^i50`?|a|N8+;sEM%XdI1J z3jQ3(Hj2`!ZQ$kbC6jDH=(G0CjnmUlU5v2RPPEg?w#J@*wUv4n2RA`s054=)Slsfu zIgptA%__70eN4k+BM3;HDQq6Hb+b5ZJTRfIAVnRKD26|^9g_PieN4@0DA3-am**NV2i@7%lpUSXFxZT`St%^X)y#}*rB(DZ^|&5vTHQ>w((A!S^*1#WS+%qi zT{zdJ@pSaf$%GFfmhHgJ2KImKc2>3nBkydXc3-VBb%|CnpflV!j!0e!>}=0froAef zUljUym8mrkWiK}!<(lPH$5yHX)(1|YEBR&K9jtQ=OIxgM2B73gA==$F@#av!J9N)u z`4w!aA^+Uu#8Aa*-2*(BY|y0}z~jNvTFAfQi(oM=g7$a~3=wNt7vXN9Xk!A%KQHY3@o!IFX9Wg#Ypd>~~={e@FH8l1EwtuEv>QYi`)*jaMZ%U1+Vd z$yjDQyy{5Z@Rp)R7+%wz&HB(&CfE=*e+TdfdpazpsLrnb=!68Tu&@!R3&71dBm&$q z(rXpUBm_*2GtdMo_^;%kia4W@q^r`^(7ErVxbPSov1Y_25RXRj6VM=T!6Q9tGA<1r zk&JnQF%Y*E3}#wzn<1WNx6_;Md&5o!YPjmLQgLE6w;#T4D`2 z8dXlXMLvA}C#hd_GSJiBbkb&2DC<}0ZrbyUDl7abC2(F(Cx4Q*K|r_)q|z47x57zi zdiJxnd<0p)w!~X*ZUiz&bGo8pji&Q@OO%_{z{3tFuU1)t@hwnvWqy)_{D+gFkYR?nZd7$8J%ne3KH_eeNjkC9jZ63=svv)u`JE9qlmaiy@zm{+R=Fj!ukPdoWKnbOb&xg(avO-fpYeWmXL3$H(fv72gg2 zSL@lBreZN?S9Me1~_bf&){n zH8vqIv+>px*4^Q`4(_T|ZWbK_fU^d=G_Hc$%CL9 zO10|kCRmfjS}4=kKy=@Q5qJrEx{sm1rDWr9ENx%ZP#OHpGblQM+fM47mcot0wC_=y z2ApJb{?0#kS#jAsUc7Or1{~#v0o;ZD`plDXgOjTYtXsSh>HySyjYsVGzk%aRHbVFZ zT%=I6Foz!gL$uQBc}d3W+PY-ppudB3UJGOm=r=-Rf%5u?_W&(^Scd{{7MnE|7f@tBRLNwD&n(8a+2ojHSFuTu-AX;_g2ubXF>k)hWTVI)km9>S(_kI<0oX z9YPXpFJ#*w*ezwjSXEAHwt7CB*fNoeyP%%c@v>|USb`w>X>M~=I9Qt`H%oK-yXm?J zyelaSz2&sE*t=FN4O%JtP%@ZwMab4(;`aY&B~Ox1nsfcGhcaHS*`?V4_NCQ=>RZ6SzW2p8t{QCIw;2 zci#XwH_6j%&y6CTi9ygt*A0MY7I~Y^XHmczL5DV0{^-Q0uEf=gyuRrCL22SLjSYgy za(En+pC`L%VY1v&8X1I{-{o=m$-md=qVuZBEYs~-N9SCg3OcjUd%IzL(5~v~ue5a~ z)13>wIT1V49jY7EH1O9U_#5x!R&0tM9w2-n7}knLSN(QhGoqw|DT0&c_++0opbJ7b z3PoU)W&tdNdiZ2}w8hP^RPL4Q=%Pp7N?SehP1M&T=hNk6d5m~-5K7!un6L_2R_MuO zxtr#pXkfKW93?y@wCDGN!>t9g(E&2*7eb>@3hx^$|AHOk6Q0PVP6@7wH0fn=Go5-# zB8fhE;tRl=NL zA1zCCRY$XA{VnvWAmlw%5M79GFZM>!DxszA6%!T+xHXr@-=6w)lwH)Ot2~$bc9H)P z8c^vS$;X<7i=deO)##7@VozZ->=YU79=O2HfDe86ntDH0d%81>=Rqna1wHEUI8<6v z5LCzB)2s~Fn)`Y;x#JDanp)>L8Z(&oZZ}D(gUSt0rkL*X z1k3#30Ik&P#to%9 z4U%uC;{)XT=u)n{gC^z5L0ZyZ-a;SslSwa&J6Y?Hemk#MLwgwI-)&8xqxJlzHk#GA zLU>+S$e-tZ;P;|xfm^PC6oh=~B){H}O!6@KXIe?#b=1Gn`v5fty_4yyM(@LvHbCBf zVkcw>2XdNJzlc@BU#z1rm7j#*Y^6@~;uEa_V{ihBay5HqEgm9wjjqB|SMA-%syE2u zgy0l9Ge%CKonz!Kt$;7r0H&)<=8FwOWN4guS0jUlxgurOLiu5(of02Gdg6YY40qGm09{~ep zs_}QE%eZfa-*1tALwXJAFp^qcAd*m~u{Lr)Vm59N;$%edj`3zBXnKvKkaCf-kPvC4 zrFi_tA=!`&NO~mTW5b_Fuz4A-*7tkh;bZIfKf>!D+4mkipLJj*AcH?B-o!rOeT2_g z6?|FA_OUxb<%xz_<^;hir?#k4kBpN$=R{bd2%^`PR=W-okCi(_l_=p7xM@ZZQb1}8u;z>M%UC(feqB}Y;7$q_(7rr5KJ?aj zxg)1ecU<$$<@AuH+CfOb;ohsL>s+M3W z)!plJ(&|S&Cc1N)oJ8L~jquIarpfJS^bT1GJ$$pgjt>Z9fdT5^d@9W39|NNeV6}V> z+>D_Q62S3_F~DP=fLX?J28LkbO8oA}?=luZREqNv{l97UDbF!l^@69?P_qde%0v7G zPck(<@A({Z>86`gu+8}e#DeC@7K!e|tp}ZQR$7ddL*8l8F7~p}_Pc zC~{}YCK@wC_RzEIeKxXMj5-)-P5RK~>GDQFYmt%l!2}Aw2ut}Fd=$(Deb^kvRs|t- z!STbVE~u7)>CRY=nfulD1~`EU_0Z~BvXiD4%E<@j%L3eHjOxO3XN5ce%Y2ML|D&E^ zh8i+}8&{!W#CgFhQz~ zacYYkA{Bo!(N4P-$<4Z~(~IOD^vXi{u<9CkM;Ml7X2iQxs0H+4k-S#AmB686*4l?# z_D2!q-^6u3YbY>J9s=C}a;ouSFc=20>jvUB0S*t0cc399a=;o$C9t>9=SDSUAD76@ z2J|as*g`!@<*uPaW%2|bnpG?>jM`tIVcE)NiT$B+XwS>RcviSaTBg9oQq>yz)!{{t zG@Gp={+-GG;6HQ9&o=0A;@8eJR*U(PgUoLva@LnuFjO*NzoIb$w_QEV)iCm?Qu@ z4%VkDtRApY#u~Z1KG2Vbr_ia*;El8Eo;dG}-6Pl{~*+{)4=1hk$;iy!yK(}25yVZPcgJ3{OB z%PR%3obt(ik35tP@01_LCjSastAvRq!UbVCZr)}UT*uq+QM`|{qcZL4t|l8NKLthOj+#OY*SzPIAq5EJSMO5g(nA|hIhc(^HHHM{|BV5N0~3j z?NsH|5P!n^mq3&E$)82s9N-FF3}c&%4deHdwaDGo8c5m%xh2(!r~+I-FduByr_vWY z^p5E6%iW?MN(1WkN~oqz--Xktdj0WG!Df9n4{p~R%=f89e#q_vA^r$#-)U>6%JvmP zMY;jl1?spcF4jyy+uXVYDofKPL`#RVbO@bpqq~#Fw$ZJmSJHHA#elMbW?O*Bo^7pL zP78Bx=#yt3M+&uLNCF=e}ZN2A-;jn zeGy=?X;q+R6ZEMt zjJ7C1)RE_ip|1skfvm>Zuz>y;bWc$`ClG1Yjs#bz^sK%?4DonD)H#iaamA{AT^Iu- zpN5LJL>zj-bJA&yb1Kpy>cNfdfXcf-s;h{GO{*I+=9r3 z2jJgT0c|y$BP07;T~N4a?|J!k@}HM$#4bD0$xC3f7Je(o()M@cx=`h5`CT47B**J& zM;z!&TYFj(!x(G*7+ZT|z(dggr%}N!2t=z6$s|h8u-efFdZ7{;@U_)L>qgiHg;pJr z*NGrl*$gr3M_>kB4h}yX4iJc33y+W55cLYQf6U?wcsJ#Q0=x7zLa5_*eI8dk0x7Wr z6Bpo6ijP?UL7Q*FYm97P$2ctGcQTD%imEy_1*89j+`46tX?rqeGJ&1WyoL|C48$*l zs|06;>}`5Q4cDm##t^Bh6@>j4nd>O!?|xIpTT>=zv>ql z6d%QTK?_-~_z^#aIFq*e9FW1Ubq+eaJIP9Q|JJ!e?|mGbA?n)e)4P-9Lad7(`8d|1 zGElAcIS|TJ*qPtxVl<}HpvEJV3+IJQz6PS+2=w$Yn@xMBCuEod`psB~0iF66XAQua zKD7Pc`d4@;=WG2S_$hs=-`*!o$|f*zwHPB5V|xd{7ffKEu!Y7msPPUYu(7NLX#=a? znS+H{JL-T3PH=9-ytK6>iq$(ikpD+4ue|TEyl(qMhCA7ZazEPlf&7@bcxOA>c2!QJ z3-8Mon)89&7q1ZP8F@9DX1pigL;rqPuA<_1<<)J%&B5ZXQROZ8A*=E$P7JyJqQ`%f z50d9c`A#um=V0QJ0vYbId{w+{=Ri91-*8(p$Z`qdYs~j@2c8`+7kcdtV!SW|!NGIk z1Ku{!V`mp^=Lk7c@n;}==NRyRkO^~tKu4bXK#mPv`ct-X+I$slG+YHgHST9QgkB6+ zdohguxC}0K?oaaa6N3eVE@fW$43T@GdffvFZQk`&02$2s8ItpWk7aY?7@Jcc=(=-4 z3e}y5B`fa-Sx0B%l-SVa54~0{mhT)--@S^VyY)k_nfCmFz8w5rP7*W%Z(!@yNbWoN z|M9J0SJv~Vq7pWvgZCugoG|9t2$h0|byEmP8NU~8}$s+GCm5XzO~Dx*D$elJsoStjlRit#wjy;b}G4ny1DN#)9Q zyHVqca>|q{!}MKHt8@(qgrt08lj)aIrMDJJVqld_oFlv|6!AT9zNiG+fC`O2jI>N! zu9{()+Wl@FZYkdc**eYbi0bRpPU-tbd5$yrvHsASQ~KKkn)6=r-B32(#Kech5s0(Q zfcv^1kGKLkk@XRlY;E+&2bfN*5DV?~D{oR8zp|2crYKuOzC`6ceqy?y*ID4His+?M zeiYi!c(#cav{62wd(xDb=&RPs)6^?fd6`OEDX*&nfI|nH8^pbNu(!N~t(Xs|c_={_ zFBE#jF5d~dkl_rUM1yFW&#m+2z{p)7J1(bx2wiRs&SgzUSjR{@bA&)|Mi>^0$WHcKGeW6DTN@h*=#_06^hP2%6!RcRkB0laLI z#k33Dbyf@1>TXJI6yQ`hrK@GyE|*qJl-b>1iS6#{t~6^-v1`1e zpM#AKOUW+CDGsMOYDr!?TxpJ8%yn@GrHoK)@In7MU)f4i@|8W3Wmg|92ZX9ahzK}2 zLebOLc}fMH9j>f02CTba({a$Od?h*b(g;Q3J;Ia&JWjrFmk^87hSJ#qa5>9ZEB>VL zJO5CuAAfA5hH88AImfV5DmTG&kQVX0&N`rYhIc>^cS!LsNK1=#K`n+IS0VmX1P=+e2CO^Mxq-g5JSG!68Bu?66pb!{r5 z2#&S9W9e|9wYoc-9f=mVwe_Zb@3a&eMH7a8On87-k@d8-V_lxkTHEK(Osx& z+Fuv4cmpQ35K?dqBDQYUWbDQQXiLwe>GcE&J0`0`E=Z03){}kLKXIBam{WjIJoO(_5 z+(ma!@$96+blq;40WL%VgJ#%yrMIo)wbDUk0gs1H#+@3T0Xj7vx|!E{ z*g9HkZ#s~5%@=SWDtgAJW;-8{@-LQ&2RdS}xgF7(j;;sRaQCvM`@%D)wMeZg(C$E{ zN_SGDkkfkE#+a`IqQyBlu;lXQ*p8Oz2RdBWfphcV#F^0Bmg&DP2NTsjVSqgtdbC@?$xJdGpb<03XAT3-2;NICIdl@Q0n#N+1vx3 z_9yYb;z!~u;tA*?>fmZyB2E>DAvn_p1;}T@E5hRl*$)Z<_&H1!1__-6KUnVH_*d|H zRs;0+LN!>+OW?c^V*B88Iq&s9qmYmB}D~`7F9b^5M-)WlQOz^CC&hoE=HdRR~9TNFEhOqZpPfgs`BM2 z;|r=5RF^KXPtXoYT2fFpr+i64X-ZwVX_W;P$daNRvgYt<{jH3=8&p{^C-Ft?gr>@x z$h+K%MFk}#)s8o<2!za4Pa6nlH8pCbYcGbDtS~i%OH#k1m}MAXQ+Aq(+-NNEG?``8CY0YRZ^%N2{*J9B@M$7HcQ+W62)vWw{j6qy;x9Kg2>+R z>9&@E8?<9F{^vu|X0_eUYjaE}UQk$>w8afi4Z3izGodEweV3SXU7@22Dhn1>mskd_ zj}y~czNAc;U>UeB+{j1^@G9Y-*8`0iZyC7udZ01m6F$BkX!sb*z}q9;jTSY0Ou`4( zLk$~c8Mx;9qK1u1`0#q5ArmbFYp(|yGBM#J72{}rRe=ae?W(s#0kGQUy#} zysumc-MLhm$AhcAx^_DF{ENB503MH{;LO;IvZ~?Cc(%1=xlIgI92gF9#^3A$kpz*DGD=%sOQ~rL0qKrqEhtfw7>x+g*qejpo#)_c${sM=T{)&TH=;Al%5DW@ktbuM#C^^#; zR>(q+aOZ=t7KdplK>`>^70;u-)efIz;zdm`1go}f^+b>IE_PGs$1O^XKzRo}N8y(M zI=flz;bjDjH*q^2UVy-#zP39QLXI0Wn!Gk+*E0BIc>EDfFtxr->1z+<-3K8uD{55_ zh)s|K_ABdX`+j9D{k%`vNj>%{&xW!Z6$=go6LzCcY@ll4Pu3b{q_%7ezZu?k)i}oV z<|f#I(meBB^(HOpMue~&Uts%r9U z+2O|DsC1@+dz3!3`)*~EE4<6|nb=Rb4d*U$me0KqY&t<2o~LtqmNbDm%m}-gHCq-m z&xXEcPO~3Vj!Qk8z!_yZ-0kag2e?9C9#@hC@*Gi~&kGm*mMSqF5#o6j!?Eg+noc3G z9LmThuht+%6_SR6J#g9!|hR7_opE%eAXyh(SN`u3+?J{h{WQ=h z&H!lh!qWiCHh|x{rmWF-;&9tv-bzlQH_s+Fo4P(fn|wU<=3B`Sef##&-5(rn05|lp zpo`JNBoE9A%RK*ztPi-|)>?ZLmZICy9DMxKNhRu+Py18E-n8(PvV|Uc9uoQ0Q_3-# z`V=h7O;0M%MO22c368~-#PS8~BzCwex2abkA#|>-FH5AcFDQ>jgl!m_rVB6PG`VW% zpl+qQrlbVpxTc{%FEFjD4z~!*mgv>fN|td<6CAWtuYJApw30~=ckw+$pLO%y7n;=7 zmy3|9w!V8K?zA}2XO3`%Z4&kfd8{XnJtx})Q!C53rqQbW(d;6jMU|$$rbNwZk>$?# z)F$XQ{Vnbfh{KJi_OB|llL3uPKiiM>UPYR&r48MI5X8&Z|lXn)Rx3 zld-I6xLQm&M0(b3qKTe(MHz<>MP*OqtiEcsp-&5O@cQ`^o3aoS`Jt`E^53s4)vc5LX<_Xke3} zyDemIg6X>i}wt=EHKX|`` zm_TxhtVWe}S1+FvXJrG&;~H35UJh&8W?e>f8AIclKz+986w$s>p@LS3kDjqzx0)8! z>l&%|X5DTTk5q&{+^n0=BX)u=sw31@_z!#l7ni5teWYChUsD$q6@){;o7=>J{t&d@ zK1@iqZ%HntOPiC|)50@Kkj}oTG|}icffZkR1Nd>^8%k~P9mNpamI2LA=4TN8vXK2w z*0$Do%e*ynVGD9ME5B@i@a8ZFzB|T6-Tvg|^y(kHgy#Oi3u(pgd?QWzm2VC8{RJmi z_Eiy*5$X;oD1L=g-0wKtxwPgKlU>)4cyr)hbX_UIqbBFJ91uq0aidhAw`}(|mSD z6q@``dRB`yO|vNQHYoC~XO+(&XEwo-0F%}gXrr&3QDOwr&|A%mc~K7~BkFV=VQ1 znfowgS>XW9X4}NN+}KXdqooZN<8$|+tLfRzky+YARrJBxpRe?WkRK+~;gQ8mgxd9t z{S1DEJz^J8Oz+r+bTd>R2IzZX3Vs`BOzdZ~FtCZ}ZXVkWTca~IY#gCZ?2D1rH!Zy8rJY`Rr$sd^pI1hN z_McZ~2?=KWk2iE^1&mi52XwuQP52wzO4bcRQj8F*mKuqq4qU|a&iPdFYifa+pDRhR z#Z7QLa5}^165C0GcmIz=aO`)A5v zOH$LKYeqqX8gdQ5AXS2Bx~3d;oE%y)T8(NMp#h&M89c=-4gvz`hPZz5PMncC2nu9X z!|H-r3yOhs4MD}J-h@q6s$w%fdT&^NDP>p)PV_qS23spts zuJf10B}GeVwn+ zTx4tb|DpAHl=od+9~@v!N1w(yMz{Z<+^P%2!6tOucNnL?zJ-l!)mKVw=>NV`48j2Z zG6X?{vB*Lke%|5V;ZVAG@S?e3fHMM1*A@k;*A~I43wu)C^eyxSc)hki*wIO!xpFPz z)?$AECTiNyQ0!-d=xeb@qN!Nf^g0*6H{pJ?3QqhI4%huu5ZfE8!nFkN_ry0|7XK+$ zu3bQve-#q(kVd0K@rhIub|((i`9)ZUbD(a48Ep$otlSL&B-P!_GG5$*gB=Gw=jq%j zy8XilAa`zIO8NYhLDdyYQrZrJ`X+-f-L1-NEm@B~#qD(VSx=YFf17n64pA;^&Rn@0 z@>QC6>^<=mC+suQ?i(B#r*lr{Fk0|lM9~31dUs2`=!OMyv9<*yLj>2ri z*TF~99kwac(Z}`ohIT%wFXAEJas7ul=?7z{dG|Mot%W1->>mLavq|jVD)O9esoXsd zB-NKXM4c+&sRB3l_G_`;L2==BA+vS~i+0~c=kCJ+e<$mW21?0}(Nj;0w>1^z#O$P1 z7H_R_-tIiiInIjMZbsNZ1Yn41@$Ru&4RlU2;eRU71sMeX>|=~2iHcDMl+w>k&HZd{VvgvO6 z?k4%a=gi!DXE6JF{`2e-VZM9rso(kP`(;V#WQ&sAo7|EmZHy?Yha`zUkhT9-QpwaT zX*d(;BA{ylpx_qlwBtfDf|Zhy*A(*ETAz&_=SdqL?E12<(g3op#GRyZonKbCyO8L3 zX&brOA?+p64rvQH7AI{Yo;Ya(aj$UiBDbt`Z-T`e6XfN9FY17f{5OQQ+$#*_Ujs7@ z{anJ>QiJUDoCO(YQ~F6s-RG26!{C@Q3vo+St;eLXXA0{P#i-K*WtSR^$Muuavaf$Y zdj=2kYwHnbiRUz{w0!_V4Zg~i^0cIcV2^kMpJ#pjT=s}&n9v@{J$iAVH8$9((07nq z2VwZf`bh7SQ++WTDSf2%K^%r-s8R!5onvBmpw3T#ZMGP;9{g_uH^7q`@Y)gn{`fd@ zcBnLhc1fEcUJq@=Un*DDFQr`y_@%L_SeG8`gAxS8qfL>H-|18CK$0;?s`MZ2FEt3O zqR>b#kp9GL;$Os<#mB_^#b)u4xLsT$79z|oU+g1##2C>8z@bl(y!0{>n9o2YzZpV# z3B>XdFfXSI2>`wP8i8)lBO(887?=sa9ihro`4N0?K81z4eaHQS9)j)UlhIGPV#VUCO2drdxINI0o0Nf1{2bOFkGQrr*Hqm^GCf zvdar=)|J#Gk6?z`n&Og@O@%3AQEg^*+4_?B1~G#|nY+AN2qm#m4Bu^@Y_b6N{@V;{Q&RGlF|( zQB`Hk1ZG0sSO{ZrSyg4q?b@#Zv@I=B2C#NE;K8C&_p_{>4b_Dy^H@5N{GI-X+3O3} zZzxeLtP_-CM%8-$W7Zb^jT(X7$vXAu4KNZ{%O%IzY;IUdD-gg`Jf^g4WmQQRN1&17 z4JbHLn35G}q_~v*>atVzXU1+4M*~UsRs^o)B8sb%)g}|@_%$TdND-6 zlhM!d185U0gfC7|p+(-v{S(1e-SNk;&$2srQpsHp97e3EgA{z^4)KP8LGW;|-?@XT zS&14Rr$%Tc(nm%{E+wVZWp{3e*9aEbAeX!4idzp7IQ&x=2Vw_PuDBPGbGxIL`7iE@ zzNT^faTLsv2R>FbUx!jbk8$JZX3tjF*TW43wyCigu+2%?ILhoa2QEJrU>(9@D(d04 z$0M5G{zxh~ZB|#wnf5!+Nu~9GuK=~CJ%M_HmWN0Og-_rGL{0@GI+6kgz1IoeEI6e- zWM90rwXRq+#YIpY&ASi~`y97bn1_SBnER5Bph&H%hvb@_=1vVx2~#Rw7%$~U1iQnN zBR@wwEfw_}G0|kiWGRVEm?%w+++GjiE+;KFofmGww~$pzm2 zsL4_S8F+&t&Uh;zXmO&xe@QAB$2Z-U1svzIB6JJGfoQN3rE5P$Mu23t1EEg z79f>mJ@+$}rn-_*8g%{G(eJ1 z-xgg&@^6b?P1J+YRU>5K9;h0ZIb?EQKvAa4xSCu*C`Dc#oxRQVec1$O@XJG|8uo_S z?b~3_B&kOM|596sT&uGYh+nCFUbP_}k$)SLMvi1jxSfm47Se5;G*aDIj~ED@xieNh zv(sH88h1@a{faQ^b5>U}x!51`yK0US+m)`awj*dq;hbDkU&5Zy^dMXXL&yjHC3~lr zgzUBr_0Z=+x>OhmOgwtw1VyDl%NS4SowJ5M5jau$4V6Kf21+sMY-0x=G9Fn|5BXDn z1aeRCC4px$!bf2|wzj^MJ*LSV#soa`l-ech`UwbngzG7O^2fqVM3-hml{pUwN|(iA zlFjQp1QRAg8rjjZ1JD#8OSai-fZ2)?Dc-n4<2_T(^dfy46CrqA0~|@sP=~|+C~qAn zkattuw~}wVx{qhb{4HQm5O#M!U0=d~&2@oJcoWy9w0md0IW}i8uu5XOq`cpF~o-nd6TCBHe1G(nBw9AF(DS_Up#m#li4H zFNER1D;|SZ_N4f(_yz2PUm>vJPsl$z0hB^w-(~JGir%X;s;l5>rR7iTW9UVK-&Yr| zFD)yKSP=f}e0qiB+m$7iC2)s=el%$*6`fOptrVfe4ZsuK@%ry2j4GcxQt=$F(sjs_ zoj-A+@|QS3ea)yYD=M$3Ntsc$zPfCqI=Y(rGl{)EI@Ukjo%poigy z61a6*_<>vtQ8vXSs;lmS@|ERsYp2Y+D<)rOxtI=|ONQSnlAbrmG?VA|#H=FA=#Tey z#hjq4zmh&pa&M*eL^s7)$X&Z)M#AD1^Ut6;2rr(6oVL|)=xpHAxwo*pj@pY8)Ts?{ zJfs@%@oQ&EeRT^5-b(*BtpO+mh;0p1^W?SVw@f@M^#lHXe?a$UM9PHLng;kSBO+0;&Bm((GSo zx1JD4QiQcGPZk|$dO0WV<(9*UzY-|!?;-8@4#4Ag`mCy7!h~gZUD_9uAuVdAy1v0i z&0u=U;NF>%p8p7Qc^C5XOexX-@O%liq$bUmsx0FhVlXABP{%_!|51)2U(S$jp+V?t z(F{5FBXItX%#>bFkl}8Mq(SIKI0Nn6L?~DHqm)-WKabw6IqJLyoGrJG97EU|yiz3T zZce(S`0(=^Ff$&5kgdU%-yxjafOz&qgOF*M8AVcto>dcUabg3QMyiLrHUlM59$qE& zj9A(L?vRNr#MFLpkgC5S4!U5KG)Tewk({VCNe!v-1RKgkB3DW2_K_p!H&8d4_B|}J z)PAcIgl;=Jl7$T^m^y=+IWo@7bXmyxGRc5l5B73y11y@M!j}OZWl%2D=^vqPZGia`Bi2M4Qf_eU z_sXRVa;6fp$#VR#^n`8B%>||=xe8|WT`tk8Am538z&GepMx3>MX7AqPMui4GR5=N;7hCy*ZTqWgo60S#6%oBck1KhYkX4aGkoXXyIRcq_=oa67{>eN&eH8SpVr^LMva_$7xOn zt^qPr|0)!r&{Yh75@s_Q001!IFGEI_1}A>*Ye*s6_DX#cb=i>#B0T1PkRvs)_9S+n zbOSS8FWe^$p@!9Z&KuK^A3_pK;`T}7HFFdt6Q?wcCezNx0oBDCr;rc#;z%Fchtcoc zDtXC|TcrJ@Xp3~rhFnoNl=pJt-^G{2KZtjbh&#mT{$+QFmxJK~dG+El(&s4ef&-2H zrTlY%2nhT5WD#}#wa{=ej1iK)j>&;S^-r7V3_5zAVA*U}ePi!}i zZ-CcXe=e9m@-ZINPD7x5L@zgtg(jvwYxE?FWbc*ILN__>jyIuU0=Y2E(}nCD?%D14 z?vaM`y=9>iR~)?ON5vleASg}iP{HFdfu}{c@tN5$3+FA(0nM3NJlR+)ZEvp(3sh&w%k4nyf88vFOXL8^!L<8ek1IK3~Di(uDB=6iR z+10X!*{t=zm%-W8zE07lrNEnb^2!0JoD?3ARcpRbd2uPS>d2p2X$XGO&_jgYlyAyP=%1w9NLU(x_gwO^WH$(ev;Mo*#| zK~@k+3vLb$hT~T>6fq-%hAF|^j~9XBq>V@$c2&c2NQ9}0V}jGeWU!_@DVnUQl?H0m z!Excl6w)=;y&zTt@EnH}7D8g)QGrgeLeve=cc z2D1BN1Rp;S*pLvVZ*e;W{7mpY+Fv~Y!W-GH!rkWq)Insd>P27!&?*`>LAp##9YDlJ zX{7(PMyZeB|Mm_kE0DNhhGk8xhAmg+*K+?vUd>8el1KGdEofMVzOQURltN}&z&Q_x zKhxZm0}>>K8R|j*kQ36gyvaMVp@!rS7UKOg8l*w|$iP4#clAKYB#~bYsJ!{Wr22^4 ziCCCe#;5|VrvXO0;yUTy$z0xV3eCCsC$OxZwA6ecZy~|+TtTd^u z0!R%tC{Vc(c{9~~0hH>q+#)#7FCx-z(Y(`$Qph1|njA^QHbRXiXP%FXh@W*B60Z}5 z^XSCsjxy4+(po?kk)#gtNL^AZnO~Q*oP2ydX)`G~p0t&0USK^I8yL?<8npEQw-GTC zi#Sp^!C9o1H<~d=&QuR=5l8FpGt$uD1$6Yt+Bm^9z<=?6>0RC*d5<(D5NlyZC_f6O z{tNgOKdI z?2=?5zdZsewGltGTlCTeDN*gy7>9Ln=?2M5mp}#5?!eoNiHgLo32bCyUmo|Gn$sA| zsP*$4q}H=cavzmmrHpi^(Fc-y9-MT^B`Lz_0=w+-{si*=!_sz}Ec}S^bm#b&5VGD~ ztUQt*uWo8Y##WXq=u}5R9DN{vehe1JjtiXz(xVZ9l%Urvt85@3)f2_o05Te#j4EsZ zph7&|s<;U9T7z8=cGHHk$>>GMQ1njdLy7PzjS1kNF2X+#Pv|#~OPhkwsCzinHRrfJ z#C9xcqgvAlbq~RYaBL)*jfspPWF*7L3lG@!TteD^ zt2ebV8PS@=`<3hC<*-0R64fH+T!jfjN2%1;*dL03lWAB4!qybd7!AEP62K!jJ%z2GCI@!)d?Km>>>KFApMs8FVj#TD$Xf!h*)`;5&(F+5}wvD{d&)Gg9uL z@b2=m@Fui?*Ex8HzlSwoGWR+huPU-JUdKTE#t;ZxpDwcTMJb)a@$2saQGqeh|&1lev}}a@)@2_2lF2 z$s5VbJCZk$IXjX!krUaLZQ`2Sib(EvR2J@K`FmH&Rasf@9HE>)k7(&3+z*XV_q7}+ z8VZf7KxUM5ud4J9`B-{Zq@}>)&9u;79*jKakrOirX)G!%yz`FayZwVcm0lI&$I>iw zkFbtE#r@2U#m#USUgjE-^r_f`NO_hAO}%fcOd)GCkcl~?ABs5~9AZf)^@AhZbJe$YOVpADA&@P{MyHIFDo}@;wot@Mm9=bR0;!-DqjP5i%UqK!41zY zF}n2;pxZ4FSUB}jI3rS11F?S)VP-vwD+rO?xnFikw9lz7DOpicG3!z9{Jjo@*t^K3 z$6-%eJVZ<*`~L23BFRI=Pspet;uSJEPy8N+1L_z_gMp`Av@@xZT-=e=P6q5qy7j^D zM3X7iLd#lB7VZ%ua92Oe<-;$3FSzVQ-27ta#B(d7B@nz=w}czp)vYLX<)bt#kBs1QN$tW&VK3{;HyC_!Vf`Lp*Aueg*nFyb<~O??FEVes|*g6(#G|RaKK# z6N17InM~ctLHtX)5+yps85@cU)zRzjHkFBDj1~CqxMFt-@u*a-pih&jfpUPltPvhj z6#daIN|pxG5+MUf+b&0I+XFA7!{wJYR)O0X)S5NfLSBxR!>X-N>hi`)%wMcSyR4=} z%ev8fE9hwGv$ zPP7bdET_IwEVF}<6xl}3N6JU7-Vu$6yvz#x`D%oG!WOs`z~JX0=kgjK1C)QMhdR$U z9m1}|q0IvWey{0b(`8C819V^Ho0h`mbt0SQvgvV(0kT0pz?fus^yskI1e=y6MJgS( zspMpW&8}wnrZ6ha5(jknVPW}EYNBnr+RZnaQEBdXMirVJ1*)m@BV;}S0t&F6hX9}V z8e*&`0J>rv$}Y09UE+trCUMpy@W-SD1Dmy@Idh*0lj};H^GNX{JvTivxM(l#r4Vq# z7q^RAaR>7AcJVO1%?rrI?c!oGZo9aNytGZM@vn|ZuHy&NnT@1AtvgUXK&-xbv1o2mI~jQ?|FK8u;1pPr9rieH zk`Kxbh_!hgu z;;Rbp%OtHY-|VsLeYx7#cB|_0;audz8cEHxC$7;p7dd@{k-<)TLQ;C7EAMC6dd{(6 zIZ;8nO-P5qyC-*AEQboed*=mrir0Q22A5y33Y504tm4fQii3*J?2<~a1iNbK`5nUCJKYdkBUbj)`=FGjF=>3kku1~ZRG0-!Va<) zKTKZBo)og3;)ag8Eh@raHVUzIGF^HR=6K;{SmlWQK69RJ_p~+~NTm2{6VCFFxAjo< zFyla)a&8+A=l~<@oMH^rWvOX!>=}~*G=R6&oVGGXsWlj+)ML+)#s4Px?NP~`Nd*O9 z>P7Hv{5S-}-pnP#hR8m}ZIK=>&lR-!#s>Uhu`4{98AiWc7PmzpGQbrydO{?pb*mpO z@o0CePPnwqN?X(kXI7(j<@0}1uCo^{Y_nk5T~2150JF2e}2-xfd+yk=!T*d)4 z@k4Gh3L$PqG|_vQqX8tPhsoiXdUiY&?E`y+i9(Qu$m&x-p7`+Iq+?{-y-BtHs*_1G zc`~cnavG(Tsn7@@@AGhg^@ous6|k1Q5lFBaJGRu@zX`Y`xlZJB%xm1@jV623s@4chMcNh4Civ?_@ghcj~0`f;wVa1oZp)+X9>iS zA%DJ*-p=t9aPM`*BW@KZA{FRwh&()se9B2eDm>%wAUJFtuhO+8EoqS-6|MC}V8nx&g`YAx#}qQMP7H zNwqLm7~9+2FE;>+*7u*LcoyhuMYx7I1yeZzBF=auD)oYm@w?yK4NdUt=8#$&RLGWY zvf`Kf%HQ(jt<&y}{*?ROqxsP?QlPE$O4%=bAgn~7L_9H=fX4DkC8AS#RAZ;MIx zt)lDb3}6?tXQH6(0e_uaycg^lq~pTJ@WLLLFb)`(! zfzlb(swNbNg3Tk0Du0zBr!lJXrUkUE@Hd`ZWk~Imii}t;v`FNS^8U)VyajE=v&~94IL89)@eIORXQcLW6)Me_*ec36hDiF)Hc@NO7DHI~eZvu7L>HOB>{So-1lS^L13oJQ^^?~DQ>;XzSP{|T=MRdyt4rG&yLar1B7GV}r$6_YxRNJ@L~IU%7$Ylx42%zFc`LlOKl7)6 z=czzBSVNL$n7Z_yaTw9{ZWkAbFr&j`AFyFr_6|ObU{G)BL6`soo?5bfv&H9srp7W< zAY=ZMd|^C>6Uo7VaVLa{M*yGyG4z30)I1&ww_1(l{A! zDQ;Rt?B|?_hAo4v{aOw5s`t0b-N_xIyOiXJfCqn3a2JzB0_wV4@1Ne+lK(CVX!uogQvE`yZ0tnMy{^*q~;dwhk`r532yux#^0AT zO@#F543xa-)FGZ**|d&SZjncjliwq9!qyJ)zu_jin3Qdn-?T1mg4U9gNK$VCc4SNc zh#1mm3pzgaYj|wcO>&Iiv_(E1h#rdK2A~`Wz@R=9wg^dxAes*g&>h@>Bl#}USnez$ ztIC{9#Db=+q@~6vW4^+6j4lG8i*f710%|ad0@m+a$-QlGBRaA#6t4-{t+w4-u@8R5l8qVZmKL;UzW2?4SjoPYYY{rSTz%VSt~XTe8x<=f^5hP9tGu!WM)C~ zq~TV%IC6P2E?l6yWfJf0ayqFU7!mJ}yjlK_kP*o(q;Kj6v8xC`Fa#-H7rBKl@37E! zpxN94C5OCwyS#!l9+BU%6g0q$l)YCRKK@)`8B*S|>Vc}s|2r>+F2|Mkt++e(yiG+d7-ij-(P4fjjE~+?tmmP*6Dg-iR3p{}eWDU)7w2vi0DH zP?-|_Q(NWpf>_aric@f1yzkyWa zgb5&@OJ%JuZ`uxC8AJuN+gG$~VB#lJdT`SG@;Uii!Lp)xAOvF4T91`#zDG_XAJs!g zYd$F#_XsF{-GG%3t0*m9eT83#i}X$u1Ta2po5z#G?dYTJ53<`o{g3iFfn=YRuhRbI zMFO`LrOPv+HckU(>o(pFKfrMP;nHT9-3KKGU?y}cC__D?^5i3OIhjX)TzeQh z>*j~$3KIJ;n9jWq;oF=CH z$er?#_%VfRN>b*O6t>{99FQ9b7Q%Pu&cr&b704>9D6I5HJR|=kkh(|ZRdo-@rmhww z_yZYsI(SGXcO1W*#{tR4Yc@3FE`^CLhpeSJq~#Y?i5%RLG~NHs3vwp!Kl_|~jwhR* zmXANzS4h`Hp5+v#S6J~lgQ_tkT zV_TE-_b?Hlq8am;5nN79oJil2q+iaoE&u+P<-t5HW;2F`GuSayfzNUbK_>!B~Qr0|1poSOgfiMW zXaMae7!H3!MOAg#l4cy{Oej>X_ao|l#3%B2(cKI*y`{4A=ts9ikP9EmR&w7}c@rrd znbb`FF(PRTSvMkSJ$Yhy(gU~qaAsOerZh8mJGCBC-K#HmJ5ofCBUbrYB$d;B%-*h& zB^T8Mx{>45$`<(4`Z)p+LA-kWg3_B5)Vo_EF+VkMLjbz?++{h=zvoUjuzGN3ti=@EITS*`f|0v%;dj2R^L@sYZxQ5%6 zHile!4PSivgFKoH{XxEk-$1T@13vxUck-fO(IhAsIY_HZhvK>%ms3B|x;x3O7S$pS zE+mlV>ciIVr0OB7j*^o9sMX*A(~sI=9Qe?B8-LPwJc9 zWzHy?@pS@+MS;dW9m-@KmkW)M*yl^}>hczZ6%TUg)eunx&p{sG6)kc-c&+pNq88|z z{T!OPfUtRw5fm*DNGF`%k^(Wuq1$vWy$I&9N>H?@X`OIU3*3oWS_mO*I(cwdKk+*) zE^SGsebg(O71A(cr>JytYViER7B`N12w@`9&en;F7M`iU`uG{;YQ(&jBy0+YD-bsP zoTv=OpAe?3|LNJE<-v6(#q2jfZTd}w#0|WIR&lKGH(=ZD1GMtQsSj49)6-rg<1 z6&xC@Jp;CUGDexMEy#~C3aTKs3?x-HCGSDIatCi&+|q{vlV0orWvrk#>R6tgjyheH zvC8fE3Og$Ft6L+K;mo}mMH6#RigS_dc^}GC{K}t1tmaSnBl~nZ)Qq#>hwRN`jMX@t z4_%fA`QJ-YGDK2gQ|1SeZD1s-7n4wKT?NAGqo`L;W_}qnMZK{Fszav3q1{>rPQ*9q zo$YBr>}a`xE~$?6z~XoB>!$P!#_wtiz!ETo6)m_9LZ~%sL(gEkMmRO8$We|(dF?Im zgyErlvNK0PrG)OvUx+tD*@>f^&(^LRX?+n!ow_7t%!6;4Os1F!4wY>-0voHG|AANd zo4NZC#$g+zE^dLpZh*0)y(Lh~UL17&j$YORcV?cktuDQQZFRZV_4{vq%M7;lH6i&> zwxZ`4y_QXTo2{%R-()KrN$+0D9;;VqnTkG>a}uBicJ)@ihuC5n`5vG%p+9AE?*V&1 z7Lwoy?nXEtGF@K&QQCg0mkazi5RIuVG(Z2*YEZ#w6A6ZJ|Fa1ZWXly-p1SE#*zSS9 ztOY7PdBv5hPQ4kDzbhDRh3$$Ppl@ghB(6Y_d}I>8^(R@xzw*J%msy-J9_3VbyU`(8l-fxOjC9T zU-uw`i&1fvtQ(|c1!qa`C^^?(d5*aIE60M9G>_x|Dc12`J_UKE^F$SHUWy<-0<3lw z7TYN4$CSjU#weW}$w0Dcfo23}kEWI}!jdsczfQUqzqAG3S-7Ud2&2YakM>g10=IC# zPOm;WTDdOVvY@4e3QOTFUd>l@SKjlZlzI~7cjubDVoSM)*z+v0d5afs@EgQ(!?n^gWp}+ zKMJ`@;E%aL@vatPS!LOupk(G5l5Ib1S6tnt&B1>FG^cTbQY1z!Z`nwF9BIh2Rl1Sq zdqhW*S0*cVvSX~06tuy?L)VDp-kT5_uz(}EYr2eAH@CtwfkG9U8hv13U3w5YIl>0CX=8vJe}a!yt41B% z%_v!UUDZl5ch5Z$-rR$5I=NBtXE3DV<=s7ZvD`5;CIe>c5{Tia z@z1vqb@L(;u2zzy|C-!l^(|%O+-H_J|BPYg2jJo4GdQ81&p?>yT~K+y;BVsxqt;Fh z6gCvdL}JU#Pv_p>l zx174!0)&A`fB8lwk7jMrmR7b#(bYF17imM3ASeO&Pu{4^4?s6XB5j%Zc%S3m6IP;1 zNC!Wb*wSr_)#bGa{zx+-tzUoK+Kt@xU92uiR$TyWd}%HASDFznZhsh5uRdnTo4X!^ z1tsl*wU9jdxV4BBJ&u0~k6V|CCAED?<3rX7WXEGxH@WK}>uWt^@F+8?pK%WZ@N76R zQ@`d?`Cf=gnXR2Tj(-IrDY-Nbb2qF&*{&A1M$@5&&)I!*6g{*jWX=kIZ}yRrR^E#1 zOkWrXesh!=8aRLOasO9^O1uEk6cZOIoS4XOzT1 zIFf@zlq-65GOa75VVzQJS=0*63I(!nLH7EHRZ24Hd8?A_Z!1+U^JGN1^5i(G!A8OD z4}6W0kdJo)C-f3u3`6n>{1KlL!`1^+5#Zt|a=~*C;;=b?X&NS_PFRhXHtg4}wcC!*0`+dx5Kf&2MpuHbLal`-m1B zH%D>Dl{SI(!M;GlkQTKff;!71lh)5s5bK)_xWjfSG3nMDTd{?*fZN$*N+bn4lrE&F z5|iw|v|hQwUO9FhC$^(5$iGk(D<62%`yph!!maCMX2c8F2aaiPMkdddG~wRTEE_nB z`8Ua#!u(c}GYgffzTBpCCI4KbIQ?t3DSbr@%;brH0S@mOk0eq79cAr7rBRJ;MF0t-#V|nNKBVZS7Yh$552_WdQ)oW|g{eW% z{jkAX(SnoQbQn7wFa1}@i%9lCWh@I721!F*twIIMq10@b0khqFgc{np4r05_)Jz)xt*i@@T zdBB12VGW|iSns0N8{skzx#??_Ntzzw9T~Axy|ER74Jx{87Yj>ayZ?xyyKRD<hx`Ur#K)?!Mn*W+N#f_gybW{X>k{(lLPy7GH1 zYPUjjqw*>r6ajj0yalyPdx(PsFWhiRyhE*Og%~(I)d(P`w@S*!1QXeHLK)tPoNhOLW9UaOa$)A17^SLrm z&KL--TUdh{BKIK7_HW!?She24-J4APUxlr(1LdYVnSl={3y=_r#B{2&)QtSdVP}-5 zN$V+P85w*^DWi_#rR2)J%0iNTuW~<`bdT~E<_>I8ya7M}1Ct>d|xB>YMEp>{;=Iz;(0p7q0 zFM)f2*^QGE0L47?yz-3y#ru@CLfs7Bgi<$fb?p+~fCxAMqSg^?%^B_#wWuwJO3zL$ zR1{GvF7nwoz$%USm*NU81nV?a;ER8Eu2utF;zcyzxk&!G-Mzyp2r#Nx4y+ z)i!|4_(>VzzxUtDT%LKsqk#w@E)pY9G-rWe7VqOv^YbCbJitw(>OdcCQ&?$+r-k*o zE?SK}z8SR?zZBJ|&@N#*(53NVU1CO{ED_X)L^U#$8r?EYYlB$_bEmC_Mr}Y>&`Ad2 z?6$GtlROd;8GjbkPLs?FbK1tx&{=&oSfK4Kf@%N~uogLfW*clkAk^lL5q`z1dZ+>2 z33xR>w++sEq%~@UY}xMORm~1T>4FiS!_USq zy8vavLWlGin9WU)ywjX%9y$l$ZpYK)VebBegMuYlyKQ430`0qCWPso6pZp5txUUT7ow})&#IO zdO$fMLf;=0MdO^B;1_vUST9%roYM;-J1#EVKZik0u0_O)htrX@*);t5RqJ)fW^yfr zuHPdJn=j<=Uxb-9l<&eC^3j#I-$PIRT94U3ZM(W%*~d~|4B z6dCFWKbn*)RkT4UMhb)G3G!y6BHUqzIyh)-4s?R&82T~-Lt**LG^p)m@EiT)P<88D zaOU`RZ4i)i48oZOsD3^#Ue&!YhvU_FbyXXr;}C)N$OAA?JQuGH?ELb=m1RZzf;LFW zPLIBC*uZ)_)htiQPCy5EZ%W%tAO{<)uG*>U@$n~}>U`_`HXMjlAXmJOZq4|Whm|)@ z%?s9{M;J*rVGLqCzvmW`m|}C5dv|0g=(-W$3{`b^s$ad+)P*;Bryfwqxg)6F`g5&m zt?*!}*+k=ufS6t<91wZ|Hldgo;4SVid~qZ{L0#3-3zDW`8udmhqcpMLQl!!aAk|K= zeRRm4U?08RnM;|>+zm_OUm}#lmX$5tFb~wplXQHgG9l<_8Hpke++)IdZlq8OSk4nb zU0KHWP`4ahkM|e_5bfEpuAMq#(Gv(z1+lx0Uwsg^&0K?w#pa#7$D${P(8}O`;k0ER zPd+|rIYGX;$8z_B>&?7rEI%4o#C`+=L2BPGP8B}qk0N*dBRGarXax4MP~Jwj;t=E< z1rv{4E+*3AI+*maG)7(6h8ToY&vm)}*F|G5Y(u=p?+`|i9f_(2GNJQJOe8ixvZezY zCs4mD+NEZrY**W|kZ*!zyYQ8MHkfO4S=&v|bkDY+iR$9P|%E zk*GO4+YklVA9^kA|>^J{>LefYvNPAd4g zHF@UTe}q_4;&Jo|t=@)tnpjlAFFzBHEr}{51((m|`hVkN(8c{gAN{ zj;E<;Oq*yKYs%5Ii6A9U?i+793`4K!3-aDr)29#a$0dLoxSa~kww2JbczX6tpn7bo znnX_b>y&WPqpg^cYEz(*h8CKA6N=`PwxTdPqjKcqwB6sj8u>*y<0v(ordlBuqpoFj zz@`|S8{B8J+kmwWGraany(yLwvpqe$CA)oh-?o+P0ey0`^qE(>sd^SZtI#>8Z3Uy$ zEOmN4U)FSUU3fWPROx)Pu7_$$v;Z4WEI~CI4?vd%{PHw*hljr^L<_9ewc4rHHCcSY zyp!Djn7Psa=L_a;Jel*bxt09)VRL1a+CPRR7O>M&w`Ta%B6sCvFGrV@u^sA^VB+}#{X#g`&%>TdYoVosW8 z$9PwIS3Hr2_&R66oQUftV^d-uM3wE{NR8!gvST5iNJN=8VtFFO$eBad6e zuJ<4te0{7s1qF0NF;uYbY?4yOtKHyvFqjRF=bLtM_l<4aSPR!3P=Y6P?{%<*?wb#u z1$T=O5n0ixK5je5TG0YHv{xcpJG=@v>f^TU43kI<($M_U;1bSh+Yv@=EFpTAPQJNj z)awhZBbb~eokNoCJmOsy+r_p!r(L9*AmDKdPDb5yRaep&mzvowFrw=w0hFoam1_P}qm!g)B`@KGkf)`~vid44UqwAy{Z=AGLP zkQ;=2YV%-Us7};Ie(p)z7CXOtPJ0Y}kM4S54E@dds$P{WI74sPdGEY-J2R?m3)+EK0hvN;h;?_8v#FelqmLR8YDzZ{~aX<6BQ}#sQDhZ~|GT(~-Pg4cdmfbN~*iC+&BoK(w>*e_rH}DE0?Fcpmj2 z+o98U15jE}qG!gF3)@u9GslP!k;|`Whfa?~v$P;#^mb!d*G@Q7?WX^qSBETMEV*d6 ztyL4+p~vH7>YQ$eIwXwCVU>W0|BBi}?b4pkNHunPb%&}ur&E7a$Eu0#X^cP{I|zo5 zl<9`JiG=tR^5IT3L+sBTBi0YhnF9XX=L7Rdvi1XWS}ZMuJ8|{u!pgGc8&;wgk2-p# z|LzaW%fzTjoY-5qoxjBWl`&}`M6~y#GLG))+kBg<$3b1VO&tkN(U&6I=y5C3L4#n{ zL3Ot}wLKTwqJd%cmxG3g*Yl9N0psmM^(Z|YWadC*+g>_k%=@>8)Y0m+cKF2*9W|oFM2=+lOV1N&RCv^-c~rUA-T1-FV%iBDq!1GQvLJ_g z*pta`lftXc+hcZTpGaj-Xw#2Ihmw>m19J;U{H?lS5f6v=2z3Q4AW@ znL1Su6}?ucdR2RSf7r8)Ir9=#AO15$9cuI1+Tke5a_NrnTaOzQuO3&2)ZL+)qC`&N zgtt(NLGj;pLR`U{cQ4*&Pa&z9V!VHKiwJ*a9B;}rbJ#p7!f2G&e3zR9Oa4V}ifa!H zjozg6tVpVLK;GBlVU$f#3bjKz1TlhtMI)YsR^lxnM2wZKru4XDwuygd&mEzLl<$-!mW zcudu^b7`Es$_slDG?(fLhE^bSMvW&g)T`<0l6LqC^)FzYEPWc$eCnl{`e2bUWNl`nN%lQu=+U$V_=% zK|6Ifc>+QNz^<~f9cop!M~9pFM}w*tzU$SfdeqhJQ0CkQ zuFb+mRre`VTpM*oJ9MuQCjNAz!AvLL8CbsrJwrqFbz_9m*r9wY!7GvHaYm>gEb&6{>89Yctn~cER}Fq`29j zVz0Iqw8QA)HVk15bmy67HC4M?Xk&H%jkBmQ*mv+m9EI%NH@Jle6rK?|;>ZkZ;)Ytp zj$opLVfXYxqaQ2}GF9HRb|rVe9dFlKOMBCrj_|=k_JkIDz`U-j-n4cykRe9Dwtx|8 zLBkqh0?YhN?PS&Cd2j#PrMRvgF75go@Um53(=9Jsmyn#-tk=lJm#ifb^J`&O1u4lo zf;s>{ziiFRl98cc1-uovk4xfb1BvEaVZV@uKmLULyY^|!4698#o2Oars-DY6s|>1@ z?Ff<&nRK?^{&r)%F`F(m0vF#ROj&RR1JMN+PXS&O$v<5J){Z)NtXkea9ZcM#?;iHf z&)N)4ioR39F<1_mnd=+t*&1w&?T6*<@B-;%@bFP9VM?poRa+WHRoV{kPYBkQMioU4 zw5rJ(Dcd^y>h_svF>Hsi7Nf{lt%hY9&H96m%7Gjz?l^(Gq4KvQbK_oeZhCx*y0(1< ztb|5AxFfsc+~m7Rq;Fr02X=1nbE@t@r5p(#zOuapy-d^LIvMo;#&fC`!yhE$`1S3@ zzZV!5K|VVd&RlK$mUhHSVKiFYNic>if-L%jaqQ{9p=ELH*zyRWzK-^dKNvEsPK(VB z6-T3G`Ey6ksyfu#)u+H~Hnn4?XBs%2*fc_-%`3Dc3TvnlXv22b z{ST^kGQ@B2v9%9^Rc>!z2@A6^28}d^JmNQYBPFG~aU+fG3JjN|{!yJn-HdESuzY&a zft~FYXi}p?p;Zd@HRJ(RJ~|>bf=v3Ou{?C-&?`*s5qPAQ%2<=!wb>R7(_sp^K4M-G`q|gP=>)MLrl6 zkbj`b`i5%s#7o9Yf?Cl6AM6U*u0RStH4Fyz2puE|bP(aMsq17DSf0zU%GQ8w>#AA-vU{NC87UQxRrZ!s{xfPnj4GxR5865_ncK7=;lG41AJJ!MavUS{;vn1m!BvOz%~HVKUWwN%Lx3Aro4 z5eS}%Cm7|N_lLG+5X#NoQA+1NBVDsj5^r0$nAORR#H}!rXp1pj) zmKJ7coOvAJW`Hs4LC$vAR5iOJhdrcq&v+=*Y|QpMyee;W-!`y8r9O!qx8B3hS?Anp=}`V#mF@QBLD6{-_uERt)d&Ry|>zS);(v- zm!ao`>_gU#1GToE+O^kdjF}z%8GYCoLGK}<`!G1hULF0yP6TWGy(2bV#1AxnJCgn8 zbwJe(VJyZNL7zfitF-CIjSX^MM=qle8zd!FQP`!b9I}|U7raMpH%s$4)Ece=UO^Pc ziU%PhG^c}FIZ|~q`N!LBqr+Ag*n`7}vfbuT`*d_;q}l=irZA3--)_^)Uq_pI4JGP! zTa3M%H@hR9(P|TfW+!WN8QLP0XS`fnefDx1g5H@l)-HP&bWnR#s%~J(+i9B>q{Ew0 z9eP=uN|wjly3yXol2KiuBK@}0W|bhlE)||YjQ&uBn?OgNU;~pv_mJeK4aH#KwLhv| zL-$hfXfN}jr@99;$i#R4Q;j00KZP-w8iTYxv!e}mzE*Yny0ZH}>|pP@1|#>GID2#m zeb6kE=t~W8n!=SpxjLf{H9@C-3jqYS=zQW+K*h{Y;p=%Y4JGp9y9b+a=rd3pOwbGR#tL9~4x~oIVM^LK#`27`xwK zY>7Uos36rg&D9`j3b}I9@Ha88mh6Mt9I_q;X{eb*EQg*~ukqqJ^2_YfD0N!SAj zB_EY{WA(6LAV2C*7)W#%WDN3=oP8sC))Dksh2u6ps^Ddzjj;KRCa90-Ez@GV0j)Kq?CK;T>G!-X8;l+yS?6#12&#@Ci#x4=t%xR-&C z+t1O3Z z%|xnMGFff2Y0-Lk2*v{ZZ<%ilBh+@MMwoD2svD?dct+6+QnlgNkrfCP-7H}8l zv&&O!+*q?+_Re=9b0eyaLeXv#;^<>OOFrqmfPxma-iIh6vWxn)8-_NT?}?|wTEq&>hQrd2U2as433$RhAOt9S6`-#C{H}0 z4P1LdkB`i+26ppOA3`@myFhPpwA+Q8aT{!$VK=*d3vs8!>V7oVpshRTFZzsQ6@uNI zWy|pMi!CBBSU5=7CBjx@HVo7y>_xsJ>dVxxOa@_ncqnv*$0r!0$ECl+9_w}cU|s@o z*!UUol6wpVH+1|NYKo7VnPT;&XB}qGy!=bZ;ic2C!dDR97dj1$H1y_X)8O>M-h>&` z4y!h=&afc5kZAyfwcA7!lV!x9rgP(vFTV@_eHLH=cX8g7y%ti?PfU;SF1ooIi16;Z zyHV+|(1r|L@XwW0`L5yr%#R|r57hbUjXuPB0Y6(ihiuLme)jLcemi}zCxJL@&KPlM zm{RDRb%W-a;Db>KPlfFpJf)k`*}f_80YxCRBXq(*l|ar82-`PQ0`&NBb`V*rP1&_P z+fdT-*8kWvJ^iK%Nal!@gJeF3^0y8A8%R?m_J_=4sHC-t?pWRO!luAB3DV;4Y?~zC zM!HzK92D5Il=y#d8;=jTVR$BN0`LM|=VcR6;zPJtXg4O=^dJ?sPm+D>=lXneMFc^<~7JOg^E5r@K7812#oG7&d(N z;8(AQ@CFKRzp6tF?+_h6BR$h-n7Y{TQ#)W)>=&!cZfh4As#ExKM+1y%fv}!`8!#Wl zUK)kfp4$PFVoq$Rp5!Lmm*7ZUH}F_*myRfUN`rBs$ZJ?)(?y2Rv1X`=9n_Q;Cz=0+xQRok*E@n z<%RMvuLH)zoLD`$iyhxH1;!3x+u7lDbs+l+bQ<$Qx83Ay0cNAA@P9G`caQ}&h60ZSp~MjJJo!O$?d@KHyBX%}MDAM*JDraiX< zVN{u&F1o~O427z;n(WQS9fyTQDgcPJakCS|h(kr2&P$9id_1F#TYE+~kTZ@|*ntSO z&~DH%qvgaD>!0d!tpTkC-(OtL=-W6!ZgSm+az4$vnmTLig z@LSyWefczuC7_NoVzZ!zI$1$o#P#`d#A8=fgE^G?C{TgTf70lG)N~z zY(W~i)(BLMM=pz*>e7AiCF4)pWCg$kE{i!@b`NA%`r*A}_l-wlIJr0xMWEW>67R1o z@R(2;24xhN3*W(|>EX`-uYEqGGQBmZN|`m+OUn#3(@_^xEThZw%0=<{JniU zvY5F;Yl<0rSM0Ls;RBs4$$dI{GJ0(S7=66g7HR;ehVp(LnT$>wy4G&@Fl$Dj@w;G2 zUfR)v(QAV@EXn9hnDc@el9zU5F!C@%GNmMkKC(sWXP4M+im_n3i#5V$!fgH`-wnU? zC-KKD$u@7dLzI;TuwQ7t(RY_Dspd_GkP$=fDs%LX@>Vug&*8LXa=;SY&SkDDr7qhKTOpd)X5VNYU&sGW^Zw`Om~P_x zQsp&*OXI|KfE%C7zm5xH8%pw~;m_J;+!;H-zV+@u;Tz! zulrDVNH```2xC#(@dxOQK7J!=UpbLqdkM8dw{p|O4}>l-L;j2Z2-cN{@O>??gGy0r zV`?vRzwAIgiSvJR#nIvxU0KZua`C6dt^_sk>^t|EZw~xRz6X)OdN~Z+?9%G8lJb&j@w9l_c=N|6&2grl=6;#1 zBk?n;%GOm?ri|ZExpG5cwfKPeK#IAagMAkbrCJI z5tSd6pJVRVkIXz}P9lTvG218yj}U}0g=E-2TE zpm|H`>_e`- zU~-b?mrYS>)dA!pLtXcDvzL;qoV#)`J);c0U2$D~BE=VQ~qN&@1)vh zFku{j34ZX*Y}wnZBg-3o2kg~AfDLANvhNWm3Fj4RWwK+*d6Vx*Cbe%%asGlAqFMk9 z^K{fd_&!nMyIdUCht}QLFBXV{#AwujIW4Rch6AeODzIjE@pHk({tHF*D7TF3L)Jc_ z=8!(mbOEsN6DsP#p~B+2O;y#!uFqYclUF~E5ByykQ&qiY9RgfkU%9>_Gd~IbnY{E~ zgk-(uy4J&-?^&bmuEwI+3mPhXTuq7`TUxcD!Y#Yy!0Wa@4hPqf$JGAhiGRhS>d&(S z&H4QpC5e7qb)p(go{P*>)GkpsuHR5zzCqd}?IEu#YEs<)XGw;nz$bPd+48wW%-E!`|r~J-2d1WPwTr)it6-8wghAoCIUG#&T3T2G) zFOxh=3;7TE59!ov&MvgzHD@}t;5Xy@(eGnbyC{^j;WcMOpZB8Q^RFt(j!(xqZ02iu z2X~UoM6@nvECuyu{Mn1&-@<=)b5%$Buo^vf%K1JLqy2lNOs1=mLuvYz$hCC&6YQ}9 z{Lpy^9myhhWK;sZcscR}t@$`|7r8!&B>LoPWCXn#85NbxUK`0yqyxxs`xkx%3ZFcV zGp9eUCFsvWAM^YJV0DB}x*4ayb*+S&9@}LMgD7Hy@N*78L4;XdBixBZ!2jK4RO2D= zB78tN|G+wk6NwI$P)RMEv-|cIXB~iYm=%l!Q;?R;yNzL4J6MYg53FG=rfDs*VEjve+hgn+C`P08anXUz*hWq_%U)}iy z__>_F2i zWTo-vVHge#A`41)vrkS}=x>+qs-F*vj*4VA`(&O%8YbC+szW#q;swhNGF-BZh?&o* zH60MW*1-5}2H54~JcTr5fP*R2Q4RWBbGMT$W-cf>p+P{|Lm~;3RuzE9jFWQ|(%T2M zpG`+-z=<-l87F5e^kE}oq?VDlp&#lkJ0NGHcEvDo#Cx2}zhl&&-d-mcG4WSZaTMu# z#mg2Aqt#~YStmUTy*hT4K0VAMg@@SU_CC2#Ay$RQAaN+v!T*MPE&UMxG5_QO<%!#8 z0)0vkb3Q9GG5;hC?C5^jOemx*`<^DfAF^yqHF8dN16zb@{y9jagufod`3#gEUv*?| z$m#q>MATHeX^N_+YEx9TY1k34f2Q3{**`?ezGEMxb{3Q@_<9`gu-zU(mANeZ`a0(l zJ`=ndPY%XD^>$JIlk5lX!HZ`8Pdo|;xb5-u%HIhTw{?C*@Q~yZ7CEeb>ELXg=>b~UPhGo6`d-xG*d2O?P-A=Al9#Yp& zeMmC{1(vSI$ufmbT{@M{85WJ9G_J7l?31Mmeb~aS{69-nphxcq?I2jV^;qiJCt>M^ zlR0eZs^7=0xPcSR)j<=ANZ6#KLVBr zdyFz8_|7|g8%*8s^(&*L-A|;f_U%8NlENDcwpHK)NiKk2?u( z#DK&!m0eLmZtN;&_$58|v6z+fmO#o^Oj}yE2Y@Kql8Yf~f z@+#}a`adNZrgnF7NJp*w#Bo&>y`>UPD<0B0X6a z2ZQM@PI#L??nmkjwrtI<6Tm-hLWirrvZ&dfN#)3QEYPEPKMY2kC@$e&;4dF=z5=Im6$kTC2Su9xs#}JcZBPTqBwgn6P**4YERz8JrL^Lak9c( zup5;-5sK#ggWjFkr%#`L5R{QSCh`ebS2F_GXq+^0=b>-Yp4|UGDTXl zKzG!4VwUc>pwzz-fudJ(3?!gOfzQ^wx>#Jj$(kKo<$}k-Q| zCED0SEI7THo_jV9z}~2RxSvrHT1|dfJ_f2-*(O6gWmFq1>H%@_C%HeNpllSmHyVm+ z^@e1+yva~QlQtO+(4LKk7sOV6OR{rvjFO5740Ts8TW?{&Alh$>i0^Lf)!$W8R9aP8 zxXL@cbvVw50L$PE3w)4uI{n}#G(l5O>TJHApBfkPM(@;vID3?@;tp;8*-W2*YIM|| zN7jzx$D(zV^Oio6T3U1_a{a@&lA``){4a9XjN^ot_|4oQ>uK!T-gQ9BVcx?aZHaeym z%CXq*)^0KD#GV|H(PeZC_-_}NaX1yZj6E!7(J78B_N*^lgS~1VIo4P2GR_gBurEa< zhDSogtpK!{Mk)7nw>svT3ffrJaljWA0>o9gE2Az^Aq`sq3;-^qkQ(C30!*q)2qRUu zegrA>w}u5HG1wK-*BZm$4JcDbrl!6t%;cHm-I4!FJxculEqW66@_vc_0b+oA1aH)nh-yWK1VsvDrjA*5`S3$_^`JlezCF{t_({MiQG-LJ z2{hX;H0~1zpny&+VbKEq_&oB=NrZun2f7%>f~i8zjn6SrfB&xgV3AKdaM5dl9S(V+$x zdJjX>$djWbYCLQ=(>MRIMbn6@_Q+%v6(1N8=5Xed8SJ)98-SYK_F?pm#eN@kG21_& zJ7Vo$GY^4>M*KS(WjbT*W6kTH?4+2C)c2f0r7`+vj9o+eI%4gPzDzVTu=IpWgjbM# zc`tXJ>x*h3-*Ji%;76+{gYW}ffKs|F(4%5feQXZr~<)j={vgHa$ zYJsdqbA`vztZ;&fErC0S%BNcGv?JTv%O5_NX#O5qkLnoyP$dcEG}@MJ)xx`3!W5)F zssrc{nX*)FS6KL?VOGu2&B!uifD<#YlBHfQ6_v#wfz)4wUIac1p9HKB92*D%C8b!- zOUd@0w=t^jN#F~6C2CcgdL`R~u~y0U-mz$LVX!GWlWe~;I>>m)$Gy^NKS(nNI2tJ_ z(Js;X{*GhxOFu{Jy~}ha0gz{ye`flu^HL@t@zaz#Als4XC~RyyCj}1}{}fEC8v=k! z@WfT7;N8hq4YSM0YUf!ECR9R5LizLQta@#}#amdH%d&xJ038M5d7}i`-_d1!{Ao_+ z)=fh%+GHR}D6wktfs!+1QQcJ5mWB~i+In=ERRd85sB)ODqB%4bs%=FX;F(l3`MZxnyLYiRYZ}1(33CK?~) zB|T?G_|Pa%si)XA(o?xAs*L7LHa=Qy(pix&Yha{cFkJjE;D!cbEL$BRP0 z0$qMvLZO0@p2Es?#jdGUp2eQk$qo!;V=PQJ*;R{|Rh29%_9R+B*^+{g{A`pu_Y_uC zE^}2bD|C(Z6c?{9TwAy}^FAe6$u@c2 z`l@2rU8{-^gq-eMhFVR8<6JVYubYTo z1yL*)w<1?w)*}4#sYO;TsoM2L)?|=Q_#dR53WB6>7Fd%ktc&IBP!0&R)N2LevI~}5 zhp-%^%1VM{8umC|5<-fyF)Za3qYb+Y7S~N?R2pX~R3ledHAEYb-__;~bx0(T z<<{;3bvRo3EY>}`MP@zJy+RJu+$#Xbq5UeiF!7)FW^Lo2J2^0xZVFet$%w{}=@8|n%okJ)1Ha(~>OcKf$ScWqTRLX&c!aDRR?=^zcvc$rYh?&b;VR#x+PnT@$*@2 z#;@Su+{S&*%?Hlm1-Pz%rPluOLv;mb)4jBBVbnfax*+O)o!4~#bgEexwTo`fkNSiv z=SS_PFXlz33G6Vx6*6hKC+aQ|sU+LRqU2 zS}oiu*k7~7ID9vQoO~&)!?nH_Y`UB44+*(qSB?S}P$aeB%AvMP`u~C(*nBs?u?xI! z$~AkXpk$O(#H_}km^HZ$4xY?lIx^+B{9t`heo{MzNzbi=ho@iAUaF)nyJK|9ZAUB5 zpWAEHu~mjD*Mv$l7fd64u6Zd2$aT4O%th74ur*+9yAw98ZXTlzo!ofZy)Gzysh!K< zV}$;I>LhaFHqk27aEZJRtok;t`22HFow9X` zW>4eEE2dUQ;QP7C!!*?>BoZDQ6tU?Xg4R&pU^rc1p?5C}srl4bNUboeKWBk_Oe;S? z0{;D%?ThBchyr#Y>VhuhCJEgz7iUlz_YaW7y_RkLoZf`z^Kn}`{ikfOzSjVbTfvIQ z;4`+YqEHd8AYgg6-NkHQnwR(Dl9cQeKacr|IZm;C0Y|Y72P!Jq^WWHjBK#-6lj1++ zKcKGv;@@Z2T)rPHb-)u5<9K?#H1WyJkUhLgn>eDp}WvYa0y9*4KOd0m#TlWZ={!hx95}Rcl%QM^*8$x zdiYoSBI^CCy_jD4#a=`Ozu>#y{%cdsN% za20o3HI+?q$MD|#I>iyF3H1uyxSc@}J3u$T&cnp|aJmOK1rPiH-ORd$j7|ePEA6e> z9ArR7r(`dT*5TwvpU1&Ld5U>Jj#<3Z>z0Cjg9-JNr)hU^Zw1~mq;3iJV32Oc9;@cH z1xc3T#6a?r*>#1iH`;bU@6eUUYoL$x|r=N?l?%0K}(0L2$ma+G1=cJN8@Z7GT_Nz5oyVk7p=}sGe69W~l z0Oj^TWLpe##e+C^68NbWZ^Cw5k?vqQ*o#|PHPJ4r?R{25wD3_tch9E`rbc*eRLPS6E) zaEXCf-JL42=7Is;UUO01Y9zA^!I!fh)f@>P{K3wzsDtZpKuB-}BVBvHRgIX(6KY*uhqmnvOwVEm&TKeea5VG{yk%_za%Pq$9lBIT*V{lLQxhlzU-5<5(V8EhS$cs1GK z`(>EHz>C#;SJCgo41?+AJRzRC3^im?#$dx=Y2_V;^Yr2%!{fE5MH88xwXTRUwKL>% zw-34A*v^p8!6y9O_F$NZGCv0I{CdOfT=4v9tA^MQ%;SQ3{p}0@Iz(xPq!|VAp4#KE z#4O{)WYlw+fJ?is7|_8MP-Hx|}MDNlsVu=0fFMF8Di z^Md+F!08jUNDH*vpKh%SX3hz;=BbZR=t5f4(jcn6j>OTD2>a0le~d^T_IN$~9pSxB zqOmU^@nJhGQCM$o+hK)RGu0^__SC~26_Q9_VaU3t+gU}pquMeq=u+ve(lEx=CR|2c z)3Mrw&#kw)kQh>no>Sg4<&V|`x>a)9?98v172=TDf&Tu-He6uvF0Gf?HKxJ)l}4+d zgOBXCN^OC8FRHgHPlUCMCp4`uF!{Q81Al@8uGYw(5Ldz0@tUw2G4HRk!**EolUO@0 zkoJ=dFIh(^hSa-WvMyj2$(yjF2I^qZy0>k~H2RKBzDOG>eM#5o(kZl&$!$kmU zbF7#sx%lSX?AU3kMP`8K|8UCq~Cvf}E!X8c|3puBYg zC!P@(!eMt#SRj~`;?=(bq&PttCVhL++Qs+Pb*oMAJ$c!Bg0H=1HDm#H`lvV=fh`XU zWBAVz!8{D;huwgmvdGY@8G+(c4)@OKDI5txWfT$8a7Dn*RybTWRWkMrg zB5V+AgiploVgz@MyT#wx*0_~|lpfnhC~}0V+A4Acj9GDpb=%RyKw{E|mkNvM>m>r| zyw>gGsOF&4PRE}XA}G@%SZUu9!9&j%3J*}nLgA>vxEtQEX$MqG?BIE8H^fj?2JH=d9Kb@ICpy1#GyIc3KgJPNIYik$t%KAKoAUR0T z%{tCgyc*zmHm?D-l+n_=|FPbSDFf^S5e!4geGH(}qyMqq5i2IZ35W0euo|*{Zi}Y} z{{!d#-2Yf@nlp*#rq=`JuF)wK#o~g5p&ljZC?b{oXkC(yKEww{5MV`qMm>=5Xi4q1 zwI2c?e*Dpz+9e(C%N;bwGY)=@V?~5aZI*4fJ z_z~O-fb*~63z#9#JLRAvD){51p$EPBsWIEyH-KvMj%)1{d{4Wqu>4~vJ?Q;3 zYY&T&!zDUfI3vtQ0H25ZJ3HC)%xmjC;QmZ4EAZ32gfi5kq~Rb-MJdU=p?)DuG(jrs z@9=*$iPF#>A%Zw0@!V2RMKR37cUE|oGSfQ0t{y1=tV}HrvvZXrg`QgF=#v@#;G}hM z3ls#O+f)xlw_B!`(iqR>wu$zdQc>!uEDSzE&sI3{$X4NKFnZJKVWQ}U7(j=EzWBFw z8%mJYVo6cAIT=EJ5_WKsxLc^jm)wT>B~ZaL)r7}~|0Lyh3-8;wvf_2Y*HqURf`x)T zQ;c;N1Sx`M@sehD+RsbL=IZ*zVS~WjYQ=n_1WfD3`T|CvzMGWE&k>})S>Zj%ty)=# z(G~}Lv9=yr13CxiRqe&VHczs71@DAD3Xb?UmLy=Qr4zrQw2#vNJEEj4<(4aol9FRL z)-Ma07jlbIDxHp!`m@ZuXaXNBcOk-ImTBv@s-9uB)s}IoflCfAl~i5x@Pks~Ih{$T z>t}#_QP?T&fRkhgAA$5mFTyDmg0b}72$REJGypeLuIqycS~tj(kEJY0`Hi$XGFStub@n6DfGZL208ib<4 zEL78-*`-#UO6h3LtB0=|cWF2Nu38*_iB38ZVNUFjTdxGj1u&2<{|z z70S%V#z^s$6eqciGwNYR?(FnK`A6)IjUaQ36i1HDv2JQHOL;WYEKR3dvC=GhELNIJ z<6@y~!wvKx#p%FcwQzcAUPqXpF_6D@E` zC)hE(nm$aGuxmL41gZ^T6BRWWl!jF}DnB?*rk_%!?&^w_e}2!YhDhXiPSl)D%Q{FJnrgpWN(9*8%H&iM(;8yP z<(BNUCQa%{t0$)x(fl;&Q99E>YG&P?Me{pgIo@_l_XO%C0N7V4d4SJ&#K4U#d4pOgQ^fsEXLyEFZ@>CQpE^L5(ReMY(rIICk zP93uUQEzmEE%>PK*$ip4K$TNc_c8X>VZ2;6;;~<#@@{+|^Q0ZC(58b^@oh@<&xdv~ zHC&?LMc;xrF^f0ZcEDbcn8?xfL{X*!oA|qLf4ta*cl$4Y2LshzLSc~y5Z&nDen-Bi z{vkTI&AaE2liC8 zfU?>#eQtx|4795}-R6<>XyilNB&ci7ILTz1dCX5X%h@Za{8YI&Tr@4cUAC)6I zKnM@$1sd`6^KfQ>SS{hGyt#)l(Lj@LB}BDpTF5;QuOFz@4O@OIVPG2?e(HIoy#S3{ zWxbmTUFh>$39(N9G-|K*Mx2j9;Kp@NjKyT~71K)D>TxaMufORRBflUX2 zpm#X@#Ylq;1~zoH;->E7_E$WELiXOh4z05n7ubedynS0?&dzjeg5ewUY#P!N6vJx! zn+-I7zD+V?3LbzlBROD~p%V*jsT5OS>!_T;FnW%)Z0*nr3si3Pl&#G;4OR zXQJP-c%7|~Y%<-N%)RQ6Lko<+OGhEA#CA@c&TSVSL7?1cd^y~qIJHX6l`Te0TVkTR zOiQOZvI8?#drEfU%zf%{c>+(rO?AwpyQVsxpjW0jnmffnSv7EWAaB6OQ(?;N!qr0l z*w~7dLe!cjZx=+YKfFA@cn35ob9OZT$S@VAaGM#vGma5x}qrFmTov%8e?o* z`E|5D+E$g~Kg~;6`huT@x%{)dn=9cr@NwK}29X|Za#?4cuEd!Wh>+$2fN2*^+-7)^ z&TKV2Nb*+0Fo3rc3=7EJxS)9^~m3ukqrRKgT7T%g@4q6GC;O z8xj@z*`5Lfu;+vjD9x}pgi%$TO;D&*mR6`fa0OXfX>0je7_Bnw8hT@kJH8VQcL%9F z&FE6eSs1NAr9w(Ur9s~mf}*pqQ-Q!gW|@>`EFFSfQm87=0=?>X1cmJm@jYovhwztW z#PDUXXe4on;g*FKA)EgY(NBB0B)+WlEUvxI!Ol({6fcu6D_+Y#Rnvu48aRua4peGq zRVs<*jfziF=SU$fIg1+(q-wW=r2ps=>^mc6w!h_wzfx5a@B6GSYF4~o;wfKePqG*a z&*Jif0H)6Pjf{9VO~?ozo_X0>Ty>yQyQfgKW(0etOx5DEsS1_aGf-*%ONF4~Eb^m( z3DlP<%e$p(@MX&KR)xZBao~VzoH_%Hp!S0}Lq7!5Ho__L6taB$z|3bW7LXX`Gpf!&I1B-=b#~7A^fSvn57=_D&c~IIxtNzg{qS3rsSt+ z6V18T*d;txgXhN|L{1DxT$*P)OC44U(qMk54eE*Cr{%>(2I9h}8vFi8XggfT~}+R2Hi2A7sz~ zY2W`rn%^~1I~o+y^=JDiq$=;I@3znftDM@E7a;A;qPs(f--BZMg^#@U-;%D60y zn{GA#GQ=S>?72N}&wC*r74H-Gmo-9@$wGiBjJ&>WTcu4rJ=5LkqZfNP_fkcs^T%`Z zU@gG4vxwuK7Z<`jeJ{5N2K~|O+L>sc-7t))5t^p+`}LG86~_j-{!2p~Qd|iQccACU zdK?fTawi5&TjjqZ4($(ttcm(*}YUs=9X!|S}xhKWE1NlCuh^Q7~9?Lec> zX5irZT_(H%2v;o>i}?`UvMFJi$q`-f!lD!3hESZ$~;tS^`p9Kws&~`(l?%op^d^l%s%Vj&$tm6e(nIow${p_@#Ii_}Z7m zXT(!5@DtF>)nbL1FOCtjpq`mlntJ&1R+`>}!Ia~^pv(%>KXu6>3j0kRCC4YkZD;V; zaaARyWouodD}We=>1Ca@nBIOsOdP{-tN6D5Jo>D2KPB9X!UM-bi5@~=DF+G?;w$Cz2E6B#g zAv(BB>L`wFSVHp)49K%lCY{!K$2AoC|GIL%-sF3KnKY0OpdH|InIW`t*ZJQ#NMzPo z!a$2xYJiO_qzuWeXt=CKmrI&6UVV>^9w?VA=GX=%C5j&y*}5=HoJ(u4~B)6j#MTinQEO_DYCy?!0$kc%XBRgJO% zW|~n{T;l1x$~6s!Z{F)}gy4Y)6;V8H>*+)Mi;?VSC3 zpOo+0QY$%mvh0)g(uDm|IbetSUfdtC*@QQd_iF=weF`uVVQk5Vkjzzt@~+{Zwm+zq$D zVD2qebS6F0>uBtP@D@~|r-hF~y8YyH$xPcGl~AwqA=yBSAC}VTlN0zc;Zf-+U#|zH z^+I5kr!nB~dDs}%bJI|TdR_u_3R`0)&K9Sply9z=f{>xJaSpm(FFEN-omAuNd0g5d z)IKH|V#jm*pMf|1n0uKUFN|U5Zh!NJMs{zw!9VywnxJNBVjurj4=fHqvgK7pg(bO# z#Y-|r7p|(Ts4A$`d)GDg2F4*+8}4|OBbACzLa#pfm}FB0k~6F?5vv`W&6^ro^oUbi z)$*rcgO0Ap%C*#m)0<3QsSy`nCSCjt6XlvLOXO^pihRRQO6j~Z$wrpKuODhcNZbh| zLMZTu&Gs=*uNeg|Qk-_RDP_k>3LIwI)5T<=?~Hn*DzUId#|Zh-ni0w)g@FkOKJrq5 zqi0*{$u+|jYE{uyshzPQN-Ua%g~&8l%&*C&Q-k3E%(;nNCzn|l(2p!%pG6KkVxm$_ zui4mvVq}QBRYH@{3z@b?a<7vm!IEvRY($V}AE(n1=oluszXIcoAgNn|9)xNzcwHd8NsB9e4?mQ!X zt-0;o#3IaXDu!V9H%&EX;!ytKDRAkfC#7f`=7i%)8o^K+32KczCG}GNIjoN*jbNm3 zDlJ+_nbXQf=%?)rLRY>J%6z?n5h z4P{Q3dRH<^Y&@l_D~k#%3UFEK=QfUQ_bD6om?B3n4jpCNNB!26$2oDm@ONPX9OJ3T z!8H)Z)|Z3_g>qr6H)1>P7)0|Zwws{M%Nw;FM~*u#kSf(o-aRRhJM7!By2){V0SKI+ zpd)~#jG~FlgmQyz`xN}MzjkX74$*QcVlh=L7lA<@gjG&L60kTr_=cpXzrQKjx(1n1RqT`}!HnYc#)AL-q^r#}Ax>+A zZwSCM^*uM91AFv+OG>?+(9@ zr*RGhh+wLnGgoaXWO)In%eg$+GLl{90d~i4>|=@n7CVA-afkwN@jbYA#be?y@cKOn zn|l}k<7PH4Vbi0HTIB`<4SN&5%v*2VKBAe801W)EM^vAV@^&`=GaKP{hit7*tNMcE z{~xE#Y=q;zorgNN3HD~E%P}UD`dg>#m!#oN%mBW|yLoP8aaCz0u68Kx87jk2`S(cq zcKnj$#Hm<Ed*)!0{dZScVtT>2~ImZR-Fvbb>* zM&Q;oP9>}0^1n*`Sb!Vj156qF==pEBxsCAFgH|1_Li>mJrS9qk2WW-4jhp{>KW>|r zxs8AZw9~9BLp@1ZC&IfUpi3yBtIj<2@*vmsmaCGH)?bl2Y4PH0)+y_KX_=C{#l+6` zyJ3hrDmeK25x@0d=&7y@6G<=L(R~|Hy$h!VGOCWEn%8s#==0Zg0L07}f#;0S#rh7s zuG=C6d~V2il7~?EWBeF+d+vva_!K}?x-@VGO!1k?oNC28v(pGj=xa!1caB27v z&zhat1P@_5)ZwsG5YB3XhYbXE!Bb zisJmmprGOg7xd(v4tFTlmJQ4s-{evxm44uyt79AywEJ85j{h{qae^|(IH+?B4palu zzKG@AIN<_J&|45047?NX<90(XN(ul)$89)l` zu&4XbGe1aXi#MXFQ^>!_wCjhUJ>=~lq%5QgYf4urRO2rwdNWsNTu`%Pg!JH7(pjB1 zvnh>^e}yyqyRW4~MsHM;n~nEEVXBS3|3<0|WWGpecFog#G1f92WwqOW7VH8$yPcXT zR!L|5mt#7&Dvq<5XBvD=S7cnbi@AuLR5Q>d)58;-i+m%-J4f?0^N8-eXxn8akJ$-@ z1qO&$pe;59h zI{>a#%~Og(<~zCQ+0U`v0L(#@-zV4QK!Jn*B|p+j#KCDErpN-5^Zrk)}5A|JYxVWZ@q zB!{{X1AmgnTD-a@m|wKn15!5;Cg7jP!!mOECn;8?wIu0B(bj(hIdtns>E~fF;yqyX z9UQkqcwbn61Tdob2)6-9m%Yd{@v&e)sNZa18ytH7C;Te9#8QyIgAx=0Tos+3Ww#w_ z`eOzI3@ck408MWOcCJd{PjxKL;7}LK~43z}ek z7!b6OC}r4BO$EB+jhoVK>3|EGhW!uf%v(|q?OMRd*a1qZKT8isdJ~#pzW^j>D3zz_ z6KUrysoI4yaFsCGJtzDN5SzVRyf>{0+Hqz;X=F$9Y=@23^Kufcc}1{>CLO$9B}_I? zYhs#wqPAdA0pjRALGBPfyF9<930i!*tf3#wqO8@*JMf$2jxu>OnxJpv)uZU`PP!x? zUOIq3+(q7RFg3y2kWLR?OGzOT<)VPNFq=p6&Tj=~kotzNg8RCGa;_SB9?E&lYM$5x z_+(;G-BaZJ`7v@zXusIpbR-0Ulx8#6DR1 znaBh#Cz3H%*0%0Fv2u^()lJZ{@k9V_;inIMV#7Si9Q0bUXV7_Ir`qX!LI*sq3U6wc zCN{wk-VU)v(O2EK(F+TjCWcwpvfo60Zj{ly&9b_n3Ar6Y%$+J>NBYt%N8iR|S<&*T zK>EyKoH$Z=lk;)Iged@?FsUQMyt)~j<<@3`+*1)x@alS5GoRg9FLyOpHiHS=!Q@BQ zOk7bzH^`c^q;P}W*=JfOALqsL=CO2bEh-+o`4Cd-J-$JnM!uEu^UC>dKrVA(FLzon z@H>G=naphKcbFG6G37pZpD1^v;FiPgNb{m5sMMWhO^zSZK^|@o;RLWkPQctF(h#?N zgXXy8yM22*$ZPom#s650c&P43cKr+dkM{yr!N8Ky*;M?8cB zn9Dan<4t%Hs){o?Mu}+&W^A#iA*~~9x@mT<57l_Fe^dAAEmT*pkN17NPoFOMc6#;w z_&)3u(y`3lF@lZn0Fc2H?hP)FAHjXbc~{?q2vj7A^fwJ#VZ}Y`@C9AJ5@Vx<8+Dh- zT&=s|>%La^l^+IYV!qT8q^#J_KZm4Xd1y)rryXN1X@c6Dmy_4KAQkdQZa{}7SP|ys%S)Jqt9tcEc-~WmehV!q9ck@fQ zuK>$<0vPT0(CkF6k39g5;;6hgZsc>_2k<@mfo~!LL-HJV-e3Ygw{Guji1yGv?G0WP{+E!;4 zr6Ll|MUVqLM!Rvq_16Bwzy<5QoZz8U`6-Vxi{@C6T=2gui_LN&&hGU~- zE$0Ul9+JDe<`k`WO)B(M@?N27GddGgFu9L;MH6&rTqx?IE*mPVu>^Gg zP`OLQ+Gdyu@VZ30_I8ww%v0=osvj=TrnuqqN@^J<7tx4eaEF^1zUj7uNx_ zoW&#L?xJ!jngE|dxczg&a={Mqd>L=#mQzAPgoBVtrXQ6o)ISuFzefS4#tkNKCa(2P z1^QvsyhuOGl(z=})AYnN>UA(Ci7t8cM%uJU--Gx?`doV4gCCI|{bS@=pg-PK;fRko zv0e#ld{pSb@8)}P9|6m);MSjmb{7z$39$7+PL<2i;V^SKvpvk`P&8(-oI+1emIqVL z6tEtRlaJ7i@v>K((H!eP<44>Z9YxpPg<;rL9;c%}j+cAT$no+F`uZ+;I^B1dJUbv3 z6mqah3AYrW#b{6!Mfe$VCfzw%wz@S!g@@Rh=QqP765>8oOcFOI${PHOQ8L23W@zqc zR5dc7(LrsG-Mr?MwltZP^-M~LK~QZBT7GzA{YHRU+sY&{!VMVukYDjI!n5DuH}e_r z?9W9EY#vK`h_<4b4I0D3lyIbAUo2A`$>yTwF1X=B49Z3U`e~lrT@7c$h}dUz6(aHq zJe5_eT%&+Ru`FnY4yd&VRf?f$&|)VRO~qI*@Z89%rJjn#uG|$xrMhX&(BVTY;ny!G zB+#144!rOW;nqMrt)JEmeZC#)uuF*%<~MhAa)W~Nt(X^{o#g09gC{#~o6!8`w05a) zlf`B?!)nnE^SawHK^FjQsct^imS><33S=j9TqzTXOM+?JOM;XfpW6&wTYC~|NHzN_ zdo-M9crmvbYGeDhdx4TKAPVQHFiK7LuAR) z@LiAnDCRfAj?oTb8hv@Y#ZsKs3~YxxXoys1=AR4Yp!SMox&$@ zkFs}o#b#)O$jYjs?dmtl8ub3hO>!EwZj`??dJWCc1=Fc#HKc~&8|6}?H=-H(9>DK` zZ;Zado8><%LF?o7$o~bj;z3kp&f&Hqne0EfVlJ6qb_NbM0IU?l-`c%QN_NC35k#6S z@9n*}45*91F$Ym%%N>SP$Lce1g!W7JE6A8`|HnIiAEc|!RDRlN^Tmue{J>MUQHJ;E z;7G#*k&zhN00a$i+sQOAqBx0V*u1NPW&cDys$>?ed{Q9R#sIa zCi{Tz%@GlO#Xd~D-^hu(p#t42hHuj5{rBOK1;p=_EVgk>Kw zjrGMImg5D~UX*{P-6XG8a7`u#9%~WJT&-|ikh#J9u0xi!>E>DcAjBbWr<*+wy+)DJ zM?7Ij3O9F|m+ym{2P&6Jccu?)y31P)-2#zH9F;xJC;H514Q5{Njo7!zMb$=xF71E9 zP+=(E2WJine0_wZkYyVpP4r8PVG<2)F+4<%w;J+{Z2fz1`^Y#kA}4kqK;@TE`0iEl zviJ>0-ifGnT0Jo$Ha12~7ROc<7gv_8G>^B~w_+?oxSR_wSAkx;4!!oK!x>8Ak^i zut95nb4>N=Z#r)Ah>~9d*-E%7jN>k$=*kkZm{O*hmo`J_PgW%YnW9g~YE(02pO9VV z&CQs`#GqB`@(EcB5B1DOwX5!r$c_kOGZqEfeIi}|1^}Rg$K?|8oREus;~tTp=12P# zzr{eR3%5`k{TIM%zT*}%cHq3`X87f0*{z%q+Udg&@MhiH6)LjBA54V3nm-}cMU}aZ zy^&sHi;kU!TrcvBgpuq}vs_}_*n;iaE0L@jl1v91koaxMT~91mmRyTVu$xSxx37C5E=*iiIyrYy6xSW5D%-=?J|sxu6`+Z3~NJB})l zs&-J7v?Ey@c6|gE$$yU!v(iy@v9OVbrn>tTsQy$f0rLns4zLm8>sD$58;pPZJrP|<0*lD3?c zR|P6uAW2IS{}R6(!SfAt=1l4^^Yj+xcXDb)9h5|cRezMjysqdRpWgyi0EtaiA)6(G zrK3&m0Z|{86?pfkA5~ zIDS$KJP$aFRa!+C8ul^{p3mQr!{Rd8;WfJ@6Bl$Mr@As#-(%40s>~@TEKndIIMn5_N_Ik|1yIW6=5H?_H|2D-Ujzb$KlkcSc`X^iV}P%A6G z@E4nrTEB#sbKaN1V-AauR68-n5RD+oDtIgMkt%vJdAdf=wRq>ZQ~N5 zGEJ4H%9^{B8-!8|qLQd%rfIs#JF{jiAnrI_w&Hrd+SPP{CU-Thp=UBohXT<2J2}w? z7pMqKN^f}JTJ(J^-eoOFo!B`jJy?00wu_ekD)*rsyls(ramyOEm9)9^h&JcpH*HSU zhQP)ER>&?cTnn+ZqNuVkerd~UsH1RjZ^&Z5o!zn^pEwp1z4`KJoERAfBtlrN;D z1rBz+NO_mdJD{Z!4$)wz>Yq;;9;KdxxKXI=S2>>Uu9U`GJ7S!x6k_#g>-wv#c~3FU zS|tf}BqD-PEqF8v(w6g1?h;P?PCypV@GlViIjt2Q2pEjjgHKuZReD=c9rV-k(^{$( zIZ(|I1zU%WI<`YNu?2!zW}Lq^5cUfajmFVsolW(|VOo_BKcxkNV1`p8RBUwDFqy%< ztB~@AEf9^dq^hk9Gq2hHkBc^&d07h+yn|Z@1l_3Q&i~)Cq~x`%SDp!5mJ5QdW1D4( z#Ii8QN$~YQ@wU*JPG&0-OA7_t5c*wjn@Gp>w){-L{0Sq-T%^7j48!w4WT(hP&4|^) z1jMHNitF|ie>boeND$u3_hYF(iU+d9v4(#C-m#aKeebBHD>oc_L^o2Z)I5e5hTI#D z-GM^16)cM8CaPT<`1`pEzCT$1VB}nL!MToX4{5>PibLhSuk3w-He|+W;G@Ym?D^ut zbLn*IhCPWc{D91I9dFpXnwOtr7OF(;3{Xnh_WjyEIM@P~j^_+C^ecO%Z|&FiyZLhm zBXqjXiZ;Gh6nTPF8OzY?gUQ6Ao(lxp;iAzfh+q zjxL#Pw+X5;##AvZ#COH zI_^tWM0h;^I`<{amsR{6BuXC1-xRtCQ-zH%EB;yd)~kOa&FR(Q2co}|mENf1Pf&K%B?KY zIZZ2=$NwQgrq8g;_3vTxr{G-I!`9z|K49SJga2P;8qmY0#XN!n!EC)+ z@4)NR{K+Z7Q1@g8lSHIu+UA=3w+>PW)T;&r{piY9QWRYsXp2JDFrUlh zUn0w_WT$0o-{*P&6q6XpEGE;vYm+p-{&;QDhcteDQUN`+F6ppu{_3Phc~c}3koN&> zoDzOEjvmH4#i|KKT|-T*b2AH9REb|F+r)0dOcqMY z{=THpbp}(@lXm}X>|V`+T4yf9HNKQp8Xge9Wv@_y*BA%PPt|mGW%1^=B5YT;o|&SZN-)S?Q9elGc7? ziSdp6ukl48R!O6Rc-ugiHCsY%xk~G8&3#YVr`!$5v5wS|3 zNTP9-Qa5$}S5-<2$hulWnfglUfEe9SN@xCtTu~qOa9SB5VBh6Z&bcRXT=!4{M~j8G zxJO`(_%lC*OT$zJKO0*UV4e&fsbkKhYF=b^5G4uyv<;{0k7JU`tg*FzirI&lF^<;8PrQGd3k5ePB=ZtY2}VQo&UO z2-(J9AB-^ji9dWbUd%AUd5LI*7S16g@keoE)dfcH)jtQbcX}}8#GtiFTKa;k-lPF^ zbX(FAir$vApKRWwEfl{s>0T<`fFCXElU@usW@mD!Y7`~Z2rh0WzXgFXR~RG(drdrm z$w+i+nSVF;GFxo>^;Fi=xPb-5!|c|JMHPL-^%AD@@AEli*`DZt-M2NF&9!zI zeVEkF?Lxy6Y+HT96K#8V@+8}i(XBJ7cL#tz{W&2*+`=yh$gn?@2aHH?quJfvTu99m zqZn6ZKmKubl3q)>=EpzEyP*pQsTlrI6X6)@(VVYTHr_&v# z_{YQ{0q+ZrM6(rlRLG5mm8Obh{eJp9Nx$2$X*cv{2g}wAJK>9|CVDkNpC6E=phBz% z$l)nW)oc6;I1!i{0Zi}YK?h!8T+-U>O4B`WSH#R8G`>-Hv$SXJA46m`gyyia{t1n#t5V zZ32tZgJN}Kx~;^#ycISXyR4;z;L~lI9r%uPo723q6}Ffxdz>m@4DDze9;0yqn^N+O z)!QxH!d7q}vIA%eL~>L-%}s;Jk;N{B=HCh^Ct^V>>@j#kQ}(ncn6{@)iGPU&T%lc* z^aJV(9-HCN;=#X|;h4>G-Jp_*>UBGm?X@YzKWaN;?Vjsoi)Q+@pIwwXB1NsRa>22r zwwK?t^a|4GD zQLHoa82--f;@mJNT;vycM?lspRDNo?Xbz=a%??jM<1d)PiUsSQICj~F^iu}!P&`QA z+-XcXbpO?*I&YG92z{3wX?xRrF9V+lxv{W<9VOhP7AKe)oihHbWqB*`5^W4j>rCd9qPnPMxSX=){jYAP# zpJubuwXrrAw()p|UeVBN3P|GNLDA9l(qLN{_JPfUrxk{v0d8#$l+$wlU|S!j*0|DB ze%plBaY*U!(2j?#gEX%7y*kKNuBIv&&WZU*cXJd$sh0rx8_sUx49nJt)?7Rur-g<@ zOtEPaSI#lpOgi$gZ9WXMt#H%ya=I4;*5vva+dwi@Ky_SLu8#{jI{fQ{jk&ZHT!tsq zRaBlh_`YoD?z*eApsHdON;aagHrExd3Gg5uQ?WzZW9{L97qkLs3}V#>p%6be#&#R# zWI^lXwuGbAnPl_G4oPHvo5WUJJM4ztY12-x?f6~sJ@)0A$e5EfH-Zvd8d>$?au?Hdwnrp@@lKklE9L;bc4bcJ^0I~F^s`%GT5pFs7%Zl&FsJv`%z~~>59Hbk zX-F>m^1(Em=4+h9*KPIsmQAIH0R*ckqC4c5D#>* zxA-7^+Dp7b^LmN*(7QeHV_;8wS5%tv+`Zo!VrFpSD1;a6;h*My0&@&8jIwwgtxI9& z3+6(sS`eIWe~QMTtxH@;iKUgU_(Q(7m8mq&vIs?PrnD9+C!M;hzMdacGkWCPHe%uy z<1NA1)QdNbGQB?6=A?$#L!Af8#PPFR3)-dbrZJ0u;&|_%)zYVvLJP<=-Q1<6``AbubB$!c~MTgA$@Qv9hyv{#_1j;79HM*|UIidM9-Q+)IHn3@w z+gWf1_6%$?r56Wk@H2YqAqC&uG%KoY{+SAPg)(Bw71`=Ziaz6|!@t?siy=wT8oaZk z1TrQaGwR+?VKr^fz$T-jV1uX0JXM%7v2UGgyps0M^^;Fl=a0 zC|DT}Jn5@O5#_9fxA-%}`>tW71tYoc#*v)6A~fLYmFsO+Ej5{Epigf(l)#1$C17pN zP(zNUHDV)U9~VCcR_#WBDne{7@JC-~Ca2 zg|6Mmw@3L5a^(J~X!BejRFt_+MR+AxP+2sxA%>W1Y^_?XDt?AfVCb*~+lgG+Z8Nn1 z+A!YJ!}=Z^@0eY-Om*e8@#(_=p+TkyWvJMqOY`Y&oC=^4BT5|6`G^tWWF=h1Npgnr zH^(gAQlF8M4Ykfq>YM}{>A6qa<7NA72Q4-2eNmvRPL*+Gqx?Y~l#YM$tzyDXI@Y0F zpMjwxb^*|;?-<<$9mUxYL?&^lT6hX2jE8_6Zr~T9R>ZUXmx5Ku1@YJA463j{I`NIVb9T&w-ugQGPDp z{PM%dcCM?LR*Q0cHEvt;?uW#od~^Sk;&jk={#!gW=)1tRLYQf9;Wf+vEq~=w`Q(Xv zG`0$Ze_JbVr+0}jnqiayRc0yu#-dI15_4O0?%!ONLP!o3nr&qCZdQn6?i#DBL3aB zmXw&E?~4UcxeXHVxDdw?wa3<(9!KGwro%3PKSymIO9y@rC7Vr_no&M;glPKQVU06T zL{lr7_=wFyYKU#4rKZRikE1PBm1Q5h3p8l^A)69X*6cfEi{@D^RuQ5PQY^heEIar- zdcR$knmC^X+T>Epe13XFX^@3p;a zPKVJ1BM{y~GKsy{t^)LYKe9j2KH$F6Dc*Leg|7AX6dk@v9puspPjuL*tcIWUR{NkMluqhf)NJ-Hf@6z1E=W z3YD8i75bpEgEd|OvfYw$*4A1XwSi}CPbccBU!`7X#cxApv4z}L{$A{x|8hsU!6bQj zOa>V^*CEGxy=#;r9;9-SZa=xc5O0$f>h_R%#kwC1t9Q(Wh(o+D7;MD5K=)y~Ntg-> zCULxvlZ0#HQL&@Y%x#f;nN$)|b3MG>WE&W*Y+Y2V9s`4SeE`ld%g))pG-voS=zyt` z)qx-3nz^~zrdG|UZ?+XuHgyeH_0aAhfp5U~-O*%g+gYIpmuc31|5qaaPFq%3J0`+kqK7uJ z{k%<8_79k6Nj;olHXlBpFdgo6i+y>_dr_g(D6eND%O10-j$Gk*3%}3@4IWC9D4tks zCMW;R)-BwV1_ME3q9#*&L$FWtOUS;Eik5OK13b>qlj>bPW4 zb9b<>h?6k!?;>C_05ZZSZ~-_}elD~V?%+vkFLwz&Rr1ZVe26iL9GuSNw}hCOF!hnr zoNcNPHe-Ml@`q9C>?mBhumlH2gwhCCM3LMpwu*S+Abj1^WM|MdCn)w^xME9Tc{e_| zVymJIsh%6>quNyk21leGaW+D6;S+^tj+xD@|6z0Usq$bJmW0QeO!59@hz}OL1WVr z1_aR+0q9fEvLc2kEvqKCAZ&eLA&W6ldWr%9HgZ*OZ$lHNsP;yd`F?$%_@+>G|4`K7 zIJ@qYZf*<>y@7scp751W!vB}wz}vX}_=3JF>!Z<*H7&wba&xp4P5z9Q6b_8QOVVZL z>WvHxzLQWu+KWTCvb*(fntdGL_u}U|#KPpzTke_2DH6H`Rud1i6C06Oi zn*iTlIa3+5vK~G#@H&rZ8eX18@n9>-v?~KbC`Lc5kS!DWaiB$$E8o~6JeBFnn&X3>D^okS zH1yRkY!PXvD0-d`dam4?p)0?LWY#Hqyl)=(Pc11OYx~mYuu*mRB3$`M7dXNseNa{2 z1g&Xi+5SUHD<8C!h;mm5f6?c*KH)TnE}aq|e1EgGlp*=;oG`_FZtJ9^d7&WORmsJ` zd!u}_F}a!ncJ*i4+0DWUI{b>HVQ-*zrqL_=*j^y1TaX?s?Hk+XP`J+wPTVi12!3Rw zei6A=Ux&krWr%ro!vL6?HDgZs0K4k`5UOAR0~Y`awE&L$fEdNY)AM}~S~P>Va3HGsUM ztq4@h>KrIg0;1j$71txOEn23aou1po!9k`oth@cWO$Y!^hGAeC=fR|pYl7{klhedb zCTL)^FwoH-Ec38K$;}EXn(EY;vdgGS)V41_k z3OQ9S?xy5}x$zpwo8uco<-|1Q$cuSZGpbH})mA`NZp9Q4IuuF6HCz7-$~NE-r>}t( z3+BO+S5UI3$UD+EG7M@ZXRm2u#`o83Yt2PI3{I9yb<#y0B`O2b@yVe1qA;rv^)aJo~DxFFefnB^w9zyvHXheg6 zM)Z)J`LAsm8Ten@(xFs6q2tz4x1=73|6B{($VGlWQZ78e4Hci|llY$eETp`>-@BZp zS#bteh8A3gv>M)(dBl|O=+xYQukI;c=bc?Ak^(R9Abt1gQV#y(eTfvjsyCCAKH@@> z?A0ZZ4jXiFWO|+M-)&7o4zn@9C<8=)GH$TzR?F~ZQyV05b&yxOlS?PWg`-? z2GIB1@CFg2p|^rgp?*y=VnQ{k-n$!@rBVY$KP#iStp{V7ZV4nfzU-##8W^>@~X{5)=x7 zsg_#m4WB$hipcT>BtNAd5>%S39+E5}?DNAVmSzToBeck+Qy0ig{vvN1RqxRqet;r2>5= z^)wH4z&N!Y(i4CRy<|Y4pVZcaUgAYhY5FpH6Y4vF3TaL>y?aZl57huCigG;GTRJ+x z#Qz`cp&dE?b`&806p@7;QABm1@T+(V{vEGDLOumuSypN&`77urKNU&+wQpF#cZpmY zDMfHU=mCH@!_-SPAaZ$*49|ee`pZwKhnSX~Y6_bwB_J~vqgt;yXZBKCd2U)gSOOJ< zI13t(K~ZXUbIE0&Aq}pEY870lf2H+-;KSxS^Qp0Z;Y-4ggxSA|UUC>Oi zakW6oRFfHC{_#J-gpl7TxNgI7ekN3GBOx#BMV%fq%EgT(sXD!#9B41uV`kL5u|#pn zb+R|nGn-^5dM21B*Mq^j$xU3OPoboyoF7pr)dl}y-9s_yp?PkFGU}oC_%EhJx1q%wK+Lo|B*mu=I8_MO#F)=^V>M_9=HZv zz+g>7L8EO*H1Hya|1H5zR#hAW=12p`)pT=&CI-W9D5yH7CAGSmosQ`>C zuAjkx3Re!`$Z)P47;8oSbeca^_1(E|j-;qI$@MvshZ6k-^lm|I1-W?6AswD2<&X_+ z%+X=VggGQspDFEcPM#_a;N2#E0n`zDsl9G50=ORLpFxg@GJZ1dcoI$npYn3DSKf;i zfRrPQ%4q)j80mg#JULw;xjHP~i~Wjxp$wv(vTaG?#XpegdCH3< z#psIru@}F%9ujpJkZq+`Zvq5-4$KRZl4SPZ#nNbI%=XT&UmEsWWa-?eSHP>7f=^p>KTiTJXs>CaSVlrEJy~wMCxXqTVD=d zR&pxB1?&8hC6cNE4p+rNbvL^nP7v8rxT;SgBbG|4G9waS)3F}j5S?6ZrTy#Qqbrvd zNGcP62^lU=Pl7Q9bxgWRF*_4b&qwU2=sK;fV{{#n*JJhhsoD zm+G3q?y{j&Qn^FESbE)@QxBg2#5E}GVOZ>>x=JZ1=lKv3I84nM}(GvP;nn1R3aA{&R*ub9~dB+C;QFJXI5eS zo7PC3sMx_47@iFOsS@;Le|!XX-d|#27=$mb((dD{rA|t!RMu)(yI#rPiuAu12_ZJ8 z>0?Nrb<%3Gf338Oc-BarN&B@@5q-|dT63gmjpQINt&x(fH|ZxSSS`(pp5})gk%qAZ z1r>R<)RRRxMsX21>t7@C#wDY4v2u6;jgBr`ZcXL6 z=4ZUpbe?S9jKNCYBJCy4&C;SMug#x`$0q%!!wanaCaD^sF|TqtF!d1ox6z~H`EGn` zBqaTbyUraIon+p((Y;CK#TcpmugoQ{s%ZY=;_^}!vyu`|BVz_v6)jp>%3-v`k@bF9EV*|QRIzn?n;um z&Ao^Gv{`y7q@6?E+1sGRcv_gt|H0qQ_dv?WLkYUc=J|f`uqbJ(C|)k^kDqvBaN+ zD-_#GXf6DAucT_nf@@)^zb%6){l=0}PaTRN|Jx_&WdrzS_=LYKbVAj)f8)cqAd4=6 zyys2ssPkI)M3b@!h7M$Sp`kPJe*_)im8r;vT4s z(@8-FZ)@&9+|U5e4$Q9ser>{s!T=-@Uy1fNg2s5bHH^1g*jPpSy&f%--ecula(uMx zFwfr!U1pj)nDi0zdA&b!`gHH2@2prTLpmS>+1gouAbP>hS-7PqwO254De0mw6Ohn+ zJ_j3YFX5sv9Dd7FQOj;V_3RmCUgd}2k*k?A%(qD$Ny$GXt;*;D)E8dsrvitpswf$X z8Z?xx##7WvKb1~p)qKKGvkqvJ5JEvTZHc;U!EV-g zo3{HIYOWu0XyigoC$58kv6ANaA&^F{)^y^3Lb5Nu)oL}NmR}UtpW|B#3H;x<7g2kB zmGBklYUt(7yaW3S+$T+3qyuQTCmbx{wzi&>jUP&@(NL ziGJuMk@a0!yl~UTp?FF%k>01IurPNti-srpp^F1rX;ecmIwCp3?Zy->Eae7JbddQV z312`)+;mDxHc#+FpQ-+U)fc*HL_|MrVTvE&1^_CgjRCKnk|F|$DG;Ml!yZ?;*8@^l z^7oUHooRLOsBI8@;fJOdBckv^7!j5KrGt^+@EZKkVgjO!1{<{O)^YI1Q4E`eLgi2p zU3*T5<2Q+`;OcOQw{R!mrz1Gbm3}znV?NYg?}0mQXuc{jj8_I|DSy9PJ;?oY zbgq9Y11if|0XoUl-z7EtjP5wP$L9E_Ftjop8hT%S%dLV$r~b)6YhEeeO_vbb{-6|3 zuGdRprr2QHll_wzTIq>~-u2*(J(=X6$k0kp6!Z;+P0IWeZZU&hAJPV#&LHJ?r(&yx z6gtdnuhNGo?jAlVPIV^0E}&a&1_c)QA)Kohgq&Q|OCrQ{TvgzQn0^y<>mFegkTy@x zvM8<{IA-B(VJb4|cjfNF$2Yhg0w;Kce(-hNgw%IW2p^Ng?#4=TzBu^^xv((#Q8H;^ z@)9y5-{>V%I~ezp86Ayxp8GTg6{U?_PY!jY?-IxGDX9InANjN_M~re3V&mb7GK!K* zE4S27&5$0GqLjVphmN2_gJf1tBh;Tv#%ToeBTz~J7ehT6(6$#tt@h(|Rhxzz!&uo$ zd}k#kZN$OAM7xDs;>V$yCaFarm_70FGg9Yph6KZ{urNF*7!)Vj9#zM@;E83F z!Khwske(p_IW3(H43gIT#rQZ6ICH@jNq^WEk zz*^FQ|Lwt6F)@^^2k%7Ku$KFwEWzL_$`Xc5Y?4|jW57^L{LqvD_5W^frGMf7kI5|d z!}g8#WUYT{GQiN9Sn&UDCWo%;XsC&i9v~Ch_^FlsHsm$B%9YLV<0lSPFH{DBoOn{o zAa7rg?7=XEIewV6!WfRcC&1xvxFE?HVG|L?uVWfu+)|sf5_SP??^YMg@k8&>@(z?a zzSRXA{jhfBc{~ciQUo9a`C*wSJ7Pkn`eE|Q(%9$|Rh~@ZS?-A-f|R|O?yqD(rA+|) zh0_s=ndV1)1sYRGA8V|t$`iq=P+*C_oGo$X%)}B;CeJl%Co5R;)_U;1s*UH%3ZV1okZH)Y#|zJ277QQB35ef$Air0 z@i}1zewgQ9%ce{@>De4pvF}z>HrEeB9OhUVUUmVM`fhc>Z2xL@fii^b0xI;~`hrzA zUho$(9})xm*WGvpWsK8rv9d9o<2gwRc@`1x8MO(@I_RJT38W#DFUx z#*J7tl(INC{{!O1V*dsPRh|)yO9&e2*Tldj{_0z_`}O16l3~y}{`Ks^l!b+{>pkTb z&qPUs0p-!*{~0HYK#usf+)faO&h*gZdJ5a&;Qxu3D2@;}AT{kP@Z;mSDSM6B2Ch-{ zn?P*2A~fNJ7g8~4Z~3oh+#nG0To~j zS$*}!PAm;XqsyA6`(kU5jQ)SeK3H>5qi*2o5-o<(0G0``O3NDd3R+e+0>v^Vg~Pz@ zrb(n+?-rcV`&c2IcTD|9{J3i!40jL80bk( z*C#uXYB+^z_SJJZu_>vWa>v4^q*StdsbK~AbBSRu$y;K$Mh=x2?iS@eE-1lJLFaT- zEJ-RctZ8rJp8^f^a3~&O<1TO&oJVXeJSG&2yHQZ$DQ-+a#+K9=71R@eMf8j#x*x7U}b29aBJ)Ny;r5g zmO?c4)=AFlk%N8(j4%J-n$$rJl)(YRj|)HrD|=)%FQ_E(4P^LTFH32be&Zv42{GwA zUv9Z~;l3SkLZoo23AUJR|LvEhj+FPui=Jcj#d10r7X=*P=ACMa)3&cjU890PjvUyn zlZ+!)6qnI|WcW2{r%haShF5s6%JZlQdV45lrpfiqGACZOmjh?2l;Ne5d}*R zVt*jpyq;A1l5?WQ1fXzBcaj0uk)Vuyo#RW+BL06#1!6&2jaI~g>^(M=ol-tt3x{})W zqTR@Ur|*)f&xb@n@($^orioP*6_v$Rm6iA*nWVgHbdXtZ8QJ|@WRTUCg==;HCEivx z+rbYXXqARf-zDnPWkDENRJy2$Cax$dSzb`Jvb;Ff5$nLuUy%O3R=M=DPsyKG5Owh3 z<#;>&_{qWJhgfqTlhlnU9rjedWH6_Uub4NlxJp;8s|Ms> z$JIkGw2Gr2KOk~)Y&!kx9n$}!R+;p#YX?8ukQ@@;hH>J<~oWj}8pLmbR+mQs8|Q?0NY!Ny&1_mKl9p6@Vcd zjym%xL5K22DMGC$^FNaYgql?d0KX>Cj~)W43L3d`-Q>GZrT#5}D*}Bf&=~>T{HYXC zW(&9Hrw97nV)s{mh@@K~x)SOxKPAwcp@YN@@?wZqWKqi;ULhQ;)KP&!q+kPrhblgo zmXqrrN|Qqwl`yiy;F!4{_PE~Mo7^y-BVPd$6oxuWm$ghJnJr z_+fYqEB^>T2tVL|MMy*u;!jZF@iP91>3M(zC#}j=7o}<+)S0n6#%KpXs`xD>A zsA1&VQ&Gvp`gGJ{^2kNJef?C_9CG3U-Ui|=q&Y>}d#@-6)qEqO@(00UxPY1tMw?3m z&{$<_rFan%;3hBr41Kikmk3p-%Ul+KniWumxly2T#QtjpbK^3X2cT;OR3Ww+bn~wf z>PeS*Y5+>lOxdcq&0;gy$nf8!EGam5!I|T^m?Z%yWwQ<^f?K)#t2BYE`%T(TKKxet z(_`X?L4{S!ft@af^L8t^IXL+TX@V_IB=F$A?oA$Qt_(oqhb}2xfYK#(5mBuih69?u zn+!)B8T?BGv&R&8MKmE(a5%_`-=%D_;D3^wf_~GfqW^{$S5;&#FAqQ$ry{X~YLeSA zXjs&ox4&Js7}f@$Nln*+M92IowU1yk`JVPP^SS`ks6Z(b0hH>D&H(EJ(3}FG3_ojz zs#q0%kfF)~(3swIK5zdcaz4Qn9tkpq9bp++4I$jbpBEpYwZ9O^xVgPg#lexZk#c!b98Fa!SMkoWPnyC zL3@;YjCMI}+Xf$ogI3k8ph*!_(xju+o)%;)S&J<0?;Z*YK1L8!1CV(_0CK*1HFH|D zk$kINb;Jzzi4!IVptw?72m!rTyJo)$-D-RQ3M&AWiC{eOYq(d2GGZYhm6eU$9BO#% z4F&OZm^){KA0Y{gV}_fn8z4xju1{9tcG)}A64_z#Nna=0Q_LG0Ajbfwj1_RIC5Qpm zH$ZMm>!f-Ujg;)&$yJwTA7SxJhV>0mH^O41maysu7;Mp+ayzs(PFeZEhUPZtaa6n2 z$@AC|19hj(F5g;hI;R2NBe+BvF?Pv+aPPmmL~MCU&k4%-Qu@GiVXEAq!ZMrE>2%?e zPzsrF7w>{Fk{u+0VehLOAkn0{)0FiNF;mUo#>m+62B;7KP&x}hhX{KULzOi^f8fzl z8ZlkWHHTd$SHnzGe>&`-{SD9{+!VUOp$$KSmN!6s0H`whN~>yc6+=yLfZD*LIUlgZ z4!xcBh-?8=GMv@`jRAnlqbNWdd2pp1q0$VZp)t5A`VVLL9%h5jS2sXo&~p9GNz@*Q zE>0TcCbs7qQNSp6l7VYPg{iA#UjNwfc1g?@M;0$fk?E8%MWsbF@vC`YN%IT+W4nv( zc4FHg1kR1bhHZs@7n zo+!I)Ufa+CJ@cpw>RK1Onjnvzi)$P5S_0aWcMRHnLnz!LvYGbe^R6vW>l$(yO4$s! zS$i_Kn>M7Zt&)bEh$m$;c(t3>mbxHT(OZVjhx~5#Jd!@k?$9$^IYCoNAhi&4RSaUi z=?y7J3mK)iq$+l&j$4G9Hwbi_z%3GoimBpm;SZFR_lv}RS{|wMF0Lsdb1D&y(xH~W zMn-%2&q>8*{(aK5hX44mO>eLau5dd@*Ia3k*<4R`RvLy{km@_KmXA(82%kVL{# zh82u38OTp=sb>p`OEcMIM1}MOGwB_E2;cZpB`@pl`dBnneO>sL(akE!DAl z)lsO2CvHYzs*U_ls7d@8GM-q9%*(bzos#8I-Ba@?ifS6p!pWlDqFc9}>P|dr&=L@x z$mVx+F4TZhjCm9Zzgp9FXiNZwIK;%x$}wU`;+rJ8mHh-2@W4vQKWz+72V+L_xD|4ED4oOQA=HlVcb@>=D((>FDw# z(`fc{*kkn|f1a_Z(FxjPO*}b@L0dkS8im6iX5vXi0iu5q57YMy9ILLCTt2C+KHEsmdMlVJzdlzgWK+Gn1W1~PPby&{bj0Md64E_)9n8c zNYC}2VpR8%Kw5`$(1i>a=LydWL!lYjKui4cA91%+%Xn}k2>+&NbB(Q-zp?_UXGfGT zES}#0kw^XAN|=iMnK|~(VG;q|5XJ=!ka*P2LYGRba?;+aKnkNgH2k0`MG0+W^3?u# zi99vSp2<9py#0(;i+6Ox>@Wxft^JTCDMlTte#VVD(8yVYA0>E5znS*gFV3+pvphA^o8LSOup2KZLse#!}^-LHC9n4H6~ zoIyOzP0`Twes)qi%WfePpO7T5LrgXfVW%_{-L&PlicciP(T8ZhW1ii{leu&46;zcn zk@)A^3!}Ju;MiRykeJHYqz>W_JaXS6UhEYA81gN?!`1Ph^ZyfC2^m5UVT>?ESS)N7 z?m%i2zwo&53Rgu6Dr1xL>|(A6hvv$PN?I0pYzh3LOU(mUS;b6zUA}x}QEAEq)cRR# z9=HEJn1TKe>QGThf|n z+H@K@e#K%^_6MlWx&+ZX{p5UhMFicU;2VkPRm&Eli_^6t_BF9xY}K`}VCQ+fVlCwS zJP*rr);uRpcS2-`oB@kNoC{wfnXkm3k5d)YAoIMlFh+Ef)N%oZw<8S3a@MZW!a-;4 zPmrMv_ERVzh_^re_WQ_ezx`Mq9eM*TSvOfYEx2LAHFE2DnR|#Eh#%nbziHP-N)LiX zys_I%&*?joKF{h~89R3lE^negZ{JI*AGPmnK6u_ToOBL8g8HBJ1a4~g0lJH*KM5kKNbirU5PMN_IC8Vvv7&Z zlbnis6$&%i$iH8=cM9n*R3Juk3fC<^R0b$WNBrZGx|mm<1vyfGfazZkS8Dt+%o8r? zLe%xa@3T+@-tly@lk|HgIT%b#Yll$+aTh6k3t4D8oQ%=g(zUV_v9$%D^ALAQ zz@c~2YfDMW)5(*`J8y}8^4dFi%Y8?Dpch>NQ7ASd)(Gz-vim5ekl-U~&2Zl2U2tJa zl_F_>LPF75_&`ZA(uJQ)M9lWPc7JoHF-bj<^LljB$>y@LNvZtd+oR;P-AK!Q3PmPA z7Gi~LVI;hg_6k1XRpB==L!7)1N~}yL`R;_nMNHnPL~`nfq*mm@ckxlpJ8qAv7EkGp z#OhpZ56wnYLJnVxP{1j0aasX|+;`|RdE~yN?!@%5{cfUr&wiN9`KSF<^O5)LFY|5K zvW9J$Z{!mZm)syEanX6 z1B<3Sx(;jkILW^*-bKc|CGKXU>(oZKxE2~;b#_99-PGw(=nG~jkzDymJWMuxh~b|9 zFYyHGZXnQNhVY57R)|KZ^ndXY2SwEToY!;_ysaDcrfL7Mee(`^y2tnE5!_SQ-r~g> z2;4=3QZ#@ucML|P~v2A^g&Cy(y1V& zRQcHSlQfCA(-}sD89tF5Es7w*h2-077M*DrLx<7fAo}pbH{<&zoE*yFEopHK?NK7R zHqWBwBnZ*s2`7iJD5oEw zd8oN`LOHTrZ{d=`=7e7J8lecxm(_&*jB4Hh&H+aaMZdFs?_s@?@w1yRPS-f4~Asf}6aiz|)I72o{AI(=8Zd0d&^$s1bj zg3FSVEPE8CBVQ}kSChr%`aOrM-MURt+%ufGPxu-;GZ`t0=HO!zmlX9m?mh@qP_{Dh zK@gPNnq(>XSRAS(R+g?rs99A}LCKnu;(?>b3|T&ZaZyTc%Jh=ViA9TX2?wvfS_MD4 zWYOXkG@sa*C$_?hnudkNlZO2+=cYxaMHQ8cD^`>&A78X^VQKO5lA;z(u{ON&6I=V! zPT@klw31o)HJE<@!4dP;E?>T&WL0t1z>=y3%Ud?1NQO$E*zbc&(f_KP6!wArosyl; zFJ7^ta(U0ZyoC$bl*})M1$;qCQTv5p6)Vcx&#x%UTV1lWBu~3t^PKlQCxm`6;(Mri zg5m=g#5=?)Xj~jnpS%T||2CmS=!@iyU*Kpsj`UemcqEmDmc0pSv=(#y;0e%xV~7+E zwYuU*lp~$X@{$!5Rmf@l896r8+Lq*AmR&KhH5HXE(2diLqrfck{!6kec5v0oGWay; zM(ai&9%{|jW$LqXN&aP7HVvvk^0xVCM!!kFiGj)GA=X&3ZwQJq?Hy)ySq3a$UbK99 zNqO|r=%s1;taNrAnKK0D=lmfsTYop$nuA7BRCF+cW*;7GO(My6CuWduK5^!{lk{0I z@(%)uDlJYKw{AsM#gd{iC1oY^;nZ+|)PLekBi>J(?a8E1oH-=#6K4i7e&Wm|pMUI3 z7BK*U7W#4PV}U3A?n@zU6j>|5Nrw| zGA}J|y87s!?-vwFCH!(<*XAwC@K1=>-ly7f-Ax7@X_lyx=M`p;Loahs4#d%^c zQ9@Phmyq{nlQ0>68FBo_AgBjGQhR~X{D!*-vrZ}3lm9pWZ}ROM4hPA*Dktigf5pYS z;H*~sK&(~#*aeq`D`5QIxguwh(^q6W<{=;68WgehifqxP>GR#ek8`icaTJ`XYp>7m z#J-aU6s1fpDlMx>S+Ten0?8_rPe}YZ@n>@MvYaVCXnc_V(T>hpq6rQa16CESD5^@@ zpR}K?3sQDjj-h|0v-Lwfm*sdm-5J42R;rvKgzewzBu5uil~hzkkB%N4Tw3@DH8-fz zKZ6V9+Au5>+%GeDhpoe`>15V0YaDCRJbLAd;&RkM(;d?tqf>cc7<@8fhgmJmCp!vj zT3n0j8yis@uLi}o_alQJd~N5?I|sdNW@@l-2~PXUKk!gf>l{*B%+9bve z;ikg#LTh-n6>&8Pd8q|2^gJrkC;c-vGtE0==TusJD!6d8WCJFXH-0CW>vVT2$?l3G znW=;HA4JdG39sgC6a+xf0kYeCJP?jEa|i0@k;ew;A84-WukX$uUJ$RFXP{YHrwAWo zxzu5UFBJbHek8spz9qgYUJ);ee+OZB4CVztOsfyT-Qb8w;4!)jZmOHawc>KI3{lNR z;tX*Ta!QO42Z?>eZel)c5b2@^0;yFriBaVI1Bu5-mj@EJ8m2x0^KL5PKR`;y%Bx96 z^4rP8o>3c~m;{xQi<}sYOcy`gpZE#cdtYJ|`S{+%hcbhVZzdlpKTvUW}7SOoiJ{j?J^ig}my}I*;Id4&^>>M7E}WCiqPSZ2*WYTWLY2jv?_z z`>^8Wl@Qho?}XV&z1m7xLS5XbwZ@GETOgCm-3Ow)J@2HRs0RnEu{BRDbuZ<~m`<^0 zr^JXa!!-+8JC0(!M~JDy&mhpJg<4^f(1!mWk9CMI#nz8TrSb=12%jLnB`g%Cf|Ktf zv=MB)s841{6}ukG!Z-gLx~3zSOS{ieei{A&sQtM!|X4wQU!q~GQ1 z+UoN&gVezH2EwQrU8#P?u z=jR3+So*rdrt|3YrQpY{FUg$*h4TFRn!`d~rcKVjJF!);@n^2eR$WJZey<>Y|5cnJ z82c!Ya)o5M$WL!NOo&FE&WURf-m?%U;brhKe4Lw3<@tf;IrXrNATfZVF=9IUXZuN6 z84)6(7H2c79!3%rF&`8>xd}5yuj?h5$y>c7Po&bF*N?AoI-n8ylwA?x*54a6j^4o&7xWx z%r48A1e15{{Sc>a=Vx97R4*z;L#kJbdoK0^PKyKQqrpS$$L0HnUq-|D_LYq%i2Z>v+p0m(8>^N z=>5aYv1&RZx;&u7p%g2I>j=umzrv!m>bQ>ZY57sOUFdRPfZaUt=wKW$vXmYgWoF*l zJI18AwS-n0d}EJ-AI_3plfr?_YV`3Klj44-qGun4Lm|-0b8A*3plzi03r@wXtzJ@f z6ijiR?7Z;?XU3ZPM(z+!H}@zwVW4lk0nm1mw8z=)_ZzOre#%{zvN{l8itu{uJFCR$GjDiO#A|BR|C}Uh<4!1_!C*CJMgER0uH1?|a zG5-HvIK*BPKNP>MNRAa{acsr%iW2j{%I2-cxDDb2TyEeBXl}K)k&5sr_bWb};kt9T z;RpIEzZ=9S%ai7zQvt10herC@De&`_YLm^)I zBq_|1?`YnWD_;th3p0WR7mxF|iHSTS`;eLJ0DsbiKQ`7HWxQSd6=yc#{-Q} zTz%68toV|yved$ly_5=ghDD7qwcrxvXwWWssjDpC^pe?)2z&Kt)kx4?IGA<=H=WZ> zj_?FSzxi2>usZ>*EPVy7Xg-5O!+@|m-2~`hsgPS}8~ACB%;Qe=7kYUC#GcEs?shGK zQyZD*o$4i|0Ig(KtXtXEYA2>Pf<;T$e2O%5*PEahHB#S1PjD$?=2;Gj#WC*gDu+X7 zj_0DuXGZtj*?Ms(w*tA!U}T#h{wn?`el30qcJrStcJFEN0Zi>WVFi?ti-mc@OvpI} zU}y$IBJD186mnofNf8nSn-DJ;A?yE+1kc|>3HbQ$uEb67{yPkR^qu@xs1ny8gM2Bf zy3FOL^Aq{8;_du!ejt3*yP`sRJH8FlD(>YSd@DXq>@W5dJB#hbwqk3<%O;6-(IUn` z9rP#It?!X&?Gqe&@1UaM6)@;e!(ej`W}Am$yg3RJ&TYbOC}y{d)%b7IDzQ>rA}&BF z=&9m(akMzJVoLFHJh692GK@0IcEF+BShynrjO(%;Mo|0@5Y)`+zo~^XS$}Ws3cQ!p zmf`z$wF}`4?x~#vd_nD0eDiT_0mkya+EKuKTss8sS8KtAijUX!Li@98yWsD~Hq|0a zoxxC>g%6!;)A7EmHU;mFS{ItL)Z+HSu39KX`0CnL_@-m68GjF`#ia1IT986rVlCKS zK4Cl6Zg1IMg}?RNOL4Q-+i8a;Z%2o8L$;$sT>tHb`2L~o(8L+XZ6AcY^xwXzCvNb@ z_Rje5`}SNwh3y%5cWw6onz$XE;LmS&;^N=8qZ9fI+c6Tt=Iyw>5VPHY?|W^>n|N#+ zl)FOowpGC2wT*V7`?hlY@WQqwcs$!Sbj4uYhOX${+h*WBeH%KYtJzkt3IA8RZ8+X@ zw++U7n{9p2Q2RR6H9D#Cu^~Hg5b@9mY)Wt4qbT ztLmWj6*|=+F&96*&H~Jnb+P#7c%2@97t~>Gi!*m@z&HJOti@G-?pVof;`AeSEW^(u zc3>98x*h1RaB#;0yz6(Mzx>lXrsMt8j)@qw@jK8Ve%=mrh-==_AGeI((H#xFw*wv0 z-M0fB;!f>oBOd3v?u7kF-?+0k-s5*-riB$dF}mWOof&u^y%TFoxMwFix=H`mPV`j& z>`uD49;t(-Lb$gMH`9;ZF&fbAJL2)p=e3h?gZ0~SOU_U?7vKN7tsCB7-i8~Cm$#v5 zeZ#g){5@jZWN#ZFI^$+=ljbMcXiCIRW z6vS(4gjolg`MWAM{n2qurMze1`ZibA@bR_YTj2 z7~TA3Z+Wm_HHq1H43u;DKfXvff<#kgNCf|&XF6_K0ZX3NG4Ku&IX_tLqRm+FmR@6H zISw?JI%E7eS#`J?GepieTN+EL%n(!oW5#NR$*NcE%fn<8xK3+aN|j~m^Iab*k5&Yo z++p%ib8I8@9J$(f?im7;*U@pZn#u3-IJpy+JU0&lnv3aWtfa$Oc{t4rhk;?QlFCLH zht=O%wgy!vmk=E#4~_xO&JE_o*ThpO#XSmjL%$ZD0qrjr2B9?OSNt;&!;5gPSh+8_ zr%~mtk{c`x6*>!Pf(0kkSNuEtC35YI$wQv2H<<`uZ_1z_!JO2a5=g-rQzDVim{4-m zXG&}}plbf&l)=Si73J~k;@7p-cX1I*Oro94yel!9t z)yZV%c2sQk#7$Uv%MINKo;Gk#!_ z`?qg8qR6hVM00eFTm!isj0-vOGYY-m`J2HuBD`kOP4eDbq1UYDcK&!f`0i~Kq^ zF*a(0yg?E7lgQtGcE;IFNRMm8MnICaW5{4;70&SkxDSZsQ}Yt@%*Kr#B$8B_R;D@q z%H&ppnN)-CoW>0iTZiRz-EVS7ROba+n9*2`O`+ME*$VApax0F!YKv8kYdl;pPiR?y zVjPA8&xYypz{sV{3tn?0ya-TDA-I67q* zHrtmk%>Xb+*3>RkH^O42US}o!W@rn1*9RXx z;isEZEd>Y#!id;e5IYp_xYcHNuEpD`iKC7L@_?X3Lhg)rk5OjglX!P0^OD9*lp>@m ziirGp_qZ0Wn9(LYR5aD8-6i$}TelkP(vOO$&k@U0#$M)SO*T4ast@If)w1f2%lv@j zmNmiKJq&SimE4}3d_xPz3BszHAddm2$QBHCZsZL%<+B1$O0L{eEE?s%@Cp?*ZOH=-}!1U;(>k{%8wrLSzFqzYN}zQT}EdTE%| z1TAG)ogi#Oh*uSIuClZ#5Kw-86U4&&G&NJ00*oP7D&(x;q2;Tf>6C~tU%>8O%zY!s zufk%y}~K}Hm;6}B9*tFjw9Niw|@R%=H;0vh8YPK3TK^)Vb_bay;3y!iXHT z9Jh!ZSz(-SuD(rX=w2;aP9`I+yIslxM)U3*oe2gABkY=75=0Rz)Eu4pe;~Ksmr#6j z%bF0C-g4y?Wot%e=9dlL3~8NZC60pd>mUNpS|PVh!Kkwl2TKr)1S@HRtyM+B>#jA5 z|IA(?s}722&}ClI1Se#ml+~f263Fj+BbGDb)tVBa#a3<|%DnL#0wYL2yeUu0S}kpI z-U3>&q6M_938Rfxl@72F4z#My3~R8e38UO{!);y_(ZfVb+{z|QGhj-*0QRM-Rixub z{`W&Gcw~W@7jK88HRAOG+)CL!ag@Dz_9`fFr7Cl+g)Y`*YwZcjm zFckY(E2~9%Sbvu`r81QAR0;}q1X**)XV9{y6gmUyZf4Mp>trhEz^u=t7&qV z)^O(Pg(&?g+IzUU%zSrc6D!`2ads`qzd+Eefr-VC4!+_)*U<Xv5~ts%g!6uQDqa9q&J7Qm`NPhu+;z>ac{J$miuMXP}&3=O&D2H zW>dNuS%Q`3rqGsTiH>x#fve-h3gNoY7d{cK@ZnCbv!>A^$JTp_V&*qMTbJh5@9sga zCBc_;UzA}PdDCDxK}H)4yU9a(!+pf1M;?@&I>Ua4Nmz&jpgjju-JkHezJqIznamdc zPAve7nqW@=o1}~(biAX(c_}6<3r&M5fl~&WscnBgB&*3+@(#-x=6Ownn9G97qt?RT zdd*=u!m)|Uj%%8r>d%Y_oJu79h(^oaBXXL#xCu4{@LkF@KyxUOw+_o)ZX$}#Mw)49 z2s;X?Bnl3kZ$ISFtnBSDXz11GO28`*$!tT4aT)>X9s*Usrl;w%ooiM z`ow8`4*x9J_KQ$|@hf>JcMyW!<0gkpzP;BOMc%qkPBD)QFM5Rrn6cnZ{Gxc|28WWpkLL1HLnBZ46PVNEC*)M~ zhNf{?j>->kj=95ZC9^M@qv_9TCcOcN-A)U?wrMO~->T*Hy9a^wKL>2$y>h-npDsQb zmuQ~WG=>g=yX6oV$^Lug)&oNm80;O-Q3g}b&E`_TJ|AGnCbP_*`^b~=p5r7X-gB(^+qs6P_`{X0^l=<4mV<>FSZ+=; zdu1>4tfycZNV5hVMle)g{Nm~!9*m1F3@ol%UQ|+wG&7ZppMqro?r_SE8S<;Ev+{sz ze|4pq7d7mE#AIQO@&j4mI2}Xw%N`WhvOrhlzl72Uqh>u7=~oJ+1n$H-*=Ptkf(`=-2> z6u&6nefUMWm>haRUK&-=1o7JKBHouB$g#Z)X()!gAQu=)n$W5TUR}u8^KCAaZf{?b zM=qcpj^$=?VgO3^Sny{>*gI#DeZ~k&;4DPi208KsN?zy-Gw-#U3ie^YxSheNQGa7@ zi6(D%Z?C=87;4Enb{{whJjcbd7;yf5ph4WRvN3JGKB9rNxcr|GP@n6AP(Uqie%u!4a{h4q#605~Sd$yh=+%C*CyPGkml2fgc zR<7l8!qS2*4z<$6ku8n|7VpevtOD7s-gQ>BqocCa_EkIXAalHqZHt0i1hsd23M=^2 zaP*uCGv+3)4dT5$xGhU^ICTe(mdsG@v5++8m3Q=H=S>TfCN4r=9uGJ3QRo;_J*s`L zunJj3J(gBzlh>{%tww}pfC%+?Tmz2SESXDH`a9g7LS7nfZ<*Fd zH?{$+O=bizk{5wVp|}CdFIA(NrUCX;vIv<$oTkSO5rTaqCY#WxFtAH~xURNA4`(sGnf_Hl4{qYt+aTu~?mP%!=^X_zz7 zT<{oni~0kcQlCK5^WfN zZYP(9IaO{(K~6nSRitj!5h>q{L}3@ZJ0t3|(pyhE4;87)tvdd&Tibg$Bg_yKIPW~D zcV?>U{hmJoi>pte(z}ENI36Uw)KaxB|zFNB9(cxQ>Dd z-Cdc2)>d->hSQj(S$JUVdj@9t;Fb5E*-3LT30(xnTLl8F8b<>B!< z_n2vzho||s=>|PdR;GD&k@s4A?u?fAz>@*#5%WlLp`ja`oIEqgk_m>xp{!G5IsSkA z9^Q?j=3~Xxs0Tw5x+9{vxM?Y-&FNB9mMmhaVj9%&7Xq@P-d3M3|!Kjq$HuVc_#lC0dUgX6OZP7WH>kya`4tzpBr<@dK`Qj^@ zU}eH(iZ>j)%yd>ZE4)qU24R;hZCb=GQS@E7WT;Zs^9FSD|2-?m^28L7>$;l6hrthn z`OU=Hz5pJd2f$x#Vf=9N#JU2dRO_@RSfRSPxzx~;um$|gvvNDd^FU$TN!lg(cJk2k z@;Wm1d3i?k%BCvpC8&qVg_BXvX5ByJBYYGdcQRTd7k5Wn4@a4z30mru#yBI?FA#o0 z*54;k*Sm=ufLN)%Fou=R#j5lyt0VTeb;;&s=WraMWRqe?JU+wYB91z@8u>W1&K+nT z`5J048J9Og0DIan*I$m?HY-0koYRXk2QN8i#GvDBy|~qw+H848{+1^jce!iG<{j>GGH0i| z@$jcn`dF@t6SpAkYkz(!u?)A&H_tmTiw0LJ;v!kr17u@xFJljdsCt)DCcLL{nR&s1 znY4(#DtcBLvFMr7HCIxETQVe}~X zF8A?Hva`E!Lo%I@7-~#Sh97cI#Hf`C7T$+>`Gl)M3Cz>q$qQlRlIM~3zsO6-wV&nL zr2J=myzd8i)%W=UzrOLkyojv$9^YBMmluSJ>O8=ql-|FDtvGN04uRkgRPH4S6O;Cs zC!V7cZP*&4rkA@j+-i<}WsS`|*B^q2RV7lI$hkk=-Rj`8-h|drTPvF}IA1(pe6An6 zYJjqYRrwZIsk>f5&pg-nFYZA`q`M_W0k2##`&=J(i6UP_c8h%YKh;@Dc@Tc)x!!+q zmxF81nKDvlOqg|(rvsuA9uI zs_E7WJ;;XhhtbiNnU+J)l4<9_RH-0nF@6)Q43!!@z(P1mZn;_Kz*nV7!Q{H&>}JL~ zRCE8nSU71{v~eFZPd^9dCRa<8rPNk8k{>eMN+DLIS>`eqMJ?CUaNhOhj&p+%y-K~J z^UTwB<8jk8Ct+4v<;rtzm0JidB+fW%H|_|avXB&@o$P$hEh~egpqrnLH}vJn)o0ya zo!7p504ex7StbR~x;K$&2a_L!pCfE1nBAw^O$-6`amHjW>f7i2h&@Xei59d5o|uqhu0zvg+U9qPk5G#2vB z7D$-~Aa91fNQY=gzQtQn=Y|7!$fATWoa9rwLCvGvIU0GRxAa^YJW8D;e>;w>Yi%8` zlXK~gGpy*I9+Al6RADL98IR-73@o!jD7l4uP=ZTei|Swp%KiUXdk?s%uC#yro_nW( zz|iO3p^k_R5mB)>tk^-Zp$H?=R6r?q#Q}_lCW>-IMZqK{*-g=1QS)$7xzX(j!^KuYrwkLnqW2CFABghg!?3D@1q3eo3~oHZ4;}8#klHVCSji+{+vh?!l=9$~q)Wby`3wR=) zVxFIlzBo9dJF##kN%+k_(765*2p{!VCrWpWfWYU0STUr>xcIb7U{C7aCPQbA?1eKv{SsIeOIU>Bt|61#e;O%{bY>h-s+AMb7+@yAC&Gf~ zAnDI_2>JXaW+X7#m}%GI8gr$(l{Zx07;$X3orf5_>+M(?eT+MdK6{q;>|=%u8FrA9 zc%$14VKia%ld+DP~*u?tp>&2+%h(2mn`#6@9WDG#fg2xP6onfoTc zNO)g(8X~Io+zohdHbS7aTA0C4fKcn-K*cra=1!pFd5|caL}DY3{F6KnKJ^f!4C~1} zG7c_Gzrttjm;=4xK{!wnO7hpk9G3gU3npj@CE1zbE38GE-G0NPOi762>F9bAu*eFp zZC!wXBfE~lEwru=Uz(GdxmmalBa2iKIWHF!GRqj@iT z93nUAuP=Luew+`hWqwX!L7o*-Gk|I7A#a%C&-lAX9}R8LU^=%X`?H!G;^!I9E+aV7?YWn$xihTmaL>cVY_viC}%NkOKH09)Zcq&)D&S*Ab_$dIcSRA1~6cLv({_ zVyVWB*0p*X=-1)8ER46E%h6$4s<8;QEN=I2Lmub z6&uRh(q9tP%_jqbk>$!Fqx5T*y z?lVtZ)NLv;loY#JZdjR0rQs0T>EqeY7l?LX+%Y7Wr8i771ca<6^WbxMmRrEb*t`$h zjE6H(NsxmJ@u5l64FLhk4~-4umOccD0FwEJu*rmW*1l$%;a*{+Cpm+oY&}OtgA;uo zISLzvA^cU)v*)$pye||2J41azNZ_)Gc8y97=1-RNp3Y4B zfS!Q!dJaFw-XGGX9+joc7f19s%d{}ETMAq{SvuM>Uz}y!Y>#00RoOhbC+8EyA@sK7 z=Mj#T(iL|=HpaHb)pcr10*Ml{R2=3DxJ>)tZoTzcD)#Dao_!EV(P&BGD>0!K`s@-> z5r8{zhlbYM2jYnCF|3Rw;;^oUoopquqshR{!s!nm9W&{KE&i{N9nNAqC)&8&K8lgP zDqp6^Sw;HMI+d_OHS&k7vBOdZ&*R*Glo+SMrb?g%|Q zkfB4%-NOlc`A_*7q>#G@={irs~|Mp9w#HTTPI|M4qc^kNlKSVs(rK!t!z%Y6M&AH<~#)y z%(F!%XN@X=6m>4b41^(tR1SXu1bHgF^*n9H$9-|+1q6-Sbs0kYNJMRU54X{kR&xTa zO6HFWV#Nsh-u^IXw3qWXd+0KLFwxiy714C_T;61VdI20L277{U*KrcZNqi+jp4fy^ z{%0N^uH-HZ3L#__Ts5s0R8MynW!6kwG9PsGjtuNvByA~(Ov~(VW!pLiO&e1LUnbc5 zp4I6v1Ev6*u0RBM+w^w<-}qIb@!C^_k=?9#)ryR}?!tmsEApcNjaTH_3Y3qxkbf6e zI=~cfeMHP1N#8SRRG)qZYY$%~=t#o?LF1)^$q{Kp0+UnZ-`uNkqwt9IwguTCq?;(2 zlx~^w#YCm8?0j*8ajJbfOa)vv1?Tfc)yd_jd@&2eD@4peF5PNUx)`T-PBx8yRq!Vq zO)U`bp_4X=57DM{v2}oB?jg*}Hqp=-8@_tNIAVi8R)7Volux=9Qp z&Y(QVbXrDI_{X_UegeyJ8su&3XNRy3Sr{ZI@pbCh3Une zuFib4Q(R?SW1kO7)1;a%d{*r0OGJrSN5glD`|0Fe;#2xvb_mX3TXmIbFrKjXGtgH` z#5D^XC`xB2x{j571Qti>+$6AgHunlfEKyW|PP#?2jO&cS2m=E2;)v-|ZFCjT`Ogxe~Po+y3$G;#6f>{<>W}q2FRp zW~+|AU*-$6?GeAGOG?GRz4PMv_VOSfBlgZ{o>RP-ba!SZL39ojtPX;zL9StBv+E>TfI+0*V4TM(OUpXg1T zK|>J`)W~P|=;sfcO8a4_p~i>`)B%tn+5?It}aXIWnMfhsbpfsB&E&&c+RCb|`>*Hom{A z7xoS5_AD8&%Z$d*x!;-mdySk+w}UQ6o!vmID_q2wGV&DrdKs__ibm2eD@0G_x>o?# z+cRXqF2kAIjiv-3+a7K#F8wLUS6<|^V3S)eJ5<@IG2XfNO z8C1C(WY8Ta#h{)D$+B;j0Tro<4EWYbv1i6GU4|WZdC%d{gT02MTW`;o0lT0$hW>Q0 z*NV|v?Rhd_H%ubhmZ@9H9Os0{H0D{@a=s76Z4kMHE%ga!1L0}4GbyLbr&qR3dcUbV zPXW>e1Au^YP^21?M4@kBdw9A#^95*mL+c1W)QtxUKJI{QptJ%RMPOHX83&C_SZkzJ>fRhwdm+&a8x#&h!&KPLy_P4p+RjuH7FCJDJzv$5dEU$5aWX`b3)tO{osWRqCw` z^JTwOLX6O*e%VNAX*ELo0>X#I2*U?RW*=w$MU^JJLJwC75stc!`@#*Zw2XMt+f_pU zA@_hW1);P6MDlI~R(t@XdJ_+V5pCuk1W1hwuqdaM?BaRpoVsM4?QmpeE98K&E?3zL z@4<`P|9+LyR{>L6A^q#(ehQJMiEiuzFuxUoKcuNwnl8FmR4qA}FTnuYBRgV^dydhT5>X&avKiK4id*7l!j8jfN1u(tU z8~elsD7%zDe4p!_Rsff`8o?j9%njuA;&#p@Aa|@6BBZu@K{TeU7kG*vV-A())YI8n zA#6HZJsF_dM|CeNq8dky9Jw^jQ={>BL-q!K5DQ=|lpvHbrkOj&LK#U$Yb&IpQ9&k! zCq!(D;dII+(Jw+idz^A^rwNSDidKk5V@zr`UitL4T@qDO4!K#REKF{NOc=(vO11H6 zFj{%_k{B7*rCJ=z?l%8c9D(CqMqv{l7S-Skl@E)fjI&!Ist*eCRG2HrP5W>!YD}}Z zl^xbW&ZXtdK-~Wk(W2TOF!T|Q&ufJoS~AhAgAIOkSdxc<4z!DJ(&mT6sz7=D!aP9O z!hgkEAy8TejpDfa_oB0#_j1dF&LhAIrpqAQF))wV|Al#$d!v*wDZ24B8;MI7aA zGqet63(%yrl+&t0*dJ&W=Q_f8=@GAxyg?F$T!f5B!KO@QTXCi_vlU{>i7vxASs^w4 zDRGQ*j?~3wb8m%+vdam2@F{Vw($`y0i3p&fZH1sQGC)0yYc7jZ6o?y_#W-&p*NXEa z#Fa6~__&M1oeLb=`#mZ4BYGei0?zTYc_xBg@t4Kjax6ACgb#%Q&uPTgd=rr|<{%?M z7GKXhRwpL4jT;;0G%Ku+xB1him&FL@P7vW zpM&2o;s07Z4}r?+CSX3t^M7$R(_g_a3<)yH1UBxTeV+tI(|I2U2JvG?Q}WNi0UFzo zssw5~r5#6i+zJb@Pdcr=M%-=vt7c*1EkT2*_i}fMHlIQUf^3b>hyLZb_Qi&Mp_(Xn z?p_X|T^~e1i3j*(=%@cglDS{Fdy#w{x?hfa3-^xGREs9XN`dtDn_^_wwB!PS?&<@` z-MFkZf!$iFp_i;lN`HyP7JaijDT&oCENh+9Cv+gK8K?K?k7??vnqY4%ZJjN@p`3HB z`u9)N8~c6(=s=HpzwyyqqMvfbuwk?MlUirW(25nKQh)#6fHV38ln1J%m){l*ef4HZ zD>O|=Fx+i<{_;|Hx*a_s%Ua`c)bs{)r^~P&727=4Z3azm-4c`O&RgP&hG%^=c1=2# zY+`YM&%p#?8q(NoM11Q}$Pf53`5$Dg8Nn}wBJwcI6`tYm2)@Dy!RA{P$OuQr z{9(~;|1M;(w=L!(^n+0*hkg)G2f3U2)6{LD_ZYC+a3n^AQCk`ut6tixjiB^zI!|gW z30-49wOcFk<2*?*`0N6X*OM@E9)XVwaH1^1+B*jmXc(C(krteU1%XZd3JmI>^wt{? z=I?tCu^)bWTXdtpy(8+3%Uc(sf8Ews2%YyP%mT4u6dM{RRyb{P>jD|N%iM?12j1w; z^Xp5ALC1<-}wkRi?Q~w6?VecZE~30ag}=4r=uFls%e@ z1U^`wa3k#6&7L2?Y#6Eq`bCkaB=&>Vz3?EsetzQ5@(U4L@C*zdzv7Nl@0Yv>8JD!K z={@B1x4U03s0_GS-6xXLpN3bBXZ>2;C;a7AxG?4h1V9tN~r22>X$t8w#}-N(ZExug|RW>^{dX^w?D-gfHd|eUNxI*Q|ey5V#Xk7jXYg!?L8RR?=!3(>f ztG?^Sw)4wcx65~hQnzxc7--e^IN0ud*K3Hl86l17;~sUs@&~H}*CS*zeOz|(Yduc~ zKtsmaC-ht2_c}{(HA2t{Xmy>i3{JS(on7i<#o!f?Fn|0C2L6YK2`~UDDBkUjw2%HN zn)}!qcmu-FKHnJoN#AcQZG}`6Z>S4N9n$?@iNPux!!|N#1Lnaxg0oTmZqHSv+y!vO zH7qlb@FIc=f1Mj3MDu|{3_q`AeRiH_u+UGCU{tp$cZW5kni=ciyEV@WBXyy|A3-1H zTXT!xg*H7i2La)VbA0~R*TZKVm8>f$$P53FnF-Ff!h$ceI49ix-fquG0emK6CR=fW zw(*(Jr(7Yq+zZGGXM)ZG13d9tDnLepVfcz9F#%Ycd?ZOiX4?)muF zUhWn0IcPw3F=Qhw{Lo#^HB{MsJTHD6p3RixIc=G)KKN(}^XlfPIjG|?oPX+wZ?qCu225jw5| zE>ir*{37xow2jQFrjuL6_PNt+ix_EqiY}HcqD`*_tkV_MV9^bs`$}QTRac^0Lw_sQ zZKtb?boXg&el>%stpE-(Zx`zJ2|~>vT6Y8ST0_ZgOu4 zwy7+R@hUJndT)pnfUOA$ zjwwu?3R%A{nOzR?%KRs`K_-J(B?{K$w3}DW*h<||P52mYVUOwem!~VO4Kg55lWGlS zN%a|Ywt}^hn_&%KlAE8+p3Dt*!PC1%X@a+HQro015B+E*o+`KDHBs7ZOl+Hg*>w#_ zUeC`Xhi*WReipXDNGyncI~WcFiBG#5=yFL~dg)$IUNh`fT#>NxDB;53^e~No8PU%D z$&(}p@dY?;X`4f6pbSHf+0z;-saiV)V{6+WCWsCTPyl6$@z)T^jb?^Q0~NHPMs_%{ zmnOo6U0LeZNJMB_)n5{g$!%at)gM5nUWb=IesOua%2jZ-}*6=d(RNRn}N8)QFS7R9aU zT0g3@Nc|OGP-nZ2{WqhqU|T-f*aqnjoGz6v`23DQF708Gnz!Ix_(mC5v_aw%X;Goz z*c3o>!dwTsGNOz&ChTz?bQjoe)`dv}m5#FA?2I>nB%N{mPS|*ifzomm{5afjXeT1x zKoU$senI-LD*@qLP=q5MkIlUtHoc?#>Mf7>(V8oyi2nLGDKQiyZUCN2^j0lWHk+^O zyy&BkW23iShKI#(outz+r#uY4c7TY#ro)-rNghQUpI!1<4e#jtgmFj^mX5UTwPXNy z1$5ZGDQ%E>&$v2giP}zZ5aB`;wh*E!?=SpfIzLjeRDJ(ws^+hqpt&D4=a!8#p%g z2Y4f}lhq@tS4apUyA8}*M2O3tcqk~M*NehTN}KYHNz|-6x~w+vYj{B+Pmrc(#vj8% zw9y?lnm!aR1^&?sxor?}1ejDO_Xi`8;jMOvq{h4>hXaC)xowbWbca$c#$L@W7_I3Btz!l~JX@Sq-R=Mh>v5iQAYCjR`$FzA$omwCRqJi$MDOXV*INL6EZTK=IwuokdIkVZs_T+04A2gDg>i8L>Xx*vL(>+OrImFP zX~SK|zf$9}Hki0U1*cf0;KB@`j}GtM^!m1R>=svopBclXXi=_YGY4!ft*+aPrF>+!<*!D_ggo-gPa3qF$j zkm@@joU*Y{e24`w=u;fg$=RYH-BzseG+a}P;0RajdCokMB zBl}v98!;ZG0{HpAgB%J^j+90?Re;KbIs!Z_Y1<%EbxO4|0U0r>_kLK@1~bNJSF|9R z-`p~)*A64A+j4Md1*ul!vL(&)qa;;CAma)+OKQu;f#M1;AX^Bu4wJg+c>s*foy91A zmv=2YE_BhzJE}~(qe?ciMc5^hLpniYM@Z9f(B`w9<9y~vWpkrhBcw5Xq9da%k0CEe z3BM&ndjokXj;6XJk8zQDZYnIQV0pBj+#r*_cqNN9GE)JQ)ql=ji-h0-~psC_)OR3ND7mA8X^=*}&O zZ8KtyUPI6CkPI}uP_iUBx{$!Z1o|6(2lSbYwAoVO&TUeQ07xGQBY_WGgM7 z5OVU;OW^Ov^NrZzQJhfCMIqbe8_0E8&aH3GQ=T%4oYQNJ8n`KtSGAu z37Z1weS4&CQ9#fqV*h-<6v*q*N6=Oglw^bkQ(=!Z1ZgYUaVJIusH*6zWuVgVlWOR0 zUB%Dz)~Y6HTiQWV1ySobFmGS&ky2tA#&p~ePFTlZsFh1F7n z{ly9?h$J|Ayp{F%S$+huL1VHN|J}z;!D5@>XlQ#^G&@!qJUQg`B}K^ShVbJ3%}6!T zv=!k}3y(xo4X&&ocOrjt@n2UEAK_B}X= zT*2Yw)MlGcO5I~1V5cl?-;ElBJe3+{^Q4zgcE1LKtA*wEn(bDSX6 zl3BhU*S1Jw`?^fIwH-!AvZ&Pi#WT`GCkv@yEipH1xoNXmV06c)HbkKQvl`RzuT;elbuVB!{UUzw9D{ia&+}QeGMOa zkuHETf%zlwq`0dqctX{yI-m&gg~*1hS?I!O%gX^Es;+5x?g#iDXW7cxOkytX`8 zmF3CZ#lWoU3dRM4vv2+K;OYIl6OTp3CHW+)BTzn`mAxsex1P918mmN?QabB6-lnkd zHLsJcgoiwL3g&D8Pvd{^iZrh3fcPFLSFRAmS3~@=OHyRlO97pe&F4vG$4CrYQlY2X zrLivOKz*p$n{4R-DH7tRg0$GB(Jqizg(2P~tpfu7Ft$q_W4!#3G(qXM6AxX2NS1U! zG#=z?(>596u(c0K5ejc)dq|2luI(6(Bgo|yBnvO2A6A!~vtAGi9b-U5O7#6t;Vh7U zQCdZRdrW#e%t5)F;DlYs>6L***&~1`k+a!SAKeHc8*Oq=C+{&GIJ#FiK6dKFiZB&E=mE!pK-NOm`9QZ z_rX#K_nHV#eKlV5X`06C9zS2CT~D^=XIqP{;R~(#CC2I7?EzY^Z+JM9bIx&I!I4+NLk(tw;II55+eCIB%3Rv-X2~X47OEe>ul@F zGHFmb`Iu(zA@2(*Wf?TK5SaiL-99GCZFann>%Pkgm9e z&$1R4;%L{?uTn#E0_3HD91cjhd^c|-l=uqk2(?s)t@D8KKR9bgD-9ADYvwoX-IKAV zzZV+tib-GWyX z;sK(HI9Y0-9s^z9+jtPf3!s$^3}}ZyB;>yeMCkjH=1hX8a2L25gtA`EH)0w7K+bY+ zfs{TCX-g=-BD)St4MrAn)h-s$1kDj+0r6S*Fr=Xf1V`g5J^YM&>el05mH-PwFwV;j zFY8q`%@%X0NIPHFOZ3ny`oGc1ujrS!CD$=l-Vzc?Th@D-soN|1(f06L`iWo#Ic_IS zds)9V)v??VTfR#0fd_jc`3{+6S^T(E1SOhjx(nzZ;tbgAm{vj-c0J!Qe`HBV1P)a{ zhxCp;aC|&D`^M|iF=8KfP4eO!evmX&lcVu=Cuhk5m=~SqX424buYqnW6fbOgW|5zn zW~Pf{b<5-!2DBv(7RCrh;B9{?M>ASjXn^T3yb^~a2L3$q5*f+0550ouCAcZ^YPwuL1fE#o0fpEGo8lvlcQ#A&f zeM#6u?|n>Yp%*R+KTzKb!aH=!d7)YMQIXTK9Ti4$ukp`wOA*^&2f6HIYWdQCf|2Wh zj770@#*F(!LxumZm!#1K=QT-aEN>1COt5AmL>0;Czyg6wn{x23yCuzJp-J#zlmz?4 zZ_O>TZ+=y(gDcKUQWpK|E$M}oZ14tdE+L3JUqrbAA&@(`*gx}OKpJlbu^ZtT!X_Ub+AS>$%4@tF!zxWTyVjR+ec#P0yE40~1|B%#(2a&Hx%i)pGu?cVGW&ZlEv_rq4qW~BQpw@a^`wzb-Ev3J{A{EQhBsXT8asq0uH~9kc zE!joPn4sxc`O5ls&5OLgZNd9@hjW$?M~L2>4se-aE&?*^18Iztq_Cg*K!VP0SI0Iq zjo7o)dR_3Rx89blpeALpNbH~Bt#BpAY@i$8mgc&x?kHg_mFIZ+whk9{@;j1-T$<#i z(FC|*Gm@c*`!<2*QgfFCL=+n2cxEJ1*w$rHh zrH=7zg}ZY@IbkCID!&B+ravJe*T=AU87iE1E&=DCrJW$5VY(q7%2+Y7{L}PPcdiz& zhIO5cgf^)c1H3(v6#ZL>01JL{v5ijtouqeygNf=3`h}mmvaRwqC25^tV}|sGcB9ri zD({Ld?SM}21TWKP-7jXFwe;#8SLc;ites#PqkA`CpwhQ0r>{1!t`jU{A4BaD6W`I3 zb)De$`T#W0SHJBGCpe$`?04LE(hz5)Fr^dp@Q+eP6q`px9Yt^fLWD@Jns4Q;Trl~B zAmeymr-KtyjI=J;Vf<|UT~ai7wB~my*jU&JUJ71biY!^SZu#v8X`Iu##d%J0GcpS^ ziw1=+-3;3aQqT#OW|Yg`?1lf4W+@D;W8ILY#kqMUn{a|GwXQ2DE~1IQN#D>1f0tI! zf*(Nb&i@~&m`435W$PJDJDNK}^$WbFYp+2je1s+}@QR>Y7I;}E2g3erVM$5xAXZOC zVQv)YuGsW9BrqhB$!KB80yYq{rI)sh$7wOq~p8O)vHs5fFSign03ibSTxNLeNI>c-lBR0~J2&%v-EAt_?kgf-k&&rO% zb?i`r#tHYM&OF@<)qRY3+Rp5m$IhD*m_3|a7mE1JrJYfbawxz19lKywg1H>~mwBMu z_Rc}@Awz0g`n%LmqFZ@$M}J`q=cm5nAWX742ea+%Cpj*J2HvcysbhF^Bn>6zO^iHB zrM1Mo%DAC(2#)_Qj+HEt(?i4@73R156L}JzwbF-}(IhjTF-&c4M76p{! zieOER&n)3T!VkjN|C>mlBpnHVRw5_N0%3Mvu|N_0h3`n*w?NhsQ?Y zhtOk4#-Ja5jQP{fITns`!ck_O7*UVqp&NgAIDUPlj;*Q@^}A6HuSbAQF1jAg=uPz* z_&%(D4a%tcWhjT#FGM-Geiq6l^^;K!s*gh%S&vo>zV*z&v9y0Z0xNNrdU(F;JL)~~ zJ*=KhRp^mYlp#lUpbR>KGlerB$pg%hBRTjk9a)F(r;f130*_!!od1y}c+z%+O|ajQ zxhQ>)%tYyP1jFOJj*Lg?c?5&xJdR)(T)!hjF{JxTj|{*+79YX*1fL^je0Mt%fbaYf zoNxNgN6-~r&EdT$4<6o$CzB6j#JV+y^8qvAFzd>~!{~}I3uZVa-#Ak*i))eHb_(Zyd(T zC(qRF!D~%*z=8Hg9dJO7)}di;`cZU(i$99*`qz%KPE0+Tj&jOTG|x>wistp=(fRm3 z=_n>kzx61PZ}2JQL{-*T@1QDqz+MKv?uC7CGuen{jkEAkQ2shO-w5IfQZOMjm3T^!r0VqwvI`WdO}Rv@(hm+{7WF}gMg!*BA)rwRITVSi3lFi0TW|<#NVoh@KgZ34>#Rb0+gxdxE$5DHaIy8E_&g zjMN>&zX>1VTwaTefs~nHPdDav!hQ`LgTlGL|0&dTK>_Bd9$1`SP*7Cd1&x@eET)p0 zDi4h&u0V8x%Ry#Y_wGbI7mpD6IpK)~n{ql6811D7l1*9x|2+on%;wVTg-kju$XwuN z?VKY|@p#&D0}8!a{^q~h*9Mpe68XlD1H-M~vC~>%!JEBzH$0J{RETanQ{7A`-x3n+0Y0)0>lJ!kScvh_LHITqTPy68aZ%Ld}KvC z7>uY8l`E2!O@n+xyZgdpaW8L&5kg3Wx}2{1gepE)%BaZ7c96yB(plzjJ&>NrBI?T}YkOsd=v za$b>6uO2}6BIEX{qvMV@< z=K6(33fM@r)-TlLg>Ec?bU4JpfgDRR`cpr@P{7InvZK6pq{Giwl_xx5I-JI6oX~N@NDZ_&Cwc z%_=I%w-Q=l2-!)$i8Vbb$IjGniI4@7*CF;`A>b>BKWt!R?s;&cz?&Ok;ofi!@YI@?3pPcPUI`g~*@4LKAVLKEZl?ryf7cWnu` z&1qjilScJ3(dN%W4fL(?ArH{_@gds`+uG;Jv?jF{OX2pa?b3JTQiYdJ<2RqVBMj%S zktnX6Pb0r`^O4VFbJ$4ZrcN0DMF;pP+D$n}_#4B_!$vr#+By0;g}HeypY)Pr%7B}@bFJg&b@R64k z3I~!43yO-?6>OvT#+cX8<_L2-ofu)xbj$99$wxFo3DdC0kl-kwKcZpou$XsJi^aS$ z*b~$4jtIT*LtVoE8!GChNNU4;QJWk-IAh_5YK3siwF+zyHIvM_?6XnXKzjZw(MX?oL+lo7n~fm3HKP}F!`Gq_G)_-#8yvLP$*{`WmupV^ z8d*`&-|SuU@>Wdp}f6_StoY|KwI!I(8kX@(SxeNaJq( zXD@gX0orePEwa?z7x;KYSnp3V>Irt3P!Ic5Q_!Zz#yQ1{xV~|g$*Vl^P>)3L1&@JL z3UVdImZ6&NHmU3#ON#9!9OcrPn9E_zOl_}1(^XoF&^Eu+!tzyF%8-&IWEK|SLf-Tk z=r$GJ*|z$EBAasN+g7BY-MiUGCi=X`pqGQdR57VmM$|_p`uxX0$zfQEI7%6o*gJ!G z{$r#62()Jgakf=9IYhRsvkp8kl*-p38x9hE>--@RZYG7oblBF9f|BS#ZZ3J1U3M|X z)K0eQOsb{3tP}pnc(baycAh+jtWNCOXqRn*Y>2aMyjd~wal$!_e6*>Z*t)o-6~xG) z-V&nC3MHdJ>#d!zkL{wy`*FBgjjsR8rKJ%W5a3 ze67&T6%fYtX}$Ymt6fYr$WT{i>)z=(_Q5f%n9qkT^*Ur&T#kgS^Y}hF?t!I!G20{^ z);GyyQQz#enw>*t#rtH$|GPk;IXu1)%&Yc;S|d1a;mcaELj2NNw&_x9wxgU{vl(T- z8ZcbKof^h)b=H94(mqiGPDpF30VkwgUV}g^yl+iBe!W(M04*e-1{|HPvW9U&IW^$x zgvm9GAG%f(j_>9ga7Eg-ngDzsP{UZTi#2ZGxcNmj0voTg7QQh=vFqgumYII2OuAYlBx|+!Y9<0XIBLr46 z2CbqRY_`r^9S!*VtHI~$|5}anlB=x-PpBsy%ljp0lP#&#HN10cZg0iIw9U|{mEkq3~suJ*|s%i$xeO2Ig z`KeW7@qAkq#1}$J6>y{Vsbt+8L%WBbG?%i6}-Q-%Z zv)t>oYw>PTE!c8xb}e{kt)aGbK3;yi7D&?#teu8Of35}6gnhLm@%&uvFuZoT7G2@5 z)`sKzg<8hj-dl@V)J?2n&%dj}b3UUA&-po3et7FrRX>!qRXV_gRDz|~+^pP*IzO*0 z2F$-I(M2+?64T0Utz3_v`Nt~LP(Dz(3P2Ys(JwCL|C$NMz`PG(ooPO*-Q$S{n8z8c z2U>__7WYqXzi>&2hx~sfo^o79y9MklG&eW_Wz`UiV*JKhDN;Sv&7qQUZ9A-XLc&y) zntaf?EtPu3YFpC|%aSlZ)eh*?5^4NEnL1K+Z>m|erBQ0vQtZ!40!gBQzRS%#X zbGkL{l6=f6r#~}@Ygp3Lx|`^hwL?A~;mUa~`w>2xBn|9p7l<*FUG3p)&<=}`w9}wJ z$EQhuqg6{`~$TGfpS^4~My6hEK_0Px^$`+{ArAg4kj#f@kiGgiKaG6AZ6o`+5E299!YHz$V*t~{s*EQ*zz@`jpwg-_;#hGr0B?(h?rg(^Qt! z0jF8k0TlN%Iehs(Rc)hIXYB}MN(FVrSnpGP>{XZ*9ifaRR$-t}4WRu|nL@@oA({Ma zv1_38eILNFaWX-XjE|Ka1DPsWodQ`k%P^*R#W-tndcx!CuP5IM!^l4VD)Hu*a&y_m zkKA-KIz5oi-Q^{;?K^3*vSTiOClwp>I$>TRIjtIi$@{)nb&d3`?_pG)-)X>@B-3Q) z#)A}Rred<;>;$N<%>1H~>=Ljm8*}ra4+9Gt!>JJwEVGgH{coR1kv+`SW)x;_&5X_{ z$Sf%&8#|e0NF=>*&nIAwBeR(sS1mufjX3IQjYskU`ABHLU1IcC)OE3>vMHN(S2*4S}o+E)XGxZw*-WJYD$+_8?wv`u$AcJmD zgj@kpYd{6IQH~n8IR$iijOkCbbdbqL&kZ!aL4S)hJxCKHO^+Nor3rM0;fiok$QFVS z1iB19F%OXO+;t|;j5lt249rnPn7W$I{nZrbDF?V!+=J+?`Fw~s+4LAVr0#&Kd!YgW z)~Gwg7>^Z0*tT@+Ke;CRjHYoi59qh)e{ir^7D@Lo~6mv7_p*CTyhFE(p<{%(BzThGQyPR>HUE=y@Sh6FY8X zEWH(?pC9D!vOls}4&bU76y`WZ0RP(sVU}iO+{kg%YnNLLeR#WDKU(@1!Oxg?z$_b> z$f6Qf@n3`mnvr8ijj(_77r~ccL%?Rm!og5%8Iqk0gF8U?&&EsOBV(fjRB}22obVM1 zp)4JkbwDGF3{C1Up0Kr82gAMr#-IptZQ=G(AQ;GX&q(s4sBy zD;KciLJjUN8+Vq*XoD5~FY6>~raQg~J{UyuAci@>alat0OAu-04hR(Y&KiVj$fCj5 zyao?m>5wk3s)Wo@3UHXO$rE^!YX&ZqoRl1G`Bd*`nwgmyzS6oWukd0CldG8&(VZ-3 z4_;+b#Y~G=nasxgi(9be0#wt$*hQvs^tXj3Pv!h$0ffDT!Q6b*>_mgB3qJ>@;{%L}=e3do3gg$V? z%Sc~+-AAO4v*H{I(oCCgc$vr<`qB-r82aK3FOi(0)*D{_?7lfza{46Lo?4>VX_ll&quH))>90l1)x3E8O1-$O%54%(Kh2;gs zus7mgp!4y9|Bc?iJV(EL4pn{e9IASq6;GoOuXO=TE-5U`EDrh)8zW8nTJR&=Y3g$r z$(rZ9L^=}%DW<t$j^ApI5Jz=pH$mPkr}B7V7H)^1R?JUe!~+Nf+rpEv^bhtJ_rn_H?E1^)OJlADvZ{~ z(-xyqqEC!+*U(SSdIxBtwDCxjcG(#0u>|*QKBR*lr5>g9%xae^a$f9pu6JwB=_ZuixDmmeZ5W-c0kr&8m{yLcjJxeeg z#{cdz!J!v^l0xVY@#ewIOavQLCRE6lPH0}nMmUYXxOJVl6|rs9&B&7I7ELq{?`|uC zBa9`|R@02oN5`4tnBhAf%b$fMMZj$VS>DO?HLh$V=f{~xJ5#py1YOq&ZH&d`mg4ZB zo?%u@bmacxB_XF1Cu0}?mBVHJW_qnRpl($sv@x(5QwAfu2;7`#9_r*N)EW~zp)m@9 zW5YNYCkivnpxG^nP0sfueN?s$Qxe6E{EJq#tgqN_v zuL+L}t-@b~hlF$gA2OFW`G4>)zya<_K4DICP10V16? z-yB7!y=!v!g+#Ns+cNN@a>R}~)6El=h#m5RArATY(u^I&IhhQ5(EmpUSR7<9O-wM) zlcjGyZH6$~mSFA&xdk$zI*qh!+D`fMaf0JWPB5#HkJVR<*3Nv)ZeMm?FiO+Yrg*dJ zg`uqBw9Y&%+P+?4%bg|VWGhpFwi!D&W1;z3#?tqunI|J!CekY$nPz^&Y3c$g5~tlR z{4D$^d@Fn@eDZ(ho+t@^f~TMt2-0Bv4=$F^;N1HT(oNsuZ}3lp7%6Q-ZuN)x`}r3B zB!7%Q1bg;!+&SA|?Y9vj;L`Y2i0QhJpTo!V6ZtsYLPJOfAHj$4Cf>dRiOeUn$kb9Y zo{T~`p+Uq#f=B={h658R`ypQuZtjPuNBfukFjNrc?6=^1(*7Xa@_Y6}zM{Ro9|9kZ zb-xEnx*uX6&BpzpmV})ZSdyA=Dj-wQlvF@erb($NfUIg_`8a$ZTmeiAGb>=Zz^|-W z!4~h3ibPcUOT|2tUsudT`D(=!H1J6UUJ#~MKqy7FRzN643>5>=xsNL#b<)nPz)hfy zufScP`J}=Z-@mQ!f=K5`1uhj`N`)Rz-l%{~MSH7!FJKJiOi0#R4j~UYUk)J;_e6OX zAWM&yr{Pa|IfQrGSId{9$p_0Jwj-aEFF+rI%IDyFLwP(*ITn>qL`5^pM+4@aa!|2) zYdN~5f1#XVXj3^lrzN8;B>bl!c*ux{P5fxr|}!zA_^^{acwEzW<}F6mzEe zi;c}$y=@nO*4nn=`)f9c=M3&PAWHM44c*dQu&u|hKihyU?L1own%QhahsY5drcXy~ z^YQ$S4cOwh+oqv;lWjbntgwy3ld-npcrwa17*Dh|Cf*!s!!e~<7K(I-8#CNhMfNBW=Eq4*RC(ti#7=>G?^rvDC; zrhgB;(0_p`)Bi95z;5V*{uiue{T)n{p?^5OeF=Q%|KpGKr+=8CW4}R*#<#%G~ zY4QexHubD0DavV2l3_G+P$(023%zCRJ=tV=4FI$u;=LGbiv!7u1M7%sqDkQ>Q=H2psCobSlc%DNYCds|{H1u%OEU z=*u0n51WbnpD%qF?rh;xCvrxEkX zoo&Rr(w7cyWEC|xPC z=|m&89@luBjf@^=>nP&*7L*?x&qn#gaqKhl*l}!suKqZ~#Np%EVO-tu+4yzpaSV)H zC_Rp~OddIog~S~?J`Cl-Su$ZKr69E1|5dV#-$SHd>0EYzU#Ou_B5+ z%oS1}lv`*&l$$Ab30Kgt7iE6KHk6whHly6wfK6hEILYJt-%jkr_hl!rfw-qnY(V+s z32bNX>IpWjS57QL*?D3S%8nBlH`jgwF`CWUV<%!zzIAyTGQ9zNOfNOCdQuw(pj^|y zNQTu7IK&O+26ud4bqp;U0*~Q5;%=ODXGG45V{A<>KZeD^Ejz{*;L@H(ng)MnqzO|^ zYwBV!PMvPnQS;uAv$SeYNFDuccSwy}z=2`1oF18mCTsj@+3t|tbk$SB z{q(O-3irtlYJ;ER4q8~mZ*qliX4{+pTbn$?201|u}JHQafOuwfZ zw?2-52oWv`{D$kns>1Z1>%mdpHtXYi5d_ect2TB{kSf^CpA&S%+cx3xJrMl{s6xLz zGlOCkF~cJ>gSOGPo(tYbPu&P!uiJVBI+iH<(lfk2oqQuWErG4ZK!iYnnBab4uaG1R z2PO9gvMlTbQ8p9_PhY`m*#%;1AonwO9WkkjxCDp`68Q13UG_!>x;x|@oZRPW>_&r` zJ{0ZYqZy)&i=?((L!h^lc~4{}@oo#<7Sg0gJk50ca1TGt2yGmk=mA8NqCHHGx4((; z@Ns-Qif^o*A=KL)O5-ar9(o!S;}HkeF)mhp<}VD>#!;iY+2nwTiuUlJds!2kVm!Pw z{k3r>dMnppqEB3fHKW}2nGFU%0hQ1#!_X@JWuQAY7(5)^0c@CW{(2^>-JDZWUI|REogzs@m z2xYIG@f-B2U&i4Fp-=Mfy^@J4at{u#GshB%F(|P}^7i{OI0XeIu>fpf8mL{{|+wsv~pZB>W&U zTi(aLN4=|!ON_;rJ+XK>Rm-DKHBV7GFe}wOz?gm619p1ObW{*|$^k8^Q_bVLnj)c> zZmTZqahOP|jijt}Nlh~k?Rqo-kl1gg!c;-nb=g2$c49cu*F*ZzQ)^&ARhMSoVka7- zpz+XhkHJ2g|DA6l`>6Mqe&>vHuFMGskFLfgo?jlM_;pcRc~Gf$nRI0~4BbLhh|y&( zhz(^yx9FLDLF?!#ThKvDY(YB^R1sF{95Ty3Dy$LQ_={ki+!2U39Z@>(<)X1ycRYgA zE;iD0Y04wX^vfyiQk|mDqa&v17rQMx6wT~fkQ&B1Q6EXiP0*WY$P|bz@0zS%LSrZE zm(jN;=~vK)C+e5dm8{UR;^G8-Qo|%YHX>_yJY3Sxa37+_#Uv0hVONt|S?-bH0s5WS7^oyA%AOlz(W&gVEW4gf;)tcKI9lGX~2Ud zd%t&scM;8w&YfX2@iZSmn|Db@`qJCMf2Vi7huq)S63jo!Ozc(!jKY*G?n%5d(iH^k z9|$Ty&TbYq2>OMV%*FfrmVB)SdgD@iFo7bQm+q@KITr+4;GP-#h%2Car zVaS^1Xq2(dpkBy`W)Ku)c(WhM=w{p(WLPuEP7>9O%E-_&JJAdodjRcP&Hbkd^>hDj0e=1DhBT_EQrEP|E$-1axsfG%@=1`zAEQeb)pkmLxTS z3gfMUz_A;`{s-jKeUvh0X5V7B&$HEi+KgX&H}lc1sM( zSuG$(_4l@*X2XgWM%hhoVG}W>MTfF}}}L;3zG;E%g~3adw7eu@q0 zy;BTxi&`)d+&iZ*Bz>%dr7CstRE7aEPxaDC%sp5t#&g^}xfGy7Phw>HK_@XX?jI*v zGcTM3>NLYnvS!{q$(pg8lw)BU5N}34C7NK|b{$vURXkYBjdKf!3dCWW=hFO{pf;Vj zER3wW9H0oxYy8sXslG zY)*1!0-we4cY!)u!@b7MqTc&Lk&(^oi5W~Pt9om!`Z!1p7Eu3j&~)$r$Ju*;H*suz z<6BhRWJ#7SS-ZAmV~h<3jE(8l^p5ErEZi^{chkYhB(#JU0uvx~Y^se-6C|-DNGA=F zkWNd#_XYw`foV+bdgxjk-AzOBDZ-1D6TjdshxFyO$Wy)=_%-~$*?FaUw z)cE{faY-al+-%|8 zD*GA))RS|XBO&Hm^dQZuj-L6D2@)aKK>uyY=D3v%2@)^Ld=om zA9;#ymR6$wPj80fZM-#Bc4_U0Fx5}z2`K@uet$(azd4*Z^zhTZ*HZ{3?ec`7{`~-= zGd~VpX)L>(`H0zW%#AZR<1cHdNFa;xAGL|;7MK%#Qp{9?(|%bMM=>K{=F&PQW?-O3 zK}^gDgVT1IqcbmCp3jeMv7LyGnW!IjnT1=tB_Ys+#ug*H#SgW`R2iJnUZ8TSl857~ z$QU`PU}99v5d9MGO1cx1L+6x4#>g1lv0F@gI19bVs3FQiMA*V-v5DL&sGZ)$WU zJ}G5hGe_N(dKMC(A)fa_A)Xit1$77osBcqDE*A?XeRebK!caZn&=sgId;L3pu$c6v%?Xb*nzjI* zV~f$KeppFSkppc88VxPR&4taa9%(dpp&+OD-M>(X(>t2uQ9;2x>8lUs333<#d^Iw> zIZmqdNY_v)4!bQu8vr8hA9=r6ST6m9CC%Dr~|UMaAw!CBSZE{?G%k=tSy#LAWy;}*o8*3WN- zw=#?YWP6V>=-r!zu^k_oDI@PpY)*b;Hsj~V{$(~R=Er9GgBkTLVvpxE!@xe)ub`kCMEv>rF*(>> zu#=`9!gyEXOWZ`>pk>PFO#FZ#hr#R;=4WEy!)AfyH4npdC|!@*E)4L)29Z>@BN%D* zb`jKkyP(%sHxI>9vdG3W+qVlnWH?@Kz|r*Q+Xb7!scRkrI)*SNv_AmH_^rZdxt_E# z5UxCgc(w}R`X$YSDM^zjX!jQR`wVINr^XyJsJt*QH*Vm(!h(`KW7}y4b0qT@cJZW-Vp#Wl6_;+RU^51@560i37ipVY^n$iXR)+;g zkY_gw$!&D(HB5{dVmqJBeGB^mGj1@>;O5boi&z;r)AlM`+crAQ=Ojb5W%Q?7P@xKR0_ovzcV>CVvp)dCZDDS_#dt59k#i8{~{fAL&w7ADiB^%kbg{x2}M0Mg4`hd_FyD;&LD<~L9GonIyZx+tuoUX{g#408{ZP# z`UTC{5@25xn4C#(3jH7D6c8)Ynpe_RFf<*7nqxy?wCY*H}lE+%A$|BA&eoTJ`nQ5 zLilEc)?UWIc;<5wv|eA}s#vcdAth@~B$uDi$Lndv#Gwu(-WuSjtgy}^57&g5!ZlFk za}T*f_6@#)9Zt#+nG334cNi9<5(E2pV~iZoVPHheWqq|fl(zU`-oNaFrPsdo1hVH~1w-N6vbnk!z^Y;2@ zLQ;VBJorplt?%zP&@8z!j=XqF;XLeZp-gXdV`CjF%KIeeZJ}SF1@CR4zroqY9gYuK zq;%Q^dG=vg$>p;btX)Qhcd4sWbz1h1@!7vDF&g+;6~K1fEd?8mxS|O8V}N${g_@d2QO@1V#f)+ zhKP5BQq4%m+^WhFviEZ#!{E$xn;W*{J-8Sctyez`1*Jm@4w0 zd%`)x8nrtXKvqPu{$I)4BG>A#gwCvfsT=+T7ONN-jh93d4 z$^_~i|56!ae#%u6GHICbu#|gGjF- z>Q$uQAoVSxAFBQ*LX;K2Rg}BLCNN&6021Xq%S8QTcN_33g)~TeNi!de$Pc3*FAOSdQkp7%HH*^DtofAOJ z^A8oi{>ww5r@o^bIsy4TM9!;*8N{$i<%pIp{O(n18`^LwX$?=(VP~rIWB=oQ3XGDow-(6oufNFd6t$kz)$} zr0lb;yCbSa$!D_9{-&(^8@~y2^zGdp=(3U*Uii-ng&Fs=FvU=_+})mfuF0G49X}}= zmTNx=9oZ0^b%2o`WtgKR=%RjaXb5j*C(Lu?mMre;I&)D!hL@r)l z@je}`A*y|vb|h)9W-BS%uGvDqeoFHsnfa7vqhG63%5W7N!w+OT6T>lsL*LJxL3xv` zpM8=OWeMyuCoa_wcX!56V`cTM#3g6(q8zHp$&1zcQg@oP-~yoU_?yg&rLbh_Q~1)3i7yKu;=WBWpShjwx(&QykSE1}G{GAEec z4C(Zh&=I@+a$_5ULj_;I$xyA> zRl@(3S`n#eM!0*lcxocUvh6P1T4jVhs1{`-f!k`a7wt$-d`2;sS*=mdJ}zp+)#O01SWYy- z;%;J8jwZFBizI@@Mx)h!uLB zdoYErye%&_ii1M~q#9BLDN~Df@}W_TFgRPgpZ6sOvvu%cUksFb8QjsEPD#%m#&o&2S;?kdO1IY71Vrb~d zNnj1qJn|RbhoEWHG8173!p(;9cO~-!_YhmGi|T$<@SRN6Z?Y8mM!bwDgz7lSog|Bz z*jtGi5T#)V0|(~-r@0uVOv}%pTCl&GKow?kg$%RORxu^I@3SoC*b5hz$%pR=cI)MuP%7A(Q%4NZ}I1by0 zhfL;3N;=~umr6;-E_L^(IO?M&iqs7Wn_<5v6H~-f(Pi#@X9Kz?|tTq6#amfnl zLWZk!;!PGUB;&kokBVz%;MvqxjM2|`X9IT1d7I>1_-nG5^4Db1(!$dRku8S?q-+>4~&>)c^d_8Rw=Y|Y6( z!?)#5gOsdieh0Sp)?`B8=!P>?3qRrNjtVWgyep_T@qVi|Sg|XPn*xOmPY7%WfW8O_bT&kyNo?=K#6%5ql~B6l^{RAs#q%^Ai?S6%{eg zbT`zW@=TdXc8a`SiL@df{0yVRcT&VOFgzdn1g7X8?G)nBHU*hCi`=>Bgn}V8?Uc5f z+lh94o;yb(FM$@|)KC_s)?*f&6(3WL&LpzeIYmN4JK4!1kZsaE4u zkV=BafvxYXYB0?vLl!lA`haW8~X$DDuYfPI4=YUq@zU@lLajE5SN6W53F-Lnbye-`{Cu z%&zM8;saKj?=FH+Wbp|Po!X0I>2~xwspu%aMc(WpdLw-!N`^NFtnQ29pcBbFj)>N5 zq<*@41&qxU;T|yoGN^MN{(SR>cw|*Mg@~0*^>;iNHdJ9r3XpdVR@UwZgT>wk=L|Pg zUkULtOaE7Qg|_zTAwH&G;$AAPV6v*ai!!aG zijXKDenz?%OM+EEARp3G5f4`N6kqZ0*-98pnD3s!8jE@akWegZEdUNsu$ogAG9E1YhLQd!-_rb}Pj5M+~Z+qj+;DYr=8ke7Y2jq;xdj(KU7y91;!O ze}KIm8JMILz$&>TG|`{wWA#Oz3@`!(eswcUvak5ZGfYVkGCdH%VE`0>%oo#5vgl)< zVOnBvrg|VaW4{}y(RI2h!0}1hbW@IgmM1Na>7j({oH5NL$BV3;W^&SVf+D3Cq;`hM zr^28;Acd9UEB+9e&*&?yGKG_30kEo%6mBB4i#GBrWL?CUsrz_ok$*UrwN+I84 zs>E6ny;%I#ACF@aB2+P7^3O1n;M_ToeUD0$kjFwjed%`IpM(_$&t26fvb$Q8b+(>r zF;lLmuh8^grSddrARCsz(u}rRP}4G9xQFbwjFI6JStxfCS=wYv-0r6>var4UwB>Qi{BHn=fmTRLy`?u55zw53=_Ku-XeI0GE%}BTwP!?& zswUFD-qI@&FyXJ&pV5bUhGS`% zC5Q4`-+vGpI4mXYKa70eP{Vp4Ov%GGkq)OU@@8bgDN7TE#I|nH2D$%1r0=MfzCV%D zb~ST~L72?72bPYt9KtQ}l%zB(T zP$dw@MzfhLzX4MoC=t2^=dN)IYe2OV$lbRQNcOaivynA#BjjCmFHUg1V+EIF7m;x> zTr`;@;@Q{H++$>r$Tic>@yso#)!9FMAh~9!iSdkwN;M3`<3oXC<1)2+3bi7e^xBCznZGnC*seP&o+4dId2gFDN*nR+@4`*CREnFK0n zlAC;IYqTuJu-l@q>dQP6Q9=3UC)Ga-)YCdw_m{#3NQ$I@+& z{xOjbRmDUBjiG9f#|8bX3Gz&n)c%34M$~F#Ym*_hnk$AHm1io5zw+hiI*m;H$JA+> z^-DZc(1cz7vT#(Rfa9p9-r$_#nGC9+^sUbkjZ8;Nk7%B{(B7a@g{Y7=9>*T-VaLJh z!(n(h$}@{9jpT-hY!T(xmTnQ(8EVo!Gasp8-mKIZzFEAFshWY#D{yVQNpWVGzDYb~ zaL)2fNAH!sjd@aGD33oWKJ91FFgP8FJipfvAZHyz9K$T#4bG_bo#~!JHbeZrt15;3 z*vl1an@%xxNzg&?ggP@Y$DchV4wNk= zeRO1%hl-vG*>XIk(CxiXiJkP-9&A9wD49%rwM`Kc4#x3Ngs44OvTdz$jhtK zvcqJ1utQ2xn$X~80EO@7a+Yupwp~!z1iI#(D8Si!CL4rYcs)o=Z-W>-?b2*t7I~7nj}=2kI}km0 zWKGt(XwvCfKH61U&-Y+mUzEqhvg(?)>kvF6JB>HHu9d|gM_!~_69KE-*SNX-R4Rv~ z-A35vVoi6@&-1`ZABWU|;hfl`2u*kPh;jN!9+(;=DVR5PkJw8ds&86yJrJC6up4OO zm)#0-K0MDykz2o6H2PH@?3wHqQ=rz0-3nmO?S|f>#Dh(eUEvId-O4h7ild!A$AkS5 z7<-_F z;)b$M`Q}Y3N$e>^xL)Q#c!9(y`Fp+hD&xBD;#(84SJdhAJuo1MSH|`6vx?#IwnKK2 z@=~fJ3>c4+?EQWn;m-Y3N0{cRXz>)f?){365H;o-YNmL~sesI6Qh^XV<* zK+(SactD&&B}8lyTGV**kW%BFL*fkmG!M)jtWl=G9-_x#1zM$t#jQB!_Ef=?SFtt0 zNTbO7fi_vIU;ixh_-6;&MjM<3o=S+Uv2tsr0~96C=>fK#erd8Vf(dZVoR;lD?W$7s zi#<4yPgRa&57#Q&rf+M-gZdF3m?}Wk6X@kLbqWr>T_>*5r+b!zSSuB>kBTy@dHSeW z1RAr9#-5g2=zKs?6D~dg?O7iWY!YA;5ctIPg9@St9}+A4U58QN9PS|dFSb852y_^n zBfSvZ5&~#qB0n5gLGM~|%7uvrjS2@!F!?>ozJ{Y$%BG!j zy*N&fRnm)YtylVgwO%Cp;a=D|#3}= zgR_+v*5GN1<-+*m3Ks4-E{@TsdSUzkx354Gwa1jz^vN-C-dKwM8tVM{B=;mTvzB1} z4?}bvsEwV)HIRxCGDo5>0ab&fjc_ivgIwTmavpLyz!Ya()j}^$+~XnmS0W|Drt{)t z(*B(2a(!`LjO9pJy;!;PqNs}0GLw+{6v06Xk@bEG4j3mfXNkcZ6rJJhT?0WFUz2*O z2#?TxI8An_KxWkpu+Q_tg+S~euYwhql;L_Vi6=V2%M(;OyOMuj6hi`G zA^r8BaLLW~!gB|814xRx17ur4Uvsn?w~~Q@0Zd1H^+3s`Kc~tI^91>}iS&Iz5rZfn zBs*RZMg3GSUY3W0eX>XFWe@NKA2JNj$-~7s0nW&WvbvUg@9~pnJPr!2;+`3pF;-f-=4KY9ml>)%DTfpW%gyUwSJ~I4s)X%y-V%C z`-0fUFNXdP&Nts1OQYDyllfV*yuqe}GL9`Q;wCeLA?^74Of1b}H{by9OulC#(amCi zSpxC_veaus6@_V(G%GasM6;McwIdUlqyR-FW4vNd0Z{ORfXVhI;Qhd36B+9j1NPlM z0U7>Jtt1t10A-S16r~M08j&!N9;HPZoEmRD6-MMCKKY`|doU-h$+s_xLaVDFfS}m( zm?*x4dkRY_oXPUyL>`*0K=Y@(Vpsnd{q9W69B(qFTS3}iy<#BmTwo1gl!GV>@H=4< z@5|H=WT+RX;qp!B)?QZ7_4k*>W%@4O_K#Fp`-)QG$}8eL{WNb1Du}Z4SC3Z}v2O9J zlrQMK?XV?@l52E*S)N+5_+_!@&SRo#l9s7NZdvYEt^%iPB{+_$gd9AA$>yTif3O~Q zE1Sb?Kq4_ce9~RaoEM;BPK3EKU2_U~)-gFRKnE2t4uXD;ChZHG<|yh=RU9|i$*!BT zk zUI#hL3q>1@$^wpVId90q9zqL>*#>8x7rIIqwgze>zNRpRd9P7HYk)Tuf|g0Hk!82b zTHh^pJAC1Cy--kEXeQH`m$>Qg( z82jhl*}hyl!u9oFZH5}XHv=M~()FO%ML8_kxYxz=dcg}lq}49>E9$DUOtP+mdw2Ij z4Vk7m3f5m$#J3-=iVmv8F|_yw(Y`MFB9)>2a|3+bZ#BbjfN*<`8;fcFe*|`O>Yv2! z7%WbTEQheBWrM-ai!~Y(@u)P>q~CD!YVx;X=E-F5F!LzwuroN&PO^~8PX?PvX-^#V zdWM;G#5v3yqn&dG2iWmZ#29ZDNnEBm+*Q!u`~|!7rwFPvm`k0>H?zB_(sQDrrn494 z@nWouuMa*}FuLO>;+Og|FDwT-C@3HQsVEyv7JLeAsx!$;EeCor0W{EE7v<#OGp>un z^aH)ngPN>zg)`R`QRtiN;tId#7J8P=H8KBY|H;CwYXO%9Yr@B2PXGt206TZih(+3- zA7f;DUYsuu))zbu#Vy=TkH_M6IK1!}C-&-eC01;s_Q+h+YC+WI<}s!dyPFS3mXJXp;>VyCN#Y}zCqXj&-9tKJ{8f2}07fQxo22j+LgH)3C!h0;gy{URDO)?XVl zfE+GRInVcwkgT@@uQlBh2L(d^`PmI3P$H3NQQS~uBcJYtpG%TO?x3X3Sa?rV91nfd zQ{jbiL<=Im{~KlLe)5gjhK&ANT#-f>pq7be*j6~>jzvVoShfK_l|Sc7??j1|2Q=bQ zKPu#H{EuP-d2nBRl587mFCl-7v2Q2a#@JzpJH|eTtoUA}vFpIQ)-ZfNT(df|PlI!< zfz94|_U~LYH{2Qh7|#4f*#Vj~O^b~r_J!~`d}ARODLP}D0UP9Il0L2o_`0?X*t#3i1q(5iWR@n6>M42QGQq#H~JJSv#xqBt7HTiU9WSGj?W@{3;JPQ#v_V-bR zlBLgUW63k`+KuG*Q(BQ+dx6iuoZhb29z|dkgbHz;((Yn=6Wb}Rne;iLJto<^XkpRM z&t;zFZgHzP8>n4p2AbArwq4jPD5>HDiFn41FvXBpZ)bhu$Eag|;(U1rIZcTIbxbb}l_3HcOQ zgsF`gPvU0A{L4@?whpH(9TfY-%UzMitj{2$9H%GKszg zut}t!E^IP6)yqB!(iW6WW_svYgCLF^JlA?NACk!TxbIx04`Tk{cD@;^G6z%t;ZK+u z{C=c{{)n57z{E$`sdPFs^()Tc#5kct{1l2?AbnCQyuqu?V*)!Y|CF-J&p&4t73NiB(#GRHoWGq$R9UO7fNy>1Q`#us%nQQoeb27=(7KADN7uwRY;^>8LvIPzlO+>N=x*zIF*7zjzqUv8xVawP~{sS@D`! zyA*extF1!msx8C)`L#vZc;2clz@2lob5WkHorUsD?NofMQ|$yi{it>f%I|82qyFXE zLAd^~mbQ7d7Tv05*VlHz3+rk-p{%V{bHXy(g&{<9RZ-&?MEmiwjJq+JIju=#r4J`;Q#E_BX-<5a0K0A zw;Z9}T6=_c>+vJBTaO)~-6}tVZfR=|qgz4k4==*~HHQHww&rj??o2z3uCUI-v=i0U zhezR7yTb$VWBFnF;iZT1VeQ7l_%OTpa5BoO!>ur{$Ldm1*43daOl=*7(6YJ&)a+Il zhw@lmEbd&bquqL~&VusQx=55S*BMd1SQn1B_ST_`%(HbtsNb_rjr*RuY7YOnYpYQ< z*HSQ69>!8(D-Me&%Ma6r$_|_GLf6B3T$dik_}G%eJj&w3XpJp8v=UFt4pGdQf2b0J znR*DA!4@3C6tKaE7NE>Kgo$8I)TQA%_Yn5%+I@joIm2-4(O@}4ap%!sIqlGB+e5Tl zQx8R;3^^2nGW!ti`s9P?y0+E9?9;BhOL5|-(ZifLrOYQW@ zq_NhZ*SD!1FVzoFZq%1;KTvg&Zk+Tuu&0!o`{R-!EI?p=&FwaH(@(6;lBx!T7UOiV ziq+2<5KA+U8e&P`ONJQ307pe-$pTQufb+d`yP>*T&G%=Pvta-o zH;blcKv<;D|4OwG@6#XW840HUOXN@1_CHfzv(YUBD6tX$OVaCVDFqioAN?imH5bkW zA;{cs$Xoq0j${6g#J6GWE$AY9v+w#tg0}Vt1?}1*EGP{M+DQ%z+K$Z!3GT^fAb8#X zl9a2OMg=X3!}LCf&;-)I$AMqk6~{n}IQ}TbuV0P=;khm+QgFZj$!Kt?o+m&CxSl8a zgZ^AR0Yu@Fk5kGs?AQ{N$Losm)>n0)QNi}QOgtTN66nPZKN*j5*h!!lH{>LJYtYGR zAh~w^iRJh);6y3P%oBwu`<`&%e&Gr5I#acO0YFZaR+T&U|(p3!SqZ#{hzp zkI?}vJXVg-i#awI^_L!-j`GAY&>~Ja22#Z3AH$O5tjGFO*0B3n5B$&_ z14ZJ(j&(p8dJLlpnthCZGUym645vL7j#6_h2n~%shB0xfqm=N?I!Zsu9;F{+jsj-v z??>s!)*S`R*#8_If%4x+`{C(~QxrDSPXRXEv{N89oZ%F(zM7kI3Pg&Vd~y|DOFv2H zb<#=9A2; zr`>WC1T<*oQA$pJK8gXb|2#_R_fJRhN%qI1bQpJ!s!&!BISN>^59=sdd{77UVZX1d zWSFqpI$#6)T^%KDf3KrmdGZvc$A7EK!P9s@{{?>d_%D06ZVIkHteb@L-8z7p{j?6e zhdEsb7--wn4Z$?U)eXd~cdi3G*z0xZIuq6=z_4}r#lwr4`;tAttU^%k0dTt}2yl4| zZr44D?InXHeB7l)c4p#pP-EkiJ(b*Pjk=1Jn~d*hArR@f)yPO9rmtI7URQnidxM%g@qR+D6{RT9P0 zPNT9G+sT(!hHdv(x)q>W|BYtx+;Z<;pMS!?! zpJ>K*MXE%qMef}* zl#*R&%Eq;;k)lUqBV7Zvr-3Bed8b)ilZL)1-)y35_G;5el&?1ddAL`bs(Yf+`KC@l z@cbrVB=>TYi1Njz2;50+(&F0Nh{eRY8>>(@Hx{9Mp%LBUE;XVn+{H$$P3^fx+T4Z4 z?kLYTqBZVJBNhi)q8k64I$eVD#Az&!puE%h zxITV*Cd#9yf&M`qPSgG#ISn-D4xff7%Kd&C^ejkwns)cbX~2nfoW=*V15RUAa=T9l zqdeF^Kd`?6oz^aFpfqex16mHsZJ32SGaJxpZePO)P%O>a2HN+X4YcVU4Yco1H?%|f zR6`=F)-_;SxNQv-Dq9;sFuBbQQMkXi0i)qIH9*ASo@~H+<2E#a5OC`o0DSGx27q0= zryf(ut*c*#@{=>OQGR@8DmsyNW-^{WJd*{A#kV?xIpdx^lZn!NrU%OR&OqwnBF`kC zG@YRzzIKL^xOdI~bU_7YD8YQY2{I!0OcO>H)Ts$ffP1TnQnj`9pm{+#^%b~YQ%@W89ST;Ct%{Q6$#9jT}ASX2*Cb5-@2 z%b@f#l$TZ1Q+SlrQ%D%=!8*8k^`R)|*3)h|PAx$>=TtfB&picP(Y8J{4|ist0>)_b zPhmo}DW^cmf*hytMQs=16y{ac?o?Mwv7`vblaQ{a8(YtE#IV(XSXZqs8=(7D3`^77 zDWR+?+Qnq)lP>G2tx>?Ah-_*bBOhO1ZW}XKuelsfHT`mh;I=U`sp{J{rk}p>vhI-z zhmvEu=vt@^uoo!P$H3U4?^)b+UC#4*C)dZJP3_*u)swlx9+5%q)Ls zg+mNK8v>OUA>(Lxl5GZO*UM2DgklMKDm_NlU;iULCLb+FLW^XTUE#IqF|tAH!1S2u z`jpEioFpru6=tU?9@D$hV&>>uUyeZM6+osYD;4G^$FwEyroAUS> zWV=IsO3YY^V*4V@2W2X|W0_hXK(y)q&$&c+_apLUc0j%aY5r@D*Xl=TH7IqQk5>N| zNGpjezq~AWv-Dzvk|+wrakPjb+BN`QW)5pLg(e%&_ONwD~p91I2mg^T2Sv@KSG-Sr@U6`Ql3;ocxT7<52c;C8O-> zf+WGWzW||-x1PuH;3Ln21o4wDf^PE@FLpsW;UbozR)4V?Ympy+5p*?Z-bD+pM_;5b z+b==@;YYfvQI2p`p&ahQ`s0VVAhhu|7l;Et*oF1S4|LHF3~ROUE|X)tfU`Ey8xkv?{uLAW$Fdc7ryaA0jl=7 zfRAb4y+Fs;@xpkNDHjHSK7V@wbd7I!ffCo;3!vNV=ND`!zrH{R;JKhjnS24{lTW$; z!pX;+UyicPc{+^5^PpmU!+B6|?e+6BL9v6nod@aSE$4^flU>h)X7RP>=?9|Dr=v8T zZ;dkId<;tcd5CL4UCx6-@!{v`2z2Mb&G^uBr6@zr(J2c)2lB~l&Ve!T`_9ppRp&;b zEWboQTyiN7<-$u7Q7*VN5)?bA@DgY>UvLQolFz%;0cFmmM3i$c#bSKnmoUfbPcMO1 z^NveA$~hOo0D}5oq|iEY5#!)zUj%>Sr(VPW`1*50@YbK_&?fiqb0EF!wR0ILZ=S<^ zvu~Yii}I6m7!vo-a~Kj^{l+;n{(1WxfX01)E*Rzgb0D7Fy|YVE{_Si9o?bo+#=zY@ zOB?d)fv9><$q2)oT3>8jak4r58D?dAn!(*|>) z#W$QG47Zev=C`mO?hE+Qz6kn!N}Z}-c80p1bg;BgF-DSZ)#j0Z)kQ8jvjj(CiY`*} zP;aO<5C3b$Rc97crRAgA&7+IWS%0lK`3yqlz<;f+UkwV2lt@y)$oyB+74_^hh$R3s z&4K=knO_?bB(2Ka!Z{vm3&>G$h9<4E$Q7OI5qM-pmAO;2pXW){5QVs?aA95?Oaxfc zP-#9zdRLmu{2oCy4DaAx;(D-G*r{;NH)II^_<*{GGz3?`E`u?2J&Q^1r{Q-~d2R}5WI;T2^;uP2K=B^xr z*l`5cE0v9>FHI~dbu5FGlOxyRy7i2`6;Dn)ZLjL?`%HHRv1;SECtzi~m$}Jw_kCsA zWtd6$KI1oPl1Gd~z-R4ad6M^xeW@R2QyB!SxPtr$%}6#nl^CuC4bsoOj1#Z6Ryj_s zl<9BZ5Q~wtJ7|w-slUdY1e4hZ>`%GI9<;y0g^5xZ<1-N;=_YrITh5Jy;q5(S0(_F4#wNqv?>e)eDQ5=q z*Kx$O2Np*K>}VWiTA{%IhUuv8gX5bHVFJkw75b95&xYB^dqF}ZpQ7$VoDDk5_G@pd z$h<~G1ls1L6C+*IJCF|hcRbEvJYc$(Z+frJ!O=xj$-oj$ssIpbj zimk&2E*43kVbJOKbDW@9w4vP24q1JI9MlR(s8!8QWmB>3{sP8;TM-VVAO8{i2{QB40TD>a zixvwR_&W{}uQh8dMEITS6h5p9?w94kJ%f9;Q>S(y<6eNhK>VLLl8~yr{3jQ|w^FB) z%()1x`UfID`R;G{gX@93g{i5&7w-Sb1(B*hxh#UK2vr+35(G;vz405DMAp8DNh%p5 zB$5%dc=$W0M6WS|-q#<~7y(ad&;BtQSM{S2;}tkyBfCc<9;pPJ`J;u17BGD59&gsI zv8(~&hp_BGC`^6tFTlvA()qS9Q(3-=e}d0L9Cr(B{=FRG7IH&yhWjIC{4i2uPGZ}$ zYMi+>zz<+5|1rE`+H`~pB`aBH+=!3&x& zdGJES@Zz$n!ivJml5%*3e%nEv+L?}BAX7Vp>G(Po!jZT&ZDp7U#DW-Escw%`8Y}`=L*V<{4G0*--`k_UR+(HMso}b@dotoyGG^v%> zJR1GZE0%V?hO_@bm|ILCChiX|oK9gIX&y~OONw#>{k+UvR%ZVB-;rO0A#b@gaH+(c zsF|aXfw?mFDsvPO-0E-(S&U#&5D4)}GCqzSB3U?OTG?(9YB=SufkBJ>+(f#394kkH zqIFm`Dg88dYlt&pO}bRE1I=Y)B`ZFO6~ zC$kb@MHEyLV=y8jWOu>Z(eXkS_(}pJ`LIg_-x=Q0dPKTawRS4b$L+DP#8`&NaE4;o zMv2qILdbh%d^-|U1`@Mu?PS89MNS=i8J|MlD&>2roa(ic$m$mZ_u%83NWPB>Qa z-bnuDjoE^?CXhd~d0}S(Tz`99iMi67VsaG1d+;Ce$N0tk2;Ros2PSXh=5pzXc=ri= zf?djv!g1yUh%-Bw1x#<8JFe%Jz{hJc**e!El6nI~ic&g>2ea|hcpGcG|1C{CnQ1_( zm7nR=3%4{n-_!NCd`~+N{Vh!zxqVa9iJV5EN>X>Tld@aD{zEr4$)x-yjUqssA9xdy zU8So?dL@11>(9^%UK7cM&rt8O0i5E>ZB1X=s7P`yTg<+vmAk?t_+hcbe26VAtKJ?> zh(xZV7?A60{BgwT7z5_~FQiC0h+z#w1lw#kiWO{P>+<2Tzr1*L= zH4}8om}zNG`l5?rBlGe~ zWr(d(&v%%R$VRC=&V)$v(%|AvFdvqN^dJH}?s5bGEj`#8fd_w5Xct6;h5K6R6@gaT zsk-T|*pMBnqNH-ZF+I`(U@p7#18-;i#x6EEWn8q#jchLpB@3I+E|v z58r?Wvh*mtkxCV|KOicp;U z5p;SGYhms)UWqGo=0D`5VO<|+i6wCki;9ePSkknP;#?tH$R_V(TRPD`b)-Xy56X8G z7YGxC3A9HdIp9Fn<)Um$m=7~(6WY9`c|x&JOx_x3>FgisKudzkw$8TBH!qt9VqPQ+ z$sP#kN>}OhN&@1oOpBHT4YcTeK$L!dG{6$x;^#5^Y%vv5mGzBU11E;~zR-67zM!-g zIlz*p8;FB&5U9LzF-Qy|`!g-A>7okZIEiUsY^}&DhecZ*0;nV)EEN(>nwdX=TQ~U! z{2k!n6=Z6!L)e71d?h~@>6QBP?f6LOcz*(bZ@@0S5le10RL&E){#*ynjBJiATA+QO&uAluYcb}Z&2+IL+YH#R?RRLN3DQRPzofR|B^9mI^r zvnW1AuAUz^IRzK8q%25EZ(ORCBp1$p`bZarik)Q=lgxD1~TzF~w% zBK@5?-%*J)%MP*nPcxs2TadcSVZ;?T#j%jSY_5Ow_5??15guzJ|NCuhkC{zMzlMS5 z=m%V}@|{}@VMs}NWnpDiE}mRg2G^VRcZj2~a-M#Gwrz~BRS6&=>?JvLIiQ+rZ+5y<+I2M*Vq747_uHN^l7`d|fBmc(( zZ<{|P2gaGZl6m9I-3@^+`KK4bj>ntrlRogV4}{=(6FY+?z}+^8cH3~fO6_lev_h?28GXVZ~OT+99hLHIrPWkegTLyp!}Na2`6vh%E+A+dC^ zlk8lpS(gPd1;Rts!uVK(;L_(=+kqx@iI*Nm3@OYjUy2@Al*WtkB65AffdMa(_j9c# zRhqg>7vIlAxz=bhGuPUlWL~kP&?}LAp96^z%^`(yj>X_3JFDk{M(oeAgp&9iORKO6 zRS;>Am`p@kSb7IUa;_zvc;VC=OQ>2DDQn(|KC8m+Y3l^yPaKvoyKUki+W%xaqL0t;XfAz z1(U0TvA-}5MkxPh21ES4O|NnX3mHauG{g-q%3Fx=D2}3F6RdRS@W_xXz4YfGA;MSn zjX@BSrPsfwQnpm3@v149+%K?3kar%aqezXE5nhU=1ZV^Q~>k#e8cbc_!Z)N0!iHaz3)7gy&o1`DSA?y=YA*OCZ1HStE%z z&)O=TLM#IDh51+br}-J6G7kW&YHm1Z0=k`IE7^Xm1{=`>%zP#t`<69azAJ0DsgWh_ z-KO~M6B7*J#6IA}l79@vzDfCcUMD9&4tls zfkAu*Gl+7wC#z-NMg(jJ(}{nRE9Y`41fpFBxTtKFPFjWwpN^0&r4HzKEQ<=^x5aGp z4Q~4`)4CnwqPq5@pE1Mp6A9{zd7M5Xaq}s#{h3^6tne?vhn_$#WtyV?W9AIAfhpiW zpl+hlUy3@d11SqbAf)!;QIV>6b(+=p^NubmgzVQv(Jf0_g74l|T~rb&&_x-s?Fqcr zONZAws?$3As)XsHEZ7vMrO}@v`6?_*-{PkWKgq(ds1(qLv_#(<&p%Mp-H-np=l4gQ zVUepWt*!4V7akQcEQEg#kx=2`R?9DiEZCa+9U)RrL&%*6ek*`Ny$x`#hK3^@QCz+R zpWVrnFvGB&8wk7XB+e`?!mrskNQbBR)?~?3{1kF=8z1j_@D#6O`CdW2$S2$RHe};g zK7sEM)PsDak4h#N^-*zTn;s)Z(VA?gR|P1v89^CR|Kjw3T8KU>f{rMf+zyX2`QZ|d zcueQ;lPnC6>Zk#nH5^C3og~S%Rw~z?g+bwL*t&#pcOar|L=NpfaN4*BI(rBsnE}*@ zgv{^;Q_HMo=J0oLsK3>&iXxX{RR)q1tBRL?8cIqQ#!bj6DK9N7DP~)-t;ppM)R@Uw zxWfMwqiRhnK|4Y3-M8c3ziqx3Bgx-vDkE87SG6L8ZK`3Uza1X*TWzSk$)-wCwN`hI zC3gC~x9zGhlJ-#Do^;xV_$EJY<)0@_Tlo}Kdv#hWNqY)=pNHGv5B*rIDsBQ4$3Vle zD7l|NExr6+ByAgngeSis%;zqyh#LUW{R{Rqn8-vZqyB`GVjZ)H8Ox<1Rd^Iw%|G$< zIIeNr0k`LWLjlBX&f1m!l|=J zT&gxQCCjm>up+NKDl7_TKI*X+b*z=+2IN%~<`v}Sj?RO??}!>7g@YIMC{p=xSe&%- zMQC^UW+;P7U?R~0tm$(YqCSnRcO$uuuyObY`zkoM6F8N@8o;971Wv7I^6=6vmf}Vm z()hkQQa`1zGG|`gFnHk?Y0MfkaeknVCDT7pC()ucHWS0?t;pcXc@?E4ao@##NAw@4 zyOZB;AWDpcVISO3M^J=|G>)sv!`^0KxnnU%Yls*kk`*`9@uc5}>ekY?$if?HJ?U{n z9VazOI^9qQ`yS}%1F5xd-bZVWhrrxDAEJ=%z4IaN<i-p%!K&=) zH1Kcwt)hR01-b728fNEkp2BFc$%s>@S$xl){8w0T{}BFTI9K#%co*iZlF!0kK#zE* zuW*OJBxi74!6qNTYVJ6@p3PzVV`Kj(RMKv!C09dJ(VxFfj!)Fu$hwKzRXK7RO7kR_wvm@4GDtq|+{o)iANJ z7-)(5>$r7s>cj+M++~R(*LEY*st(Ud{ccMLDcx=96EY0>RIy#T7KApWob=bdj|Dp?t!${ zxW{4$kjdXCYvU0K`!JOM(F|Y1MY8Ll$K1w5^Cs@_qO}M?0kuou48*;R&mgNmQQ49L z$N9dq4LLLbyJRh*Fyf7XcgDk)u-U9%&Uf>>Y=X34mJsQwuwYJN=U=J89`&ipU$ zR`A`@|F^Fx?>d9m&X8UX7~`i+<2#d8W>rk!{A!$ow~>FB^P&3CwK!BkA2X?DAC~Y^ zRd+dW`)kz@oCz|ew5sp4h#|h=RPb@6?~5_vsdOyp+y6SKqO}P1f!6~;u>ikefm5Ns z0zyT8FXLCurm{smGn?f-{2{EHToCluJkA@Tf;x_4{3>obmkAyl4kbE5eX#q0wUrQt z;XVgm{3G)|bBWo-EN5o(pM$qG;>=+!TZTX&L&2*>Xzn(;v@=9OZAqkPyr`sbYTV{r#S(Z{1SM$bgwP35YKydV@XeuldD4#fli*Lt!%13;Emmzw z@z);$g=tP<2|Pul)-I1NVt%iZ+21xwN*ibkc0##QYafT^xqm zA`iQkw(vdv2b5^1!5kKI(;#rfu>Xdy>?I^@akAMk-c4am%y-N+q{m*#jD=?LGQ_H_ zAcmJC?W8Z1JkU96!pO3%SCZ$@`7Q26BQ%Xv5<7nE1(3PPpTR>+@Nl`w% zANnBl0ZI8mZ3~T4Thjb5k+|{ZNX}a0x_?ePpCwbzY2(S%3)-JX(-DZ2Sl&RRorQQ+I<(Z#1vw6&7H;A<@;Q8WocZ0u&i(|qi7SOBsw+D13wZx_ z99(n(VYmjsjN(eT9BveVm&{p^WZ+xmp}WBDC*5WTwShH)RY#xRoQeLgnG;M|QfvYyHxFVA*5JtW z^sMv_qcTSi&$O<#t|m+96s$WC6ifbdAgF_GeCH0M2ag{=c8YbXbt;KI81xaTJ^-x0 zelTcJ_YnS5@M|2+y7}Eud{4*D#)$lt7q~4LLvJnuI<`yfCU!35nqaupKgVoga+&Ta zYHS>kA}dv=3ntHp>vW_nT$e(N_>iK)N=I>J#MOwa#1^hg#;&7761k?+i9sVFSw(mw zytE$JrA`+{_UUw^!v^K$=TUW7L{mgli+1OKuMgo*MVz9Q?4-L+r>8HPi3&md$=;d4 zBDo!gdwaulN%XA&nPX(yV(s8 z_S#`Jya>{p&t$Mal1vea%&+b?J?P;kA>^ z!WqeTkRIv5P*?sVt{ZrDly3^ZI%yPrbCy+7SW!|84!5ANBK%?aLprB|J}a-Xyu^R= zLHGk71{^zKT;jtD{sgu{(&Sd2Fq(b${`RBVLQ0=Ab(Y#CL!L7kd=H|YGgreo`hiIrK{&m0{Q%s$qE9~r3bmb9~fhM-jqR_pEC`G859!?va+<8#Gf=KOP-=C zgy-b#Tz>>PD1rh`M6APJBzmc_?j%eQM}V1p4(Vi-bdYwBX=XM<*6ze#r-M!)Ck0(cUFO2ls!DoB8Zj?|M1VGT5>`5~Q^DB%ieB%kP0cfNJbH{0n^r1|H(-`f$TH!RNlM(pYVxVTHQE2h= z!WyICgY8Q-0oYDhgGQxwTvUUmDE5(`YG4B-Az!~5qsjM1!Wz6Gt>C+>F~QOdt)=&} zI_cX?%dGI7EE#_@{zmNxA}No37Rx0Q#PxG5mujSfkA=qaCH5(7KhjwqaT1P0fE&%< zfRE}9&dDu+%|s@SIV|k&FqwZJ^rjAVeUR#VIQ$BQK?3>peSIij5>X;S%7w7yGvP{0 zf%b+UXbFT;QSybL+bSbAus@|e)vu|T90m-(H;#yN*a&7c&NQUJl~KMBKhnI?f^_;n z?7atg6i2o;Jl#E`(TpbNq?u7hfDl4pa*#k|Nk}4?C`QsCjnar22@pvL8)qBv7;4P| z#$mCIiN?0piQqL3VAA4*6JVR`fK70~0UQ5sRV#tLyZ1idv;T9y=UeT1=&r7=uCA)C zI(5!_-qX(!>i|3LDEc3OtyYnq4iYf?BdK?C@3iFI%)P>oQ3}WKx??1eW9JDuP)mHq zKaKCPfKPQ5teQQ=3R0-=rDD($*~0D@pSvO_vtMgPIl;jrXG8u7j+yVR2GtY881( z;W#RlM=R9;(b~!uxZBXe-LU06h^Zj}RgfA}))SD)^6&xQkLA4?Vt0U_$>(4p_d;)S z0n^9fzTP1{FKr6$xK`7LPO=v8vqJFLEQDbSGeEET2LAxY#c&YeUWLT< z0JZ>QVAuK_!v9LiY-A=6-lMm*EDUK=Fi>zv?g?uZtt*i87UwPG!LYWN>^mKmAgUmb zXK76>-wo5g%4Lbq%aRC(g)Kr8e5JebR}c!}5lDe~yceKwD`Hd+c=~KzFvsx|5 z3TZ)EdRD6-#dSDJKZ_q!(MEp#6!SX@w2>p9YOSQ;ZY-CZK1EbTc66*xt5mfqWE?RKB!Z#ngcSD1rf$aY;Z5*kDm6%p8jtsmrHT4fdT&fts0Q@kA;VR}Rk8S!ujylWLm|x)((3A$-rZKnQ4{WPAong&Pr7<`=-d=!Rh|zV8Hl;Q}VUlRzf!#t^=fo6l9z zN5vE8WSz3*iMw^V4@{e-45d^UGTHq9oV~5Tj5(!-OdL!>j`}J z(_q@U0qv)Q2k0f}$==~!Lr(T4XViL6%Q&@uI?wuDSyTh-Zle+W?cxw}$T89UU90aQ zwq_BmTom$T=xylDQi$_z-3`DGp_9GDsn)A+q)KKZLW*E6Ey9%WfKY>_O9OM<6Ii+m zFadoDEyOMG<}$(B@faq}iO_}7<%;(1_oyAU%WuZSdJFou5`yv=4%l*Ofv8{q2>Nx* z)6xmdR3Oia&caDP8KyC((d0Z*z?=I*9V{K+VM!Xe&PdhC(s9%j*P9-Vr8Z0l+2*(F z>FH<@j{v}gh2A=fwSC%BX?qGTe# zx6yL4GGv1@h)(HnkY|A|6eQAN8h%U@8|>X|g_K zZg&;nx!cuIq<)85$Me6C<3HIwwsKbbrgsY|52-PkW%;vlRiL5 zJ23@MgermKPeL460UJ|KEI{vJy1E16!eFe`UqE__K)*Z)qo$ho@wtS1QfF>?;{}r- z&_Q4$kGx|{#!lT+{My|*Ga);%N!ew9aJ6Q)E;z5FybV(PVT`C{u%Zuy0_979YyO07{}?_Ii_j&=m9L_8)^I5@ zkmF~3gEGAZK)9TqU>&ulNhXt@aGgk%Wu}OiCKOo*z&6&FbCV!b32F8;GP?kp)Fpx} zntV_M)hTQg$+QH!rU-D@In};K7!8ulNi2bA z?W+7xO~_tsFJ@1j`-#ayW`1JQ5$`9a1ZMnD=LYM;LEtSyj_Ho+;-fEoY>E+&4&kU% z4Zq@0!zg={SoHW{dBC>Vwm4munJK=|22N&@E9{EyvdlCwW!!^iz3`sxJ$6U*n6idi z*Adqd`gl7@=VWquS6kOOS*BIYz4wes!LZF%8uID{=JRG@Dli}ljK7@_gl^=ase}0Q zD0+D;Tr4k0UV^xK2TaSO0@aQ2iitTlPVBB!#8(DO;v>PK7P3mkt0SiedL#P>dh9lt z8On;Ryu92(A7WV)`syIxo8B<4Ve)$xl0z*&5}QgM3)n8WKKbx5IwU`0qTY(Re-@tvH!3wG z_Ve5+C~B!@?|!IiMO^C?G~Ey`HL`3%I(bmVdm`@)O{I+$IXF}usVlTZ9vd339z_`m zLbZXg=S$C*5#UZDzM+YcA;@uMNLr+LP?yM-A*pCtOJvg!CA+?Ohz9A_$fP0qh zI6@qEH=+b~GU9=d0+8l7W_JTO=hsTkZZGJ9||Ovq_{ zBF6@qBAJ6Nw2X*iup#osppMhT5(@=rkQ$d;^E zU4|d`_hiFC=glq0q#iBbvcLrtGDDd-BtV%wCq#r0M3zjbFV67?;4OI*CefkTll_XN z>j`Xh15loO(6c8n(3>Swgb%R~=!^cfwPQ`*#f0<{6boCqR9Skrh;M?Ce0-b3xb_YJ zcb~h>(S^LPLg=UoIMocV@P%u1GsdlGilUdNMtkk&gyZrarn=w3DsAG8p578J#SKVUL>o)7*Q4I*hu<(f|}Kv zsBU+tn61=7Ve@ZdMY$E$_dy^kya>7QQOqO7d~ZmG=h1N6SQ8I}KH)N?!=0E*$|OU1 zH_zIOytl@o!JAsOg@HNs-ifd@)Yf}$^4vtz$USQuS}AQ8^57aQpLJ^-a@L}x_Zs*H z(Do);+%Fyhw4x!aZ%5ksI|1XN?Mn{b31rJKf}<^WI+O$kY^!2?1GXsMmEM)?f^r;M z3A&nFytjy##{og+_pJ1+WVISozp%~+v`etQ+Vha-A#&ypM>pDs@vMG3??C+$Wa%C@ zB<{Myp{7+yLT7hrPgaitUdxX@E%OZa3}*cg6JKCqRiM_p+`F9CIF(j50fKJp*jjqK zgCZYT&l?HOlw`*3ju;3HA0RX#goYQPZdnQhOfMk@WBOI7sG88=LtyB<1RVYY*y&7T z!uWe=?z^by&_zbF7CCKXVS)?F@&!(tc7#7r6D(;c$E4x4dePMP;c|L{OGUnpcXe&W zt;D;`ipEemjL&8-Xno^dcJg$*%R-Ofx}fH5+H9Y{dQM}=Yx0_yb=bGSY0_jZEb~?R zJeNI}naoPl$X5g%n1v^kSBOI+mQODzv#RHy4xVp4-x41|Nkv!=nn54tPjc2wLmrD(@S9^Lo+c@U+pXPHTY`1 zw|j4=7i?O8s3uSgD^$*$de3mraCV=1qQBA?_H6WQZ2cCEs-n7vDo@B0>PV;wR(YQB zJc9`_k@fm-YaHrKHfwS=upDtVVA_;eJ@nA=BuYl|k8^MFlO#{^snqpNDYI5t{C#14y7mSWdq235_J=6PA%*W()PhseaQ=zuE0@^Y?Le0MsR8SMsi82NVuIU>n}!Z-$bjt&h!WKNtf2-b8OA!zQsVerS=? zBHHcgX>=jRfLHJebmXOq_#~RHn-Hum^Jdiq{Uzv+cyGKoDq%u^p z&xlCh0WHTiXcvj=?; z_LU28ijOCSJ}rU%*p;`&5^-{D0ke$L^FolN+yoN&y11W4{K*jrTuM^{u1FGbo?E#{$&AV`vd=X zY&jaC8|%%>VEKCn#-C}>P^z&a?*Z-R9Jp*SF|&CzSon9Uc@xBjOmJzpo+<%+1WqbY z=04#*L6#C{S82Q~)6T9dM>Lj{G*r3IxX+Mu;_OcD8SAt|r{S;j<}~`<@4Me84~|BB zpet*guz0O?W|E=EKpt4@)REb1okPh4dQ_}N8jfTnc`bUTy>xPQjZ=v^1VSyV%m-_n z3bJyIv$yz|tWcl^@YsNNqIV)oA+y$CwA775Y5mrq6X|59x-n2);=}*Fa<5z*Qy1fy|ISUZXbJ*tJOO9t?*K+X;P(iyg_2!m!I{g5FX_|G7!y9)y_jPHP$Pg46k540+zM=$`eD0x z5l?vxo409zDt?R4`4!Y%bj2#3An z{eIxHO1-7DT3yJJ(auDpS{Mc4cQBaip!OUrJirfyd$yqJs-3Nv6&5T-D%+=1Z zOf$4}{TNy&4FBBpn$wZ}r-(#GHx2uO!aWfbW``xGAr&$s?tVPGH(mE5_4XW%Ayj1=0viZjS4cVkY z5!1E!%;}LX8%uN*^~DI(2HgkT2MD*rVJFdA^gAm(+lNnes;}JV-sj#&Z%HLPb~){e ztSVo)!V}{Gew|h#s|>@3ZmisA-DkzFAFn~z)6rp>90&!<0&Q>@&t}i&j`91O+Nr>n z61!?PbSLeE(87k)qiQFlNwqUwoTBp8s4*MKDQbK;Y;^vrLM_?R33{|+r?Xp@Qg{oW zE!6B(V>$s2Ckh5}UyYA;IFJOFfJl23`j$dy|CFHgd;$xLPrC5^wiS}l zal9kBxD{TVtUYifB}=wK(8Sv&lViJ`J;}D+&IGZ2$5VN(B8X@+9tmlp?bomyUkhvL z@w-uPbX$^`bxbG(ir+=ocd z?WohdU1-|$U07DxBi*~4dKreVj2FjD|7{NSW}QJgS)5uY)6MxdOnkG2z7VWFfQ{)c zSdj)n*!`S)0am7RY_%QGQ@jow=3>cYIGh5T1my3#(C=>J)yBh8gS%$D?y!&tUPIgZUUMYU3l3G-SBo+1tMRV(t|kSS(fH2Sv70~!ho+_ifeqDK?$_{I$m*Hh2rKRU4rFHS{qhcnm#p0309tk@N~vkTFk%PxE_m~<;(#q|fFMfE zpdP^^h_@cv?w|;6Ok%$64vRY6SXvRR3&Pv(WB13j;n0NJ(FbVEH1P&6ZV(@XqiFK$ zHtZPK$1x$`3;Wz#+*`!a@aQ&dEZPfh!dA-%prgOqec64Pwst!7+rpQ^`@&Ixjh}=$ z>VCBQ5`d0p1FzakaKc0DYs?e-pf$V?TaHR-f``EVZD*R`_p$YO0cwzq=#!hV+>~*X zxpBa)B?2XT1>W#)LX)%&n!FW~8UvnHp3@Yjh7#{6UkJk|P+bkLqliIB5^}`!9J(>q zX5VXqcCJds99&^Ga0BLvy3PqW4{Bh6&%xfLp1N0hN3w$OrBIl zjkUqB3EQe_or6^{R922vv0k;A%yJr>E_E0@ zO=DQqgY}JQBy7+W=cu<>PB3L*nLiNo8>?(Er5rV?F#f6ajHyse{aQ2n;3uZs9RsK6 zoZ5Mql=S^rw%YpO!eFr0BermDtuM`wA9aS9u_{p35d8@nu?cro`Qg4D49j1pZe%&N z7^J2CGVkPu>Ut0d_V1Z)f3g)Vh z0MGm@ zF~?W)J8gNp>YO##@9znOi+$zgAwT?-=lSuH%M>mRIxSob=TIn%%EcrFORBBuoM8^O z%k3EkE8?sD^ZeDtSXSEmo7Sl{)wkf9RIJSY()w_5nBuj?LiLLH_EZX(`dw;`uRKut zyVUC7{E9j;)!0!&1z_&&bu)LQ*JIu3^vvt8bUat5hzGTNX%(ti3TvkLfF?!!d^n5N zqOttp4x|ycvKF9+gdX4yK(^W&H)4SEcY0lraJ$1S|_Il=Y@RQ z><3(cbG0s}W2#f=qzV9C>zYiOVugXfzY2PdP@rC${ijYV=Zy=4Sj@E98#|><2!<8} zuoiFVoCYOcNl=@;zEf4$0;0|SbEj=aUMy#^Xwjzbsg*E^oUA zKN5F3TgK`uY6A`KvEs2G<6d=Fr?#8A5b)G;sBAmctZ7OxRHMzF-6`7?zppM>tIaO% zl#O~DYqMu{dQbRVQ#WC4_RLO+txKdfdj@qvZ*4+=g0RtOsM2On@03~;43$DJ-h>jS zbxyAJ)y?<&A!+*$+L zC-@J2(y6ZbC1nUz(S)HsvD5Q&gJH1F)FW?^1s3ww0>=91`>Vxj6?Q73^}En!ukF-) zqwD-N)DM46r;MY5L1@E}SU^`SUI5tmF8C@wEBvKNSPKJe5ODK+2-q&z#lD8K>3(SR z*FwOie$Rb)C&X)tyMLB@5EjND#Ofi~G{$jeFztK~tr z2sHt#kii#Wda4dW%by#p_CYEe>$4o8B36;lUl9sK)xa!m8%5r)gzwjTl`Y(vHmAB#*}cwViTmL z;$kZPv66a|vS4ShdOk7->(&|i( z$xM9T$_HFWD7)bs`6g}gYB@m29kE+k=GVTJr<*%H91N@GT!NK4>3R2;kK{sDU+51G)pDRXW(>S$CR#T`R73s zRLKl&6uWg7uv_Wy0*Apmn?np$p%X)Iv)(7?f8ep|>GP*F10~LT{(oMKdHEs*0NBU3AS|SJs0g z*`AQZY?6Ai=4N?{qIvWxD;TEj&dA);#+KR*@_TuCvvrjYN=I_)8IPGfPyjl$_twi7 z45H5$_*W=>Qg8khaQsALM@IE`weSK?0p{#O=;-d`N??|7!ng4#3>Qt3V#y#d4U8b$ z4k!}H-3Jt2Qv5Q!dlnu5RmZUdI4U}z(8K(j2CE-U>v=$-hTo>53*79}V3tFg#uuvc zLK=mmQB=>Uo@>>>6K{N30r2k2iqxoHvi_Oi54gI|W+7)b0ho5?LX?N>y8xK)>GL4m zdg1~YwiaFh2h@ZMQC;D@mM^N|u68U6>mRRn*DX%}t;J4-jgIgP zxV4%D;WH9F$k5v)*$5Ov5OU8-px<|ZFZGD<5g9+o5KDrC4Bf5BP30`$H|pm!RC~ua zVmGDDu5Nj9kU=WYxw;E^Zm1zq9WCgETwK}8mhFA-sm&8bRWe9>-T}_*cBnJ^F*MLY zC^DBpiP?>(ERWj&IV^(DCNFshipplmL?GcAa{^ZjDvS}B>K%}{F2Wo_A#tn7>{y+f z0Ku*1^#L+_2u=Xtjv-5?0FOO-3Pp}*=-u$B1uhwOJ$DSCK@=8l5DWtG!R|*UxPc;1 zn+)FpR@9#+>(kaw)@zC0jj|4%i2_puy{{FiZ3Il076~_bdi?-Bf}2bnDW}%Ns9t(6 z`Kgyahu$OF5S5}NZ?yp!i|2LexI!-U!b6efA&+J1^M;8yJ*(5|6dMZuPjA6)u@orL zE{MDEHnx=%nR)~8mmh=sbR|rQ17Vgr1FOYduv*-}-u{_b-4cl0eb0-pQ+WnXDXjUo zxO80!oIqlP75WvMCm5u?DIJ1|`VnpgymksU4?Lo4YzFmH77S`_m_#i8%z4r?nFPwl4XN*TJaOybtVe5B7<}>m2~!( z0!4thD8-0~IEVMZ6g>$juo}3!oDhx(uY>x2F93Q^3p+8|HiJ)VJs2ET!{)F8sOUyG z!_aBjOpXTzC*DBFo z%Wg%9EbpdDT{P`I2dSvU;!jZLk9^s`kZP~jmwF?oc<290F?T?_ zYV;o~Oxsj@?RwGwXiGcvo&Qo>8vJ)^OVxaVB#I*v_{tDrhcF3xf1>}?GP4CCMpHO# z$>RWGB-ov8v?0Fd4Wl~mY2nuxRrol9z9LU7omBwCK%Q>o-17$2H8I>dxNb@$lPN+= z%t($ui+p3BGk`aUa)jUy8((V5o+>GLJfESo+KSxu5!UF>o;8?R{>~Mkw@i5)$c?nN za*bq{Tx}w6KWA`}jVQfyZae|G0Y>?Q++D8EnD_X2_Fm>r?=_8r^Ksr9OMumywgFxE z&6Mt(x`*5>%mfcM4}92GxQC1fC*N;C!9RnAzl!StozwFW(}%-L`Z4O4(57q(lYJr8 z0%?EQl!UcmRf=&0)rAB~5x}6#zR13)pKMATO(#df;5#2Ao03Y;EZN`>DQonOfa${@ z3fmj)jR~?$C)p5E+2zpfIrljCko!ZpZPPfdXyZMF6#@~ zo9zE9R823vVjDv;UbW@1OfgyWnf6-wl=3Ok^r~$#;|#M>AMcY`cPMLEA6Sb%#om4; zSi>j}!k3V7?&fBJ$2|r-2rYp7`y@9of+Fr#Q!F`ntLX-DvcJU?ttkXqkUwO(V!6_m z!xb|DAf~cFt>q`nPjnXclKehq1v&i+ruKcfr{$)Xb#L(<6LKb2!Rp|4yNTu7{>tEl#uz@*pM^4J2yRDn`ZchYn9#d>lUd*(1SY$j~|sA6F<=xl$HyaG?oVo6Uj zcds@biYuF!?AxoAt4D_X{_uPlY3%3h=g8617BO7~%u-z#Rtx)i`*~9EaceSp<7Bi- ze#w5Ri!2Ka7JId^FJT1O+Cc&AU3(km|NlU3TcS?Q-imoW*+MEOFgFt$^M5BJ)yLD8pLWh!VY&8 zE5=r+0gK>~as>npo4C1f(Q`p{LIX0)fx;#U|0Da)gBE4Ueb`OEcwT#!?EFgGm8N-# z>uc>0qL=ABB1s|-HAxtSCva*woZO#&K>1m&L99fT*F!Jkg) zwtnCb@*D77j0S<;H~22rVVf}&d;|Xl&-YbOmGu$+&UbWH3zTvJo-CTIQwSd#J`^t; zE5qO#k0jpkE~}?TbO<(dH*|0Bd~&kPw2RD?=`@V=s|WPFcv2Jas*l3C^9a!HXE`t; zqJ@6rm2m$|t_~@7vS0+1p!E?>D@|GonGWB%g!yw3zWl z(6)J)UkvXo3q0_jXX?vdpk_G<6?Ky&ABg-S;K?(A!Bt_Cb{-a$qj;As*s9Hk%W}){ z-nz%IAC^Ij6zr{|pEnIg)EoNaKlj!7X-j!@^bJD6`Gy=rj)Z;wSvP={Y+p35n4S;h zRkhz>H!v?0vm}>Cw5J6^F2aX=3;q0BfZ2y&!a4=2r<>q)n+m^@<3J*a>_*LSDl1`H zwJv-tnA_#pSe-yLuSYrNM)cq;t($Bt)|QYRGJ~DWo`vsldmpo$Jh({LdRi01tH~xM z-(7S(qIalVxW@w%4)uxPVsPzSmUm3rmpp&;q7Gha=2O8}80KHEH<8u;dlg`1fhsM%+kXucg$4*Wy#4I>x zk#3#XmhAMG8_dz<(oC(rW&I58ZM-<^vZiL22QSh^vn?nSTmVObf$kBgUz?$J^+SI> z1_-Y-3{pKdq2KeLV+;BsCgne)Ci75}HYWugEGHMa)1dODEYs^j0~12s$HP3(6`xYH z)q0v|OL?4EacIiz6S(ZFlq1T-cx#oO$2|xIngc5$xb>{=GJ0Eb}d4IAo3NM04h0Lu(dWU$u{rq!b8}b9Z6}wn`txg`=?Fpio;Q?}=wgt2vx7LD1m0CSze=HdGr($2zHHhf` z(cP}y<^4`F?EeoWL$!1AY z_X1e{quK9_dH#27!vDQEXbfNr)ziKS{K#VX&?P{ZbQr8-b0P6q;G_65Ha*xL4F;C& zGlVT$iLJp6{1h^m$`AS5Vc~vY8*J}v$*bO`*NM`?&~0Flq{|{Xwg8K!Ya8+%->UB_ zE~GRqCJ%di#5>aO((md>CF{28W7_2qaJtjGQ~P4yz=RN-Mmk;1Z-ljO>jGUOp+_yZ zH0r9k|L5T_wX^@(!qBVN^|OAjUe}u$f1l$YtPAq5HR0mUDuZj_FrWUP=?iB48}tPh zB?D>7pdJEhwG5ilo;bXnnD!a6l+F3gW!~mI{Om6Ik#LHt<`OXsE;;{})w}!R&pIx0 z>j+;=|k3O#{_`MYEnoKyXh0m28|_tYn{HJ}L`9?iOO z4fP;U0qFwq5awA(Q;GYsQzP}tGR@R0(oBB+-We?wIjrdE1K-0{{O#|Ng>3{_7NnWU zupi*tsQsQ2E_@Fc)WP4wu{B?XP^S-Q_^4KrEEJ#}8G=_^J^f0{Jd-_>$@W8zuI(Bv_d5 z1_8%#h{0C?u-OS#qShT{ zS1N0HMG>IyC7wc0q1X|pd$<&0&0px@ieX1FMFGSVhQD>ar=H&EAay-lT9Veol`8u5 zXY_Dc6x5T@@9@I^6`f}%U;O}oU)o-JY$xl2Wr2no&kWBD78GaK5AflC=m$86FZuzl z;urw&VzeAKxbplJ{*o$RgJ+#*9m{_FGP3J_aK@0smz~370-__JXNPBp_~M^ycs0Nu z?}{8JPlA=G6ojg7Xc$fain9<K+4}`bX5;J^j5F36$3I7Fuy=XlbCCB?;gaS^WTTmd zUpfhAh6rHNV}LLJ1ypiRf=Zx_AHe34gNO_~55(DBL96gK0%qL>!nFYjvOad=bD}#v zb}&HXX|YwmWWzwYM1yw@(ef%lJX^CU!3|Ig6-p0p53>D=qX)~Q%9`)10F_M8o90au z?^=AtkrGn}2h|#1mAAXMJJDW&hjfoGoDND05cV}-=z6ofS>k(s_%q&xaaX_-ZgO2u3Q}u z`_Ew)0Pl~jlIP$8KMn5J+qpEf;bKWV`ar_-lC&gjgCBfbu#sX$zWV4| zWCFcK;OBszs{IKh!w22yvQq{J9u3re`voJp=Fujy?$qxKo4rNKp3k`8pb71`CH0h{ zdn+^p=n47>cPGNG{p&sjdCO*@u39JxCV)@?NolXs3&;4}w7988faS>h2E807~8 zS-9T2(YukpQdjoH>pMBodq=isCVTBzJlGs_za5Q&8NxxT?M`DcjUr`}OqYNl=@wu@ zGGW8}1SC7_7%g@hl$Rf4)gV|kCa}nV@3P2$(}jdPmEoD7?ayQhw(la4m+)6@eHtvc+TNy$YIckEYtE`8RZ+-qfz|G0D7^^b7p{fE*k)u4L#M*rIC1`UHk3N>H{u0$Z_$8jl$^!P70t~_1 z;`xi`FQoYhD!lAVtkhXwg5~29rdG{lP`02laG>=L_6`WV!&W&q{za$HL412NttyIacAmfMI?GK8Z(QIh_U84!z_O#L%sh zJ8{E%uoRSoBRRL#vDMCNFhza~I>-|sX{1WgbXj^|+HfY)Ga0;H?2U^M#w*z9x!rTS z*j!H}gNBGv3$l!c6lb1zp_pFisOvo`&UCU}3mKFZGXc(#pa7}#RI;{EPXOP!KU5d2 z_pbAuha-Jabf_ox%0+Gtx2JL*(Rd&<)LlY*nD zukNU`CpmWnX+31=eZ3 zj`ydN@b%%FvywZLoW`jbih#^!m58x++G>Z0Qq`@@ALhT9|DqKBj#dP|`$2>|7%jN4 zW7^N(3og-2L`FIZZqO!}X_EnOK8R3v2r?<@Eu0b+4Vh5}6OX+R>=$O$RCvRirflS!0SCETR zgOX-Rqd$p?I-rlk&PSY&uv4;Ohh8D>evV5G9#XplT8y5u%szyj4&I^Hhz1u{sAdP; z7CN5s@pgT8vU|HeT|F91wPE`N`vkU+Vz*A+4rd3ZNMX13*shQ6RPe9c^co5VQg^@u zbD|7!MRY7WB}Ebd-X4HbXDV=pMv#Uch9|~tuq%v!XW~_~=2M7(5d?iqH%<Kq9L^E3;!ruy}%Q}uk?lmQmTKW?g0u%Pkdrf+>daigRCt#3?C+>S; zzihiICqJ*o>Auyb-el)$P&GHMHbDlbcN~f_s)XC4ZYRA~qc}DF`D~R5+|UuA_*jk| z5tAY+Gu1W1HKIMCTU17>tJYOZdddwj2Ft-^f+I7zQ*MYSRcQtgqsbvMRi_zZ$OO5; zOS;No@%l9iJ%}GA`4mUAh#9UKCqS7@1YeXA`monwT3ZI6#QvNa_DZ^KzYQv}q434cwOL6_*wp%MoQbs= z$rmB;PIr-|rxJF$FJv;1+d?L|lh7absyBvA*usQNiR9{B81>K3MN{pbYr<4G7fo6< z7ws}(t|^@inTvZ_u;|9cnoe{yk z?2cf>Bqy_DjB-ThbBjrfltzv4H|yWXclVmS6wdCYO+h9ojpp%pN8K%oLLd-70l4o< z*s2C&1f4~Q&b4qW8-)lKlmnHLmr?rapCK(jh3#Dp=)-A%pvzb$sDX470G?!5U$afs zP$ovAi#i&0l%^z#>mX~C({7teoKD#39yfre$YLey+%`3t<+de>231@IPodkUAwykg zX}8;ECLhMyy0%|+s(gt3Qw=DOLyaBA{?=Ub=v*w+_SfyN6J5S|qns>>wQ1Ws#t{Si z%A9(?-_gy{P3*_ySeuTlqS>#yYSh@mki^3Ajr9l%%-h$F-1^D^-6VBxvJU|bmUAT0^hDk zMBw0yrE(?xl!{zM^m-h5d%SHfSvB64MBCO%ZpyVi(y2FQ=h{?cY@W@{`algw|JI&6 z8FiA?y`?G7)}PxfHA?%?sV7>JEa7q?ff1obk_;NADcoO>-081&wH{!L*w{E~Zow8q z|C@Y38yaKWZ}NEU^wo4LMFYaFThO&%$x&c-ItT4M(u1XTM;;T|ZF2Ef7P3?|SpjPcPR zgWQO2xdAfMDeMB4Abh$K#2=r-!R-}v*&{$ZEQgV{geyQH8B|Ar85+gaFm6{GGeF%Q zGXTkzG^Rige1+0LM<|W2@4+I1qzWea@ISum?M~~*vAUO{5R<@RfWAKZS ziazS4Rne=ZWZy#?7ALrbhQ~=H>uhSORglgW<1y|2R_5f2#UgHc-pGoWMZ;h@$YWG)NFOnUjBk;9>Cq&zbc)x5`?oK3D2c_h01-+iOU`2XfGh0!kOINEth+6O0MO68mHh|{@xw? zgDEr)L@cE#e-T6wA$(|bIlKU4`))86H6YSjFBl0gVP=0E6IK-vDqUez{|sDrTY-!T zOQt|jn+AMJHj6(P1?0-7kb+<4NM0&phK)`&#>#rx3+x3XBh_e4%;;mo7UxM-C~eqx~~Zf5R{8UTP^V5-6K;7N^^oQ73t zJtU8b;Do102O50h1kg=SaBD#-Sca|O5D*Ho32oyksk;40DL)={oK3EAr=+In0N8Hq ztL>}V^~j6y&~u)WT3e1K3Lm$^GGb3j6E?ey(rI+!by2d{PlZ>7N8yMu3p6}d#K$-S z@Wt)e_ly97>lgI$ekj#epbFVs66T20a4LKNz=~<$Ti=hb{Bd9lZ{rpqjMEh0y!wEH z&q!>Q=#6g!#w4Ft7K=1j;P?dG$eS1Jk@^~~pjlB0{u7^BYt}|o!Pv;z+LXwPwS6OhskKGIwF!~qHKv%!fSiG(&n!2~>3L*K zZA`>i8y~q?L$7;S+AB4ln2|y7<{+NQu5Bdn$|xkpn?zBv745zSr@IEnkJ4D=6!jSP4 zKBZ!eQZ0nAR}eOHF0g9x(1^T+EzxoiN_Ua`Bsql9Stl6+vEeGT@5i{kWUfETN%oaT zMU(RKs7g{-76qrq@+idfY`dV%YFL0^P|!Uzgf)9Ld)Y?=E0aY|x_=~9GP-=?OBReQ zO*Mvce8DILLhDAdCkZkJ%X;!dX$%!9tYq7VQjJ)~Lajw3d}sVl6iQ}&DD6VJYb|Q| ze%*eCkE4aI)mrrO2aOL>QhxC%Z)+?%d5f-vDGk_jn@&liJ5{5cX5i!aj#~yJMcAR+ zLA1%JkLHwA3x?Tr=(cFBzdR*{6Z0uNoC!Q4{YI!utxO7R-MM4Jq+mBpRgq=!^Wu>;8zl?6h~m)SdT$g zA)J-uk_GvezK9MTix|UM)hQEw0e?ebLkbjvlzU62m62nYH5TDj<*VYs0p$U9KotK9`R%gC?ru@GTw7*AZOQ_X_bW;pMb=%`z-jBUri(hirZrvPTi=_E zy{zd@hF#Vu5jG|kv7_5+gj|fn@oDALr=`-7$n z+4UWM+_@HKD~5HkM6y_z24^b^*Ce@0^fsW24M=5*lH) zOZ&LG-|r?Hn7~rC(CmTKauib* zoN}Hb`|>QwWJ8`Mfh^6lc*x{DOBd3E{s?)NZsgru{Orud>Fv3e6cWs}Kv{gvIGR-5 z*0-7Z%+39b(n30J9dxVzG<>?NKvd_(CgOdB)>#LVhjH)*`VouiR&3$}Os>(u9s3o@ zCP^bU`tL$keID2D2YYWArqEGX!xA|C?#)Z5agnCQDdb^2pVV^a2=m7rDRsx_BhM~2 zXHnVM3ifWuW=BBuuoFZNKE!$Z6>f|VLuZ(eZOdiQ-#rL!+A&ageJeQ(4DIdU?Hr6K z>bU6*(jVi1ig^b~tRAEg(%0dbZDbz3yNl_05zm+D?kMIihJLZW7smzugJ7E>4>% zlXW+G>r!T;2E#R&(?>hiG-)vdvmz>jnKXmrKT5i=r!1o{VPO&;PH@?29yn#T205YO zE@+VpXv`8D>4~@`^t3**V?qKw2t^(plw_a+aunndeiQcEqa~jLf~$K(SD`Im-h};> zx&2FGzyvy*Plq?hVE|*R08^sgqqRmr%D^@{J36#=N4JSvwk;IwBm#!jh_q4Zv;1iJ5jQ<9!k8!uTRT2jTV4{JZ#->0 zjVq6}BAo7amD zCDa|3#NKLRgZNLBTEVT#4c1l}?=#+qTx&&|3+0(8J$Ii-QUTHwV7I|9K})$;q~$;r zV&rj#IHar=iAHF!&1l23hG&tqtP}Cc1`wan8|zqDIvS;p1(p59sE=03u%Qx)_{~sy zXA|9x{481X_~lY>%i&lqlb1H9F6YSVEiqP@kT_RM4?89#3mxY&sLX{h{})UyIXHY) zGLcv&82d$)>@#^JPEzwMEK)T~T(9wI%hz78nn_s(w~lP=$?a&lngQ`>s>oG=zt_(2GyaP1&GRY+2O&I*rus&Ud%8w$ip`C}ozaFUZ zMF`ASfcUoE;Y!jsiOg-(SjnuoXdTH)i3U;{T*MV3+!}7iOUc|1q~M^L6BR||anS}U zf;q`aZ#3vb{828l-5afgUa2pfi%^VVM3Bx*vG_eH(W;J;T27Zm zW%8~2E)?S=n)qlrSrr$pOcLA5EfK~-Qx}8Kn{GHMNPunuWl{9L=K0NGuOyZD)&W4_ zjp0s{jA-s#LEb!ViSF}NTXCttO)q$XqRc15ly2894(7*cfpUA-clBe z5-k?Dwo#*@NlE051sW|auqVyyA{XML)zLQ&pFBqMj^>??B+@e>I-1_Va)5mVt*0M_ zcvyg$h3Wq;sWn+Y>YM3Sq$l zEfyEWDTR-*8HQQtDd1%2hQ)ym%lnWj*Fuw&4_@~u7=K!zh_3`vCK=$3k1@DcgDzzR zxWj0$>a*Mtvg;FrjWm61n2E8Hl0mZ0z(}$Fw84P*g9ca2j~^SN@zuCu5FPCda0ZJ` zL)(p8?BuK-y!i>T6a>@3EfMvSo-94`*L0XZ{jS z69?JmeLXnG7Lqep6?Ss;3c@Mfd&LqbKdw5SBFlgY;b)7f+7qg0CI@950c zk~Q1$9Y?^I@qNpPUkobldbg0<5K6lQtOUd0%j6KE09^kFZN4AsV1hNS1|CQwVSz}5 zkoqq}&ft4|S+X17P^yqYNrhP zg^ba@zEyXqsSwj(Ifsr5s*pgi-a1@-c&Xo8*g&U0#bL3W5*FLCK6(LV4K4JgjHvK= zi@^UME^VmyyHZdRq-L3(e3c7U)lYI|CN=zYNS4fIQB%&}0ua&r%6#w!&d8NH*2-)SE%o6jXb1oi37+d}9r=2^%+W+E zU(hfoP$Nzs%A>UM1-H&E{imdKnZLu>W?t_B@cSHpgu<-?_q*CWx#VBDXH;AZ#%<-a z_?JwnzW;%D#{a+>m@X`K=*$^UoDW0Z!}e#p5hcD3)+H}g=||zveG{zaJ(()@pyUxa z;!P3WhtuvUC_N5A0VhUWS_=2xX$U&fm*Z36Q0b0YMQ1_;^>AZ4+~kRY9>Wu}joj_Q z9<6HrxxikAw_z z$0QYqbuXa1%l+70(jdR-@ZLHL7|Wjlew+?Go(8JJ7coUr{wurW8`!EJ0-CGIc-v-DL4G?U{!Gu7L)Elj2=|KZR_Z>7OlS{7~l7t7X57L7!q~|wPZ-%19*ZqSQ2;YcO5ge_ru)kBH#=;vm6)bc2K{53;& zwqR(cfQWZtxB@s9OS~nX-0>Q$*K8%Z!N6-;o^-|dIXQjf9+DkIzRZ}){(_+U;t4D*+^xO9Z;4JhW_m>$W+NNln#*0SW>sq>>|1$Ah6r_7=ML>h*F2-Cqd0PW$-LfNTX*dB{|0suafqF3D8h z5#UM#Uf6P<CfkzaC&`!;d5f~ya}U%!31*DA z{p(>CJnfbPC-9RsnjDRlPeG)`6VQG@AxwQ&CWG8tg%9y%5L+&RXg>h*(|73kXCYnH zLRxWSM7#q{-6}~1l))chEAa)$3dz-_Du;GL5I9nQ2#%Qg6j@3-*_B~7lR-_Y)R>VC z;9&QM;8wYge6Um%4>JpX)+|*ek*cMtt|Vuv3Rd=|szmbh5-=!zv_$11dzYv@Wc?CV z0%@c_6PF`eq7OEbeHrE`vaLxKGnIZHPB3F3jNM*xa zS-M!|h}^x#80(UyfT=aBzCKtn-$y5*aLtWD8oE_hC@YNgSkomEy(T&G$$kAJ$L~vt zY`aevX}B+eylQ}x@1jg|ESZ^U&LC--W+nNtmpPuiO@IE{%j_oWdtoM+*UQXW(@6Zi z%=!UtSqeomb$;0RK(GN86n}JnbiPBDV*cIb(hAvKvb)H)8RjIej;k2{Yi%Q666U92*ZFW=B;BeRK3 zliOGtL;x-9ddy#%zZ8>#)n(#N*mBBpiYAebZ(zTM2iXWLum*M%d6^h+&85V8OTqqk zdG5j~MO$Q~uxCW_i5?c43?SL@#7G)Z(xM`AqM`p9hWqCEMcK>o|1tI*@KIFT|1&!~ z+e?z|*=({QJt2fhlTMc21EKdNS&~SyffOK!#vouvbb&)r0a2cUw1*n$-~&_?1j|o) zv7^t1PklZq|L>jIG+rK`e;n2+ckZ3J_s+fNp7TB5^F#Cx_0MSy?OVw(e@w^5?s{S+ z^mcgP(4>`)P~6H?DXzJENw?D0SePxRxZK+pq+e(Pe~I#v@)Fu3E%efgq#B)Y8HQb~ zBV$x?0J@cVS&4OF`7XbPZHyi6XHE^xJ;+s3k?`|2cO?x_Y0HTxD}yGyDX^vC{#&Ax}R-6a`P^&MmOEyR{4re!uhfB3;l!7C69 z;8kUir`cDF%`2w4|3^x*?;&ih#7z3`rq)yUM-quRr9%I_*2Rw5H1Vx4?Fe1h0{0D9^34^N7UsA~EEBg40D}0ELQBek+!6Wp^ z)~Gi0+SaI4*$lR0D^~XFwniDTY|ly}c4+dI&BemUne0sNDE7~!gReo1>%SEe<&UpL zb)>zoMYW^n*tyErAX2(43OB9!(3C(6K7_4C`W)~3(8Rt%rzwxQ$FMLK1@C7rGuE0r+U6Und1Ne9nYv_WLCKgaO z8$fn8SadmQLP&Nt>gZ3J9IW9C7`>|t0)e>{yDh4fL}n{OW)pIu*d4%EajOt{`v79F z&cx!^Awe|OVPeYV;{iB&2j+9 zfQp+=9oAUuPK}Ri!{dYh1gn%T%(SvxmzSN^{)VpZf=b)2qzB4cJ=xe8NFc>H`BIHc(Bnn3i&9F5zSi0e=wl z=Pt<_VgMlw(A|>Brb*v(hz!*DY&HIdAu3#IeW)Nr3%W~gvTu~xw+365nAZ7!yu!ee z`glk6@q`dksI8dRwLX1K{Qwy*z43;I5J-rE^#4^teMBX*k5a_6wE7ZSE&!2cuqBH% z|FiZRqR$`zO=EriS9R3~MM7MpbgS^jd2TKy4V)9hP{ zEkR6+Z=P3GuraCG_Y}7OF0U%+tM<>FiKswNVv9ljTkg!n$5?%yz}C`)fzi{Cm9g3P zIJTC)z?=$1J2(3t!-k3vLh5?_WMk@6wf4lOKu4CE zhA)XNqt6$|ma2<(!2`?TqO0E;Efjpz?xAgqW83R$({{nj%7Yl`6tBZ&dI;LnMGxB- z(BOsk$zFMRpUw$`6@3vz?Fz!E4d$K`)(G$Of5C`8t1k8Vm?^xvw)diWUZ5;~ISt~V zQR`w}Q!i93nj1c2t9$tY#XA1k=ahCGH=Gkjz*l0WqAmZiunopK1NV1|$klc*Pul~B zvdr*06BTx~m&r=y!(G|oDv-rxj_1ej!JD|?>H6Z+kHEA8sz%DSUy)r388y34Q`>rJDlJ0OCQ zzptyIQR^Qve-9cp&K2K1{EYqqP-EBib+x}EM}GVsv}c;zSpPB-QL&?6V~(sZ;g6rR zM}fEY#MeJ#&evdFDDCIUZ2B@R;ea&j@Ir(mq9d(y;mqrrF%IJ zx^x?qZKdh97%BdO2tyg{BV82f+&N~hzt24Ru^@sox!m=m!c`ILyH!_}^*xO>HQJEl zCqGvD|CjLo$5@=1I8WDbPs=%@98z!lf9j0VV=jB_J}E&$V}fitP^B?9NfpBjh>WiM zKfa4jI0EB4C_>f)7&S!jD*ml_7x0pqu#g(Dtl0qo+9>$s{K3781rOLkpq#r5h?m$E z9EY=&uDXpQm6LgR2z5=9j_ILX5bXtDjA+yRoSGghH!x44Ch61^*TT70;M-`H{cQRhlG9Jsa17gKyGIz`@m6X1@%5b#Fx^{2g|~=vf4-uo-Z$ z10WzR6#frM@g3aWfPe#w%3%dYajl_jkn@Z-GTN>F@JB9H?@;fct+SPBjn8Kuju@pZ z23(ddtNsob&8h&n4)5)uH_Mfg5dXWnq{q_@_0Pn@Q5B(zpa(0I3*|DuM44FTc1@Df zz^$_+Q0;|_QF&Rp=RMDR^z#U13Qc-3!Xzg*j#TRE;PIt{uBQSOHmF=_?5`6}%7o<` zgxOf}YCt@=0|?m(ic~0ekMirFO&tW3&+ib%*Kk2-)jn?O6H~$#DAMESRNGyq;qY-p z?0J~`#7W{L>Rycr=jdAqZgKl9gaKOh7M}j}{Ww?rmMTh_Bz6VuDsIybM!d_QI6<61 zW_HJW^X-vMu1aFHyTV-|-&;E0-sE0mKR@Ewi2cR>Qb%Fgkz>By0+U`>m{Hl`m(_MV z*zCGy$%lWhhJ6rEkwrDTRUVxzk%%+I8SHUe(G%5n9ovJ~d$qj{eKOD9wMid5JP%nn z)VOVQu%s$~X0_LcAgY#kE$^Z?ApAOBHdE4LyO|#QJOjPH5-f+@?OojN2Vr?zc0< zv<{(Dn;dlSUZqJWaukIoY>E$c-h{3kX|;yZH|Irfr5=!88$&BzjtkAfzez7ghkCsn6LP+s8v6C6q|niq z+Jv^e6dkI0sdeb=-%@Cr1<>^K8MY)q%9Eh2YdThrg-^bzuce;VXV%D<#$f5CV}$sgMO8e zMOXK#Y~b?^>wt`BjAv-tETvCX9&q<@_n~L^s*)+VSCxqAtdncyUX_Ci_No9w+^f>k zjXkO~?ihX?4AGEji6cRm?`qdGi$fX%)%v*afBvuG^?R#4u+{i2*|Ps zSc9Ix0{%t8}XV?}=&Z1VOZ7N(>9q)WbT52U&T?-8y-~&u4tq~`700HqQpw*T zDv^42fUDw_QiNA)+X2SBKib3ef^&BIzI~K|R<)1nF2C;VwW#!28zLg;(pr5hse+Ap zm44XS%3-@d=shUc&z80N2r6BxPo;rt^@(yjbX$w2^0$ZF@$nj5K%FPi(lvVN-Mlnt z4bo+-(ZfY`jozV^r;SKeq@3ShtC8P3tM!n^SX=L3t=Gx5ylORC9nG8|!A)JuQ$cMqm6d7JXkLjn zol-YMWWudKGn*EaXroQwF~Q6_6li?YQqxkF&Q6Cr!HkC{u+#IMqD-vF?liI!S|pDHuiHis}AJ{kQsWrF+bM zfFUaIO3^rAeXL-QXs67MQ4vsoW#Xgmi1PIvVUSH1Gcnb$!z&$Nv)$Jr$|wProy=k8 z3@Y_m_~{RY@2Ot#wc;qS=W{_>nkvl(e+Mt^bQp|HAp3lSTZ9|N3K#hw7?|IVp`>#r z&7NV8rTsJPs{k6br=m_eCsB65?zGm23F%W-Qes?XT$L<#c1u_EIrz}aK|XoRbBw0F zrHrBD1$HyNRtR9tjr9=>Hjhf{8`MUU7(`v8f|9~5R*G}d)mPXa+6|HY(0Jy&ApA~- z0!$JJnmU_0Q)a0)POgRQQmw^MiWUvdEUPf#KX#X6WvLcn(pcM^FVUK$W~cQ*ZClm^ zb~2P{qc;6)QFdjDRwvh$gTv1Kh~t|MpQ3l6e4ioF7<_|??>VShhXImwgF6Q!$8zxF zj^nxtSGaDee4aYDJeobq-n;}OgY;IJOM zl{Qt1*g2ku18cIuZh$6jR#7z!=)vB-Y1>;$kCqv}{D#Gb#q5yLb#!(}HL4w2T*Y}=M@71)1myvI0j9)=wCQT5S=CZnGV?TlXwEr?e2 zP|Pl;hI-Dhw=rQ*GNC^*@fID9I_yz;d&(mfe3#EbS-Bcfz49PW2#9I22g~Z&U~x#1 zg3IiHkU9gXJiCO;euZ0zm@7T`(>(RoiLK(jVhY^M#(+ejs=UH-(QOW6^&)yi^hgv_(pKt32VK{SfZ%CG$keQs%{oy-uWH2v=2%+@tb9br zh>pak)n6K~6`A*KO15-!TdioKe`&<_v`iza=rg;*DCDYhY4#ojjm0T79n^>hdO#!k z40$XXFbv%0tLCeigq6{zp;eOLGo7E#o`z~QqFpb|DzN50D?BSDqSJfP*stwXCefqV z)BCC_nY9tC__%^bWm>v%H6Zwv*`@#miFzzS3!GlFCHk_%Bs38Tn6B^ zb{6E>H=)>HK~Xm>wSWz|ga#E>-HSIYQv|G?&dWOF?U<6sA>fP#Mx#Aa5S%{HApeF5 zc^!}-!z8%E8RWSd&ZHB-0(XV_rDN2Vsf4bCQ*Yu)8Hjzf^5ms8iTBTP{F;9`K-C85&~##%!)2V+D0!P{bOTCLYhy>@Htp$Tusg|6(Y*p>78Exxzx zaL^U`8Ept*^(y9^zNp|&5pZMyV7o~G!7{Ngh{}zI=HnQ*maF8tN)RLX#CzL|-P@6W zj}T3xcMHt5TH~T)Uz$KGZlkkLTA1gG`iItHMhEKJDcT)1vI?wC1@{F4!I%Rv2XO5o zZC2@+Gqk#vc1$(dsA7%~$qpZ4hpD2vDqHML{Cn{KKQviTQ|46pav>dDV{;h?_^X1I z+DTeCYOC|9?boK(3iULa9aN{Wf+w@}3H`jn=`=B%TUjYyk3UDmnqiNp#( zV&qo7pnL&W#!$@`yOTb;X|%J47)?*FP%%do^(gx3x}rVX8%|Ssy|g!&);+C=rQU}X zR(2t07ee!hp#`cKQ9-JlWKbP zu)-j;i*6@pC7n9qG->F;aR9UqKCI9R8(bUMQHGpx&+(#2TP9*EM2X%eMV#znj9}kG zYLjzQaSj3o;*>})g+mqf>VmMn=+ZP|JYH;C7o#|4K%k_Q1;2^z7u`=*?62X3>F~@G z_$k~PfcYnKx6rq{a#>j7yb9p=uK*x-2e|4r#RJ=OB%h!Zo}WB<`#`2plmTJ9nRfPs zwmf$v06n+I+Z>9{JT3dT>I0hehw3HT{JZM!AS+dEqp82Co`;I*W5{*=Spb)Z0f6o- zSV6k-Ekk+6@L$;2L_3G8?6mNtzUQLnVq=RvcT0?rJHV`4sHZNs#Ez82_AcEN z0ieGLEP^y>zHk#mA({ug12-}INki)3n<$$NZ`alPE! zmu^4=YHXj~Hy{I{t07eB4KYg20edQ?`jGmNoHgsNx(R{unSe;gXk!{qYRo{W1uETt zx&K0ys1TrU`E47w)FvYkBf$wU<p8(T}(%se~*#;ZC0Ah<#E&Azv=d0;)X zH9SlBQASn;@ECR2S~5`Pq8Q-1%E~ItzBjS8gkC|&!D1;G$rzx+tI7jr-y7Ikdg$C5 zDXH1_IyS^CN04O6u-IVH&GpX=J);*jlRMa6+^1@7UUiX`SxOspSwU zHNKq)lhRU#jbT#|Ii)45ZbQTrJX}L072oz&Vp`mPmt80aT|saaY|tmx+iYtZ-gIaH zX5p>a++tefof$|W#1Tcjr8*p3RwXt37PD^)l#&0{o`Z|3f@a@lY%N@^2@VEvsoD1` zww7LUu)nkveI}pbZNj*QSIoXwpghgK^BJ2atp_*!&FuSIQ^B&{P~VWY2KhD^;y0On zo9>z#i5sl(FPnWYw^Y{+S(|+?VQUG20oH}-#mEcGeYldDeH*c{6^N6GiF@JLUIGW< zcsT2Rj9`I_AR^zZhywhGVb#kJ49F|3o!LBF2r=;z;=+$eb-;&pxJpNxhN~vfPv<~W zRp*9pcbOY5etgRr;z#F*AX1(n-UjO-&~q_v{LWaauxZ9lmr@-LR#X~$;EXyv*EI$88luXsK@nKNkM-Z@hX@Tl zdj|ANV=*3hD~lME5i9%3u`JFJf}Fp`hH)ob0bRr}{sba*_W~#BS8!e=7~mN7@Ats$ zZr~q;8MY$=b$<_MgBO5#&*i2GR{@M>e=(vPirs#J;uO&0!8MsaO2hl_oejd|57S`Z z|EEIK3;mt_Y545u*3@QpbUghs8-C7lv!l&4A{{Ai%!<~@X`h-EZRG!CiCiEHC@gj^ zaxRk7Y|C)KBAekzVn5OP0LIets-Sa)a|Oj`z{v+Vmx2n|PhDP@SE9yyC>4I1`d<|` z!Q=AKx^xG^r?JO*D%}yqvP^&}rClaT$-1XItTMlzbZAb;t$6knIAbA>EjtHYdr7&! zDCoTIyw38;ke=6+6D%kyFD?xhmplLI{3mrxb0oN#oTCP4PnZvAbP49TLEH`;*4iHL z08}~FtGyD%SbF|vm4)6+5C_$*ixGz@gzCq$=$TeJE44lZ)8VE#*rQxA;u4?SKt86t z+m40URN-FadJt0V!)Ty^5>wg-Xdq@MzZbLYk8sT*ZYJl0U&~cMM3-~3>*mLJmsOEubBQ0T=9*S)TL zS=)n}1a+hWPG0D#*w1eTK)i^j?5TWf@;do6^R%Y{Jczd?)MFkbll8cBF)sQ5KTXjG z&;avOo(B2=sq68S^{Ly|TbsW+7xQ>s^4XXOm>$=~E~Nc0#2!wSTgl1s!w?+UDa^v! zppyTN<7(ZH_l2zKaMu@(5O3Y7ZFIA^ZBmps%j12dg!P8?HfdtF`XZ5_D;&?!` zdrPV6(H6+AH3gHD_9jXD(l0;8JVvvBjHyx2f4o0HGjJl@N*0Kz2Cb z#QTOWnjZNfrnJ#Z=&D3IRffPC*%AliVZ{oJAH85W_z{Ftui(RFA&@mt=^lcdJqNOv zB2(-PVjwuPReFI3t|~0c9Of^lt!<)W>o&ECn!wXQ)>F!?>W`_HRh=d4R)4XofwHuz zf7vv^s_e^#E;rYgLxi&@VXPhr7bOF{K-E)L1-`{i=e6U_AB( z0+l5J)qhm~p||vwR#dLBBx#bw6i^|J4bV@^tZresYB?pH15@Eot>L`-PV1<{@F12{ zKC84AS#EW5y_oCiqxhQc5p+;v*1_D84^6KY%pGq*iCGAV)d{7>X^=}i$`yd$s~576 z{+i2n6N*7vQj{~l*xLsy+L@65`e17@P06g1Dt~@W5tCJY*qVdG!Wk8o_{(M$mBE?D z?90K{VouYmD=G?DG%B;N7q*s!*71-dgKVaj6f9=nDQpsEt>z9nQA%j`eTc0A8Q26E zI2I)72^srYV~zFKgj0q=nID*aAKW#^+%R_Z zeY5ZVyCwu^vY-?a^Kon~7cG@s10W%qpvdfd4_hW|*>{R#^2>P3W_U*hN}&X2{(ENM zyVzP1-WpTqmRG?f!P35i?SDNhf{(GRL7$ahZT20*){^wtnClR>xT{3cquBoUd$Bwj zxsKU)1lwJ*tU0|jV8sFr~tF?Ft-2o_JQ&m z_N4v%n7z%uL)h-}s7MIZ0T`k1_6M=uJ!x-9^RUU8eFv~LTPk|P-vFx@3Ubq|4|JQL#MOz$YD1GK?P z#G8x|B80jvy%1*s`YHs7`Pe56Fd0EM=JQYY<9bCrNABK2R(d25|2~+^VHlEy*!!6C zFwTHfE8hevJO?`{3dHuJ4Wq0!V9MDEc$7sy-?;l+7gru$XYtexMR|?b5jc)4GNmykh{OEAg9Nke|JLbXjSja=z&| z7CsXKQy4GHL>M<4a?hb^2-T8@poAj)D&GY4atYY*Vqw(14DS{Oz8?$hfE~z_Q`|Q0 z5h&z(@p~yU6ZXty)76PoI$a&1VUD!Yc)xeHHAZ;O@*G7>SGS_?{P5j7?pGtwsUMTo zW9%@;ueJ~fZB4>+s^{2IB8|vbTTF7mKc)?bwy8VuesvsZ5L1|-3^yUXXK)61z5}@u z>)$HZD)|vUou-bU=ccKXfuw>H-}-54J1w22PBrvLOq5wL8-e2ZdAZCiy+xxfE5NX* ziUTGCJF05|E=WmqVZ6_7emDL2n;Nlkepl<+ zULu|R4TPGFH@8g@4C(TlNlRwc}zJS`WG@7_M6(o_Tnk)H+9^~-_%*` z@{E`nELTt;{0mvvbIFd18AYegf}t zAInEMXk#cQ^Wo5Wf4NmBtX8ciQ$D(g)RAtX57Ck7>Xd=3W4gfO1J}04LBZM+&ZL{Yq3$ql^6snHTjx+mM~pT-GimRWdto3st2C9Mles{s)LRgf%lSh zcsq^AdOaLsWaXmtq6>_6Lz8NlWMoVhEQ1a#16HYEsnlVG_Zn+a2Z5>5M1L6U(Z*p_ z!RkP;Dwwb4)jXXzgJ{kTt!I(#osywQ^O)u_i2#$8XB=9L0am?UyL}Tk#V+WF0<6%lY@Pz0QxG`9!6SPWk)EFJ*)*=3VrDM#`{_c|f$!y)UE(@md_iD^Tl$HYvb=Qp~# z)$Qpk^i$9a-G%2Ry1i(ol{g1tl&6Imh>jHl4EP5i8L7oc-&5hi`2Hz;{6nznk3a-R z1+1;RxTi4SbYt)}YHP7Fz*Jf`c`Z=CpNs&xIL@i{Ae&_#(8{skmaUDly6O8UiGw>W zOHTQAlr@c>i?Sx0fXl0>ENA)wjOz(fA;^fNR2;byCB0;y!kaYBI zB$&IgmmuA`J`$|l_eFxUdq^Z$xl<#piPCuoJC6skMhz&Q?=OWw?*%JdS-Img$7j-c z`q2Vr?u?;@)N8smM1T;Vd0${P2-$h6+QDsux zS*yD)eue$Af*v?)&4dLR%-6MNtKN%mC&&43wum=f{KhS)tC=0 zTf&cDr86UU*1a!op`TvX#aZ=_ySTe z9j3wK1mZvw@TM#=^z0eF^F3Rr_sfxnQ9!M$UsJy(^`^`3I!xYvC4quM#x(4B-tm0s z{JU|X74HuMgKV1Qh1fL5Joxoh23%WRTP4)!!uP=rYf;2W1<<>!=ayKksh!wJEyY{@ zSa=cS`2!&Y-Q9C&ebJm1rngORv$EXOwr8}8T>o()jCM~D&!?Tm7msrqD(;COS2_WR zyxu(#uu9((YP17Az%jqHM|4~A_kgYk?<{4YHVzF03ySk0@L>dm)wlk9Bj@S^iU-); zt>~}r(b|TR)pWc&^mNFq6+Pcw3XlidFsTB|x+4ymw|jJZy4el9&Qg{?^hA^~RJWUc z>IR(dufaujapI^P4nsuZ4%4(=LID$BThnC&{D z(OIp83CMcY0LXP}f!58a&dk6C0(s6Zc6mlqLR+8FES4{Vz06E8&uC%^dup2htR|U; zJ*!~?56sd#pV2tz=(C!xO%B(wBo}6=H0m{qHI1nXLzRGTlNffsSmuZa95q5&t z0n3A(L%_HoXfOPxW2R%YJ_ML&_Yjbyc*abdtY7NSfyj9Pd{_Dlh0uyqWG~e{F}1>y ze3&*H94O=wh=&#nge4En5K?K-RZn!ieki9}NN~?xGF`eO>`~F|jzi;c$H6L%smUF! zB82;v_@!GiSYk+z2j&ay=(0m;Y2Z|p$FW8h#)>7=q&t9OmhSlFh{Hl#D+Dj~_(zN> zlO?ZbSG@Dq?2g{j;vn31D{2#$%zzgfZ9Arlt-Gd+b@0ks+mZr`U!=8C_tPpk;LH=| zV4=d$C4k$#4qj2FzRCi0>8fHc@MJ+aJv#VyBeG{?WC1GA!IXHfp zhGYV^yCn?zXUz=+3d}XW@n+xn=IV!LWrOaa0652b{mnSDZ(K{dpzte!vfJz%i>aCtN`I3^US;>O}a|0z(?f6ETeIxHucKqywc_NofGa&s=QH z($$2O0^$0@LU1la{rQGtyG#FK3r4eV7`D4qbnmkA3OpMq4~8~3qBVKjnxMCLS)i&M z&o%_x|4fHfzXV${`vzlcZf=#c>kU#f$eCu}AZ*RuQso4`s{DL3(?D#EY7xo#I(!`y zaAgToI1a$p+%gzWQR1H;05G!9?CX!M#X?xPP_wTeHjEOY(5$kX*EN(z<;6A3k#;gR zM&=*Q0a^MwR3c7kM7mWSH^=Hn@5V{56ohSh-lq1f!hU^%O$Hy>J6 z#h?Ru{`~Ud8Ir0H-)~tX00)$pMJ;u`fiU_9i>HS_S$r>rEw$o+ zs=^wCH=XMp02NzFf!Q|$TT9tfkdP_|c9w^7p2gnrfh1T)kWt?PdGqZ0RHfc2Y?{A@% zzi4!6K~V|F4$VG%G1W|5QZZwA1jNB75LjUYMRXHW%z?$@q$OFs6jQ$>%ZzX4U(B(! z*sR54q_p*J$hSVh%5C2_imV2~=u?HwT)B9Zl&apoSDz}Hx__Z?HBCy@Un`brYiBPW z>1As>y4pu+sq04DZ$Kyt?xvCx>zy99(b5`+G` zx_9a76)gb4SG0-3?1KVpT%b*rZ|8BrTvUc2yX8fQhFl@MC%h*M!BZd9+Ms^w zWRr9F@jA;vpMxN;V(kqq*|DqI zG|BlcmK(x>@o+sr*nZH8c?Ax3xqa{lU#JKG50R{3PIyP8C2@r$6k5U2@+lluR&bTV z7q~h6NBh6lrBcn;x_FxUwa!aDzt*)kG>l9=%{^Cst&79DI1auDsI9DvHyE0^$YkJslR|v%Qv5Ey>#?*Z7bUJ zxi*d-VLyfJT))q8HIZFd|FzCDoUMSJjLYDP1XZtPwo9ymKLAqlQN%Corf>jHcT6HD z914T$f4GmpG`)x$4n5ZwK-s+kCYhyBG0fm|F_C8Sp_$)x2=)CgIpp~+HFV;dBV_o_ z68i93a%jXgd+4oeHY|@alR~Gjxk9V2#f5raQ-^}rOrf-EsiE87riadan-bdfZ4!N- z3soKO+|6C^xu03bTA5&c4{vG8X*HAe63?h)PS24Nh`Ksb0e z_;_kHT1~9zW>$9@B?DM2B(5UwSnxQP1&x0g|DgNFz>}_cj6TY46Wy>wgj4o`5hh?< zZCp)l$G~SUa*RIi-ey_#0m8I$J|^q_ML=yB)*IG4MK^c_!uR(EcV0yWg0HAeYT7#* z&$@avd33 z5h#Iw!N>auVD8U?6HE`);ir5C&3O9r&{PzU^kVNZn^|k@A7?VL% zzV!P@m#&{|TZvc2Q!gCTiQ5JQ)Vpm+1gI+sKDI2ibGOZ)01$fMZQ!=Nw+(6Z?^}jc zdi(~c5#PLppC@h^GN|YlC=>_YGQ>ITq8s|DaK()c%&eLb@b2{PB>OGgYPe<4(dC;4 z?>%nOozReMbg+PV<}rYo_@ek?v$h-MN8KAY7&p*|i5i=5%5X~B2|fC423<~s7wVO< zdT;AyrRD)6P*~*I=h@v1BpC zA>7Ht60wB!@UWit4YWfcB|$LM zsSGF*s=eW)bsG_{XW&M=9&<$Jg!)tFkpET;Rd29IQuYS8toKaTAjC4R1iFvKjiU2_THWi5J;rLvgoG1uic*|q^B zWbB=cjl|Q@h&GK=Y1H#Yds0K*rXgS`lmo@P-f+DUioG2}U%hD0Vbu~tvo_k{pp1OR zHKP3U+z6!lKGd4<048{4_5)4v?+_zifFXpfe6C~sc^>NPet>oTz#WBcaSk_FI1jJj zM1>jd3tu5@0Atg91`)#x`H=snv#yWNwS=d2yeXjUjqi-4@YH?fy`f~#wNa8pgkpqUCIG@W{4>eLifBh5;DgA_a&=Fq% zgnt=~=Di`U{Q(cD?LhhzK-cd;)xU?(xz*eVkSX7mm~lUVIP{A2ltq}hd+~JY6_=e3 zzUop_x6Lk%@P_J*=BHBWpReLkV>Y|IY)?;^y2F9en6ftyb1aG4&V|Z&=#H{<*7~a6weU{4)QM`G`s!&Gk ztTIqlVVg>;j#-lws(0z&G3y)2c3f9n)Cn#=JQm>?Cs<+ZM3H}vzdX)MYu>SDF-Suq zop{IU9fv{`EJzT#+@PeD!bCOT9pzT;NtP-g)KAawkpm=HurEdPK( zWC6NMIzkp)9?f73deq=1Qk~A?{YUD5aB5M=E=mAXNZSVpw5V5ie$XU^Ihg z=hKl&J!@1uAp!v$h*=*hiiCS^TqHa)r3)WeKyxB716;M>j-^pbBkL=6V_q>rDY8Lb ze_el_PDP9p!T;*twnP+{{O}I3J?JQ}TuTSjIoI zTwaPmImmAyJ)Q(E11aZiThPz{wHa_fsdt~+>_RXB*3Y+KPhv{4bKRMt;T8CJP6lF4 zDM2S5f&WS?knMhikL!LAQnvy};JY91YniuKN z2d-#Zb`l@opd6)aJrFA0m2{$)vNf&irEEiSC$ZKUlBCf>yzh|3ZubzKbeV+KVh4JL zy+G~(rBcr0zLPG4bc0rQiCW-Zzz)+PK6dcPt#pbd`Qe1?9(w8nSG$Hh?eyRYmyIQk zCh>$TTj-+d!pe`P?I$qwNRRpZNf&c<>JTU86xny)EKI1-+=`Egk0gj4T+(S!X)uv8 z)*I_>{(u!pAay`K8U0wFb8^7YUY68M%nL}b_ztU!XRx;Dp|Aq!a}@T6xzf5q53J;2 zU}#H#p*;x%_G*YA(<`k5+^DM%> zv`7EJ)X6 zPLQ90>)8S@N(n;XTt(EdS+H*Q;9EiJ`vD7Kcyx?j{XW&{reYM9X>VpYup zz&i*C(ugX5fq#yAmwFfdZ~^xzYrW`fT|4vWBf#sf3TOMd75}m24zpjnaCh($JV>B};+s;G|0{ zq*#dIK1Q#v0D~2)>nIt3^rY)a^kA)IjisWC+PD~5T>?sniBOfM^J}o)8wExT4pZ+a ziaBHLs2IGJCd6qr)m@CywB_qAI5q#rgU_o`nV)$w#K!UmeJKP4yPzA8W zv5=4F!MOD}?}yPj3BcJ4Kt(J?_?6xum5mcK+!VbQZVso`fGAJ9))dM1KuvQB!rlHg zaCpF88ckV)sC~WGm}1c`%+0uAW$c}pHyMHK3QCISxpUk(^yg|*8hyMP8P=YTw9www zaLjmYHJm>Dt3eFC>r0)7dVZ-(xO250wvF_y4w!W01&2PcGvk_MLrg2jcv z&4IK?eN%mt4u7L#E{$;==5^@ylgaRUNOIdwt+)=ueGLDQp_|Z43|P1`0yrSXA(tS zu_o1Nhw^_YsLf#hlh#+@98ei zR`7~tAe!vt^0=pOu8iY4yKMCW3P=Upk+ze?+8kTY^JSYW7}LI|zL*Z3EIDD#oAk6O zW=vTLyn!)Dp_sl*whtDPI@2;cO6bE)*bJ&;lv7VMiE_Hed*1nq6E=gqxuI+eNp&%? zqs1__d3Ex#bc_4#UiO4B}$v{9Rn zvHCHwB)d*U7HTCf3Qs!(x1IMEX;AO>)t+|%CEUdA#ud=Bix z>t9?@Twqzs?fPHtqFhS@l!~xR(EtnNv!OC+c zP!j1-=`oT=#%?qj)e-^5s6${^c!(Q^y8Z>0o`X1g3e`7NxTfekFP{bI6{AFm;He7(lZPI0JYwCX) zduf-o5p?4cu3lt6`z|5LTKwEG8w@X-AJArNv#IzJTw({Yr0JKmUZ@H@(9zV-8M3&y zj9*6ox~R>h?=Nb#boin+CM!ntKvhtmOj`QM^A{xAy=)9ua$Pv+j!jrNb>SvZ)X&yL zW$lE8lPR;Dzep2j@&B$f2O;!^xuOO!P1RDY;`;#?d`q&EEmu@P5NxN20Q=Ta2+dVk z0LvU@yRihG%?&~v&ijEx8H^fsgQ5RddRgI2p@$XDRy0|G4%klNOs5EiGl9P2ad?z> zCea4onMiYZX9kU6hiSYsl~g>E%tS55d&Q(CZ^imn(>FW79ayo^nN4ke5zKVpAlz0~ z9Yl*&9YmW9JLpKEOm@z|e!e<@!+#ubw4$}FWj|0jQzd+>#EQ+<2TQTw?2bT;4Bfg~ z3OLG$>nWt52V;c&3jxC30QS0&>(W}xhP1j*>#8g2t14B{t9?LZ_Gy1r1}$WJ zIlmyH(=@@EB>brSk?o{XR~(TYKT^nUI}6!;4i(J&LOKFd`vuk{%rB&iA`*dl4~8S| zIKjYJhj11XplxL#UuuD~&BM|+3B*Z%a$kZVWDl51pTv4)LQ$Y7K;8FgTg#CGa`tIs zrAb5mlKCZx#aue09}KCm;vjVTuPxIXgd^r7w0=Lrnkf&Wiyl4zRwVqS&;jfTJGDF6 z#kl&ga5I%NrDN)H09w~b_Vew2{2bg5tPF08jquio9s%ZDs-f8jprkF_uWds;_JamX zD$2YcMb+;a>DPT)xH{Hb^Lm(jP(%vCS1jwRQqhyY2vW{2y4FY4X_(xJE1BJ;KeC^2KR4_3ehykXa88au-%g*XnTyxQTJuE zDu%DCwW%)fUD*gEp-Xna=|2yy>1rVE{sHd8YVi4WQdsb<9K*MAKN>CtgYhNIK2LA~ zc(QioX#01L7*lV5X&^HnR*-<_fad^}Epf*fb0AL4^m~?imO=|g8wUO{MIGf zy3rp=wkWMcRjvC|_orN63sP(mtob1UrhtDil^uScYy)sf%%;PO5v%oLvdu&G+2PP+n;L=$i0-As^kneZ{sN|F)@Dw+l4Oe%5W#|S z79r0ANj6>M(Q`PGQ&k{ULmoC$Rq1s9bie1E=UkJX$fTltbH3D1q`rAG5hd;T7S4VT zU2`O*$gMqvwYC{*wkZf#F$k{v>v$>j2 zkCcA#lfl&u@1fYq*JXCbGJ$&BtN3YCgiR@pb9Tft0ZeQju##RW{Q5?;+i-C4+(6i_ zjR5QpM68`(;dZeaVC+Gl5S6t}cbGY(M$-+3<+s}JdD8PFwL!zuz(?F^q+RTeB%U2! zSmcfr8k#fWx*$eE2U(EPAI^_~*xcCMX4mNNix3C&r|%u20m9BGCR}RY(!M2Uh0`i} ze34r(fK`iT|03AvAso>MkGSE;#tM^CL|+%cVii6Fw-0)juD^dS4BDP)o@r9=qjldq zO!D3UwkM@_fA0vV?mM%%w6w}I&NGgsNvGQH9D|L_zeF-Tc?vy+>{a1U_njk?KD>s4 zJ1%zHC3avXD7lzN2|t}%ND)rkkmTC&3#YKp)B&0eG*3hO;4`fqn~A35Y9}xBledPy zBGyh?I1Q9h_wg25w}4ku&l=uCFZg3#B2RwI7c_D0&#K=G z)}XAbsZ!P|>Tcc_rv$c_8Nc&6ETA7iP^`Ax2V6emejje0Q9A)(I#+zXv05^J8>YnA zLa$tRH5bGs6S%(?2xg?O7wj9;54vuRY9`Q1=|i)Ac`kJD=fC4ah3yH73v1@zX(s41P z6jB$E#J>Z=3qp-BC2Y;T3cA6+A&^>;6oKyscmWPUy<5AAnn85GJo>hGo!k80=Jb&d|3(X&|o~ z`Y}IutVn=J_6Kbyo2l;gbB0KMY`tJ6r}6=35e8b>HrY0LL=V=I_2obz01_h^(_!0V z+v65JFda8s1z(R8->$;;y6trucU^#m_)*sj^!#Jc>b?Icv|D(S)b0v2u?_eJEETH} zHhvBC{R5$W{T-FE9FdfA;I#7vTu-0iM`A|00bR(`+*GbJyNeV3^wkeyD=3D=ak6@0 zIP?aCH`pTe=bh(qwtWwAbQb-TsA=u!U4mHf2w({oU2~2(2N&BlXyO{VvyO|$aV1Mu zg6405k`0G#=t_<&h3x?~yx!h{?X{L{7F745-K-K3z_8x3_U#U}Aw>nkTQRMf_y3*N zCnQJ>t^clb4R#V+Lg$PwFZCCdp!xw;nvV_X67B*&k?o~s-&AZ!YHJA{l+)mhi!nNk zpRDoqHTw|WThukbLk=1gW|=|q1|yHzw;vni^B;lNIPMz16BraX?EUw0ZVi5d8lbE-7d#50rFJfNGq}w^`$B2suco^uAFR+x{tXK*J`DmELVjvuxg@4CVz69a{VA2rk7~3JEAO04CUNIDn{rP)% z4^)i_q9;4F;j|@Ga(Z>hf2tLf)t(MGVcq5V=t({_>tjb~{V6eY^y98{|8*grK0agU zOR;ASy%L*$`vcK!tNp>5{tD+r=S0+mhK&oM?x&p+S|f&`H7>#*bOSIgQzQ>0rfp*o z=Q$8VJ1cBh*!>@#IfQ3s=GWh`cGw2dHpmT^;&&EcFzAg4rCy%AS@31c%TmYbSrA&t z9k$K3&2+mB+}tj)pJiL|9CLWOPAX_V6j9(~d5@IRSwiu^27ok06C;TgFq z6TWtp>}PDI+C!b#RR?}diK3@nVRQ#|t$wi^3NFgt6l0}Z zn-rOKYj!AR2!K>wh0G2})dAr-1W}&?^@x37w;_$UmdRU*#PcC=J4>Tmc+JF@h6Y;nv0YSXxLR z(*=4#9Pl9WiiDXOh<1QD%7MtVcCdD!D569@xT($szD(1oiqp$Rd)==;lM%g zQN2Adsy%%+5Y)cg2ZDX~v4OZcWgvp9_81uDg-1=(nFGtKaM)t&DeI|~1EX5qQKwP@ zpcmnGXFp>A4x6r0Stj6_O@O6A3OPx@R zPRT-0gs03=fE$*0bNzD|NWf;W8Q40>$qiCKR(lEx;ok5b{#Ef2!Vb(w5RNQ`1`g1# zqbo8$mMAQH4?&|)0*U*qVi;zu_KH}A9`K^CV1hbQcj!pep9&g$1aG|iov8kD9o@c; zSQ9x%;U>HNNK~Yq$xCV&ykWfD2Av1-UKj&l$7{{6s57Lan7V(YqHzhj(^u=cITgY_ z;1;IAWMe~bcn{B3tr&;cXN-SxKLm&epgXz;dW{PpJ6Q#Cv0QYc9{fBOnh(A;Wz*q> zB+mnNyY7h|%G05C(N>z*7M?59--F`g@;mVKS@jMAfCt`zLuMa#=zPcCn*Mdno=Be_ zv&YdZ$LyK3h#gKoW{3LXn7u9W$B^XGQF}snj>8Or4mTbkQ#1jb>w|?Qft+A~#i7&u zQ}a*u(kghg2*UtYXb%{cn_I>Qv3?=08^w&Wd4+L1D(RO4wro0k(B@Uws-FS_NZQJ$ zRj?T^hVSt6AH^BSwpi5z>pRsWRAz~LhCYmnTSud!;ug@x$he&=KhcUt4j^hyu>cx; z8`m?G^HM8)?Wo#z-r79;aJ%}R+{^F!^{9&9`0Ei~a>j8oue1$9KpL3-La+&DfV~e< zGDt*Hx6F4s)U`< zJ6D_*lU5GHiPDJ(m9iyzi*zvjs#Pm2buOiy3el+_;Ga=gU05EyKYBlH8?MZv+TqGf z+~_p+2Z16&#FhJ9N|#c~SPSdc%z*Qj^A>r30C(d0Un6aT3z1!=qcR++zjA&hMR2^z zB%`gzENWq+b0a-7ObL$d;dqh-!w{=NT24zTCJ$4pS=KJ<8{|C#dY*^(a%ZG zkW*Dqg!OTW-xcACke+_qP^E#sPt61w9xE8t|XrQLCu!uL7fNy^7Bn zPML4RGkgZ@J8@vK{utldV~T0eV%gBJ?*lNx)UBP-OMaH%KE;6h;Eyf`T}#Mb>S{y3 zl(=jW;0AyYDYM6kUBPB^p$ul>vt_OnX-|N`iY0W@`=u@&+e0X(5?2i69(RJMvTbxs z-Mek0Ej%r18;$r3+0kntPjYcoeNVJoavpVZV>sdez-hDu%HdAme5VZVU?}OD}8!@M*6n+7lt$fdb_bw<2yqXw0C4o@ke8P;qb` z&fSQ(0YEe~VV>w{O@N*GE8;J9UmDhtaO-7hjeP?7VAIBD8}U=bPqZx#4tOucMc+eH z;y`88JubQfO^(Ik=dsu;i^Z*gz;~vfVxwbdqRwDYMEuNN8b;hwR~GdtMcqUPA@ToI z>KaDtOI)p~d(bsM>O`w@bwUVgHW&K}dR9)tV~ zALFK(_85K5)deH&-8mtt2kKA;DE+V-_A$Oon;>As9-M99%um(pXbW zS7ZH>5@H)%yANNtCGkp{X^VMUHc|3VbAa^rf>Zr81qWgsE%z);#vE23n3@;LS%z2oCrg^?U6?Q{fcd@v`{@-a5@m{*l#O|*++Q_4P+sVrNLMxj zoQNNfuw1d6?bzx5$)Gy>d2vnf!&4V(g1dE697I+TQINpy2E$lqp7f<^n! z$xyDJnhbr<*2%bI@nk5{r9L@oG89HJlN~Hh26JPd42XegGSo@^r{WGNNyn*3^2Suh zU`QU!C%yR`CTlbQ()~pzC&8$K{*0Js9=M$znB;)Axapx$bJ=(q)d(}_zKw=N=>rFM zv;xso9%NkcFf*S5;_w+nt>}mOQ&%w$w7EAwbAbon`SHVqF z*~s>x1%{N61z7o=5nB67i&l)lT#k?eW$dF3T5GMf^;gt1!2))FjE$`&fdh$w`8fi? z>`W8@?i-?*2`EbI&;|S$(`MTKZTmM(h(gYibTTVStE8b(S|i23gJG5(>IN4x>LY8i zHJPqOA|dVu>0TsM<}XA-Cy${Q_<=|mgxGjY!+sUCwC6qx!U$MDYCL7c^N#e-!U$s@ zZXeDb)=M`ckO%fM*ud_k)Gbbfu)(^4ma(FdkBzoQSW^4Q;X(T_7lXx+hGDCKY<3!* zZ869xShN*JPO%x(wc{cG7^IjD^&ZA%g@8%qd;UD_NCl1I_8&m`ioFzh?j2h^r#z53 z&XwWHU{h$@71P8x!yv%bqnAZ5gK9dS{Hgf2<@6Q^)*l6sL1`j~weAuP&v;-C#xa_hNHLU%u&8 zZQ(E}b;F{*A#dq{u6?C|-uDiZyuNPPeL&|ZYkMvnNx8MWmFAC*+mb7*v6!=ks1`mE z)=Azk@vzVBQ!Ie!XaHz_Kjivy%-c3;-rkIr-w;KL0tg$p@_h;U;{ZPW7Xb;nA9+Z; z>K=}vul5{s6zG#hRF8<@F#8+x8m%-DH{QM*!AC7 zK%`isL=r3(hy^(HFBZ|Py+ZjbD5#YkS)#Rcs2oso<7}}0V+MJhYTj|SGD_i89hr_y z%#B-V{Xz3RxF{Z_sqe=n=|44K9x}QU#LhMvVKO@-av(_>vy53d8!hpj?mP<1kNKF^ zgu9?LKJbGo8(r0CPZ8TC&@(?ERMP`DP3Fn0NgUjG{HlsTs=61t#ei@xqJ4dbXkV)! zY>tMdor9v`b$$sH3JHL>eg-h>5^g+JP#=JT`xQXk9>Jtl#E*k0+7XmN4yJ_3Musye zXOJ!p<*NepbEJmxtg8y>>Uq88|Izm4@l6%o`?K#o1&Y7x>v zpU-<9g-KZZa|IBt-kJ%t7c(;5tEd&5)C}X(}nwLtE*zAZS@!?ie&Z5Oj;WLn=0;_YPA`2`#EF9kP< zc|RBYXQW){BfRb-bddEx-PU6|`4Tj**W=+Q19Pioulgmhk{t=u*B;G3!FxCl_GVJh&tTn|&_*286EjMj2n6zTt1_SaBeGdH2 z{0#%H=l!EZ%^#^&{1)5{%hxU4&&^%nCOnz{-@O@yf z6@R>IFWhqAcX%APxPMYFQO3|uacIVnt9}bIuym@^K%@3Q1`w}-vwjqt)t*Bj)Di&V zhQi$U2^{iQKua70|86~W&oOh6FmvNZJmQeKFyVYZ2j&`n;`iquqxrPGIPlOM>#|igZ8f8ix-PmjL??7h7!8@Ksv)}JOya!&R7_! za$HZio{*P!?KPOwG~DyltEopB)qUz~pj5jWtG#8gi%!BiYLHr?7GN!fC`CBkt^rGI z8&s~N@KSz;G3P}Hforh-3**%s15r@SDgIu>*S;PqZ~%hgagdeVgp21tU{Pz-<^qXREKND%Bw9Em1uUa8UDn+fJ@ZgEuI){EVn&{-Ma`>-n0a6*l5&qA1dw? zoloejjXz;`GhxG0YZX|26Dx6z{IG+v#~W(DO85?b`00fIMA+q^=aTH;R?JRLg|Nv3r9}9il}NLfBAS zBZ$F;hX7%Yg|Fby^+a{o81JHZSwPva{I#Bq>TBpJ5#a=5;K|5TayY847OSfaw)`uw zE5y1T_KM^7Vs|}Vx-mit;J{rt7J0(JnwfB$aOg^UESZr68sX$nviu^{c8lvgB~>IW z)`@hZ)9&1Z-8J0Q7isej8W)KBht*b%N9}51uF%`l*t^_>z?X(pOA5ThEwPyHd(>UV zBz=g%rWCuF#v+mYU8ufIPeOhd@em={c?~9dQV9O!LM&PfZB8D!2ptoJ0^zwhpC}J+6>EKC_PBOt{MHoOGwbACCYsevbSs0ORy}vPdiX^yV6gTb~=wX z;=sF_{!WWrxC&!o)tG)*x1yKRJf}ghR0m#WblJ8b)_mD!$TC$}H9EUOo?KWpNF)lX zR-un+^qE${Z6RKjXBWh-f~t{pVY)V7S)*w~Pex2g7h+41T`z*477d70Vbx_5k2_chAP3 zGS8y?(5;;}Fny4(+6t-F9ttG#Z|qyVfxcBejz$otQPI+;5-*RZh&D7cJA(*Ipwj!I1ud1RvtPbv}^G@#S=xp~@+2w_0L+7jVG#;BX2rHi` zxlCS~s~S_CiIPjXW4FqRSO|HaFU~m&k4LGXFX`@_Q_+23uC0b!6B}>FJ?t4?PLDw~ zh%IW2fX)CWw6)#$%ykYZMcfo0$ujryg{diq3v;trcXwYrcVPELb4${UB&=M--ye~#*uH%wsgKwQF+nM?%?-_n4tZ;AVs`4akdG2AS*iVT_e)>wPtoyHem^rQ|JOT#gsL-@SDXVm{SjIOd%L zUX>Wr$x~vCV4(6R7ZyO`zGsd0v^kGv=wX27V0wBJ*+TyVx7}(?P%VhCJq|ITWiV6k zgClG^k~(gJ_xoJ*=J`m;a{{uv_k%~_XRKV`!`k*~^yr(Qv#vmY_9F#!Jya7X=JOvk zAHz}hD7-)GK@`~ecrm}0Y%UfDRKQ5y8-41yYIpaZg#)|aUTEol7Jm=mZv*~T;cq$q zg7}-c&@%Bwe&-=@{Kb&&Bdq(5-x>1y_~J!B=j{K)@2@?XD!iB9Nqf?JYP>y&$+DiD z?+67f*LJ_Sz>(IgPNkkW;(gHy{x0qK+O6&GDSWXYLLn1XF7BwviyOikz&ufwDA7SE zY&^!S_E+nJxxCOM1?z*z;EawJ_txY4P(0w{qUc8}yTs3MSy zF%|b5$L|IXY0N~Du-W`KRmXDYmaUkq**K$HSZdcJMg4x*l|55$RNb|%st2K=##ZGThuIR6g+@_>75 zH!Mx~vsuRS9sJ15=l9M`f!)whyy-z}9$2Kl)f@-VA#}m#5Zbd5{p?H-d7cW$$q=;) zc;g@8CfUWwXe?)xEP}0}#;;_2DnQ1=qA<$=$ptQ{z$?_D+WH9Om3M3uxhwHK5xtVAjBx+RnN5qk-##*;~><=cVO7N*UH;uD+hr= zfka-dV}iU*pfwrCo!tAn_pPp65KdrniTT0>=km)5BWT?7KHoA-Sj7AfbM`-wO~7sJ z(epDd@+C0_eU)Rl6iOoA(3dbFi50{cFbw8PyH~EZRA0>R8nOUsFpX7z6#`#(H?1Dn z-MHG)eH8v&_|xIz6Bwd z$G@@z3@q&dWF0?OE_4uIvlMXw9S~yE5lPmF><`mLbp{FQ|lo#hcb=D2o?s<|$^ z*rtU`eo6nlOU2%PdF#Z3-n@&%JJosT735!B2GAs88{zez;?3i15f$R*>b#NY^4~+a z#x?3^u)jPB$L)=v-&_J!;dHky`U0XqH}==P&wqppF% zkO$M@7Z9-9V2QaAQHm>I#F`C2-jPZrIIX`2a$-9GvDd>y5Rc<6^B9F@8Hgsmvs@55 zfrzmmsp<8Z$}Ihv;a73Pl)}pL+!Hcz_buITJyO&C<|F0ZPvP%g{9X4*iE9c)g+@Iy zxoc%Emf`lQF6;I^V(HK0K68Xpqp3T&r)O&rp!sZf-6PfAM?7Ngc0OWGKgqH&>Vt_m zh|Ew>CJ|8|to(+17Rc8iZ2!p;o;+>dIn-v zTSN3cHT-fq zVj#Y0^-hlY0W;Otb6*Eeq0KSAcXyl=G@&qhx9-&3!c19cPeoE;&sF^LK)cP_9&ee}b%-9sO?c30uA@L}u1M|j-8U;_rKWVxz?;e*{}+E1+W{1JdjIZ!>0m=xnh)cG>{{!K?a1N#KZHe#0Ax^ zpG3#!Ro&u+&#G<{Cw*3Rnb@|s>MX_$R8dBoj{z9ki21;$PEe14J?t9*hBjd^v;w=} zh5Pkmj+dYyF%w(^t9lr-z(~alm}~JQWQ*TGZ7Y^9jX5IP9ft2az<9F|`_jBCY9-DM@>vTm3bu&EShbt5hGN!?`w5rdX# zVy=%uDTq*Fg*~P{{qw8q>iGc3fiZ6=iO9bUvWsR{(+%y#lGe zvGJ%IiZ_VCRHdWM-gP(;^)~VLx-tV|d#VYn7-~T`f_mM>Bq2=hth-Hjo49CQnOl4} z(OLm)Wi^3fdKxzQFbQ<%oqDi`t^=l{WF2ye?_Z1NuV90$dW6XutATpA0b%GJaPo|V za``{)9vB@r!i(F9NbVt86A(^sf~4RY;5-*7Cjk8aGp5tqkw9oH5Kkv7@c3Dd5{t0O z8*?dE&aum(qg;%pzcAj%nWk$z(KX2uunz~ zz!RrfE5$GLmG(@s9wl~60;qo06zd71X|lDpc6y8!vJt3sDZlwN^J(_{Y6{)y`K8l+ zO9D~-4f-39OUeoh;Up^pV&^dJtF~6_1-SE5Ncd=@^<#5{66#gs!UresFZo0*xM~Y&6%cS>V@56kG zm^&RgREA8qn8d+p7MKF3;f>un4Rxi{EG}{VG>cK}n`&|8pJtwKo-cRjnol>MPRGaP z&oR$4&l4|B#T&kRDqi^82h|$*U22Dj_YSHK1FQvp^wWr5(JSJg7F_iTi{%(=qYq)Y z5CF47$aQS^)9@#I;1^pg4jmJG#6g(yhd9h)@vgU64$F{CG(f5KcM-il)2vQAUomluwFijfPG&sQTF${a8Nb{V(r-V$uP#Q*0TiGvytd zKl}tb%P!6xs5@4)A26FF6BhrxAp>8jU_aQ2TcZS8OqL0!`IjmgD zTWH8@wX>1P!lp@Te*_n+!Dn)x-wqg_wI|Qf{c~Ml{OHh{#c$KyJv?Y1rL8mJKnF*rgkhw1Y*AO_C^x6pCy zj`}weP@WE3h?Ud%YzB;E2D~Br02X~3Bkx)y&WgZVG8runQ*4S@eYo)m5jY%i$tTjL z{BYwS@l&m_O1x2vv~>5^8V4eNd+;!E?|wKmm;OU*EGVhqM7vzEX|vWO&Z{-L#fUrd zOVk^c8^t>E32fVsq_L9&t>M=87$sIOtN>@eaX+T9=k}AQvo_PFcr0?7CA~L$Zx##o z=MMrfb#M*eD$94|E%4HL2twJ1B(5**%kM`{OZ5GHNECbbH~ELr0js!aADp9n=j6V8 zo7@{udxiV*>o$E#D<|}jqckfhnDr@uaBc!gei{hCnE(wPkJ-`z?7r_Un}e4VnFIByWgvG11uw{}9v5jSmZwNP zQJz;H@Z)g8dlM@|8Nbie+`^P>0Sg`Dx2&p1Vc!CntljgR*mj=9F_^WjXgHQ~_mhpo zzLr$dJ(?E|pmq*;8)3u28mMBLSb3hMTy&fV`PzoP!Wo@F+FQO7N1bP}rsabXln4t{ z#D`!#VELLCb~MLR}sc(rbwR|X*=1lD=si-ex`9>?qNck)I=CP>N(`A^)r1C5=VWp+Azg+alsDnI_+x>tXgUvW* zd}7l#89PKBrL)_OCD~nYu$=`f#0-S44#YV61vZG6fUdj&7Kj+^w)IHSLhkVIAcJ1a zBp13EHm=iC{$r2*c-hIM zH4L7b%KyraDCNbh0LD(<<+97js+n<6wMHQvUhckUkF9(Co&nvL@6jEd`$i28ktf?sjr#() zcF`|VQ1n)|!EA!3dMWo=!3YY54xmO+sHvnBEZ&hwB^6mM-+8sAOo%<3`_F>JZxN{%48TJ6bd>3%{X)IZ}-Yjz% z&^&WA%x6GnzpeR782@V>qt*OVO#Uxa?T-IioAo-?s%A1LZ+Yy$)i*H0=oOK&=@Ja9=8~BToBHAV<$b z#K!`J_cmZ+uSL{HG0esvvDx@e0Ix65#MOQI$AXY?d=yK%K2EB%cO0m@&*vV8pi0QT zKm=8`xBIm6js+q2d3_s=J;k=CZ=+_gtxIQF&y|{I+1_D^6UVyVI|E)9+OhBNsS_W3 z<8V*gp4#5-kCgU#o=TrzKeT2Qp_Omq63x$kF=V_ktxwtEt}CU zXt_*ErSw+BDV>Y-H|W0QUV|DRr0R5Xq{NdIW5oiKQY+@0Fq=0CuL;N>gGs3=e~tS= zrtw(JeF@tN@v2c7C|)rlAapA>mSysN$O}>%+ftD-D*Z*$sFaBoY-$s^muW=UWzu+5 z?qf8995fV5+U^uuBOXIBD%N4Qv&6=&WrVA7c~6AjE$W=>6W!^wo1P*W9WFAkJANXt4 ze*RHt1)mk%xsaQ-r}|V;&6E7f&UmFfPc9?30h>h_bHk2SWFd50Pgm?KVOfV;m?|WohJ?$-T|Jldbz8BuWKTb zBgOs2A7#sUbMUtmJtJ@03PHRKLm(MUbtEh^SyxQ>qAjt6ufw}e4o#$Z!zo@SKec*f zH_p`2jAVaWcB^!zuD(;wW71$52QE#XT67g(oh$Hai>{PcqT{#>Wg#f)mYuKzzBhIt zHU+{hsc@-FwxocdE^3<$nBS6*Mw*)6JC100;_2f3{F^8T6e=^{s$zm1GaZOo!0YyT zZj*f(HolA&p}$WGlMbB3!`u0RT^-u%yN7BtyDJmM$nrlc(RvP4UQW+l(c|sM0S=L` zT*XfO4{oin`77UYsKfeP6b>q1I0dTri~5SrnKMld7xo=+GiTb~V^K(N1un0uA=2PJ z3H0;!tBp;m##Fenusu(-aNij&o8J0NUfk}X?y>L1tUx)t4`roSsy;P zT5|zX$c$+zC@jpbRJm=zD#S11iUSF-gk>XobJzR4R36WhesNDyX+7-b3rjS)@3UI$QnD&Yh$nm9i zH!|#Q!NhkhCcXrGS+lgwzyQ=}?cmV;3244I;KzCdly#J>@_Z!;vgbJW^bh%IBG0^1?1eW^XJeDXP+g$#PnOYtzmHZjIdkI4e;)B`JKe*#AMW+P0Q7Diwa22s-_`M8Us|)=9|-CHkcVo5l;G96Hd6|u zmb8bg$Mz{5lQ|8NB&z!t|B5Ag^6`4d`(qK?XTo@|)|GCJMa#zVXa#(Udz|-*Y|$5m zoHHKF*MVCVlauRNz7C@GGOVH{()dpmGf2Y4Sz51DsI{fCfY1cz8h)5 zn(x+@ies@!-^vX#7^D`TVLwg9C(tPRR^5vT`@7ZapgOKVoP7&MQ3Fsk{Zx~xg=6ju z@Fwj--2K0`w_;kp6u{+nSc_ytW39GIYr@*>2bdLi0?K?J_(s-aEG zffR^-dwH#4#4x;N!c8q+ha8OhqNXjSx}pP$uq#Eut40^Sok21I>iRXL*=r#5zZcQG zYmf{#h3_yPDtsmAOZP#Ae^GlceDW(`Rhj`7;bB?_taX3FF83ZdUbaAmU!yGLcRofL zqPU?I{Qw;2E1=EV1pE2ra3CNNZZAm9PE#JOhSQj2eQg;d+jBHFP#akuXi2pcv%1ni z3p%%7w#Tp~2;g*IOG_wOyqSg@B#^9}h+Hl3l@;Gky_guhkafiujddogD|&0>0zCh# zo|@K7SI_^F=E5xTmv~zOZ{bHwRWH4m_8) z$4{?sph4H*OLYX`)zv}Fe54*l#Ng813dn3sXJg``X_w;-7qnQcvXBX$e{ILpxKY~X|KaryAhmaD*^j& zVRP*utxH=5n9EmSM}G`N?>Aszt%Pb2gt=*=GFlnRaDN>{zyS=fH$dL~DA=uUgn#9H z^&nBZP044%TX9b+-!bw^9#Ns7RAu$WeTzl>LvVD0Z)ss?ZXqU4$LV5TD!;@T$vqIx zEi4jFv{KsFr}AxQ;AQDQ=H7`5Hemd?TV>le@UbLHhUXTJ%PsIs-vE?;7dTrgGbO;e zp#Ph%JH7B>nyfPCIU|G>pKdm>!%QuudV3NQ$X~#TY za9i*0t(o19ko#x;^3;{QaM`xb>dDsk>WVm=mu9x?f-?Z}Q4h`Zm-74?OK~&i{kLE?dIWR+Rlv_K1uPy^ zMOca#0c}X=+544^;HY1zELMEL&JF?kO9x-ZH(;UM4uZiApcp(~vlx%VpOpaA@$ACs ze*Q^R1xs`|;J%vFCU{Mwc|o7|NO6BPs5!7HKibB>D(g;VBnUZIITaMo2A)L1tc0GnI`xuzTjR>hk&sG zbRD7U{?PK${+XvmHKsa$!Jpz+FVb`W*IQ^iWogeb08S%q`AfKS(Iwy}4I#lfDYEf| z_86WPxE?I?9RdBgoQih1DI9af!ln6D%6R@qT)i~k)yx<^epK%ylE*POYn-x1F2{`x zz1M+XD9}}SR_2A^3GhPH*M$L>8u@C^PeUzi0myOE0b{|1y=S8uOeFL9OTdhoh^ZIx zXx{iOe(TyL`Be@cV<9Z^^$$xa6Zi8xHcBj9lJ72z#5(=4&LXh|v&iY(k3&JMykU1} zz!JJkIhd(q+@~)HG+?0Gn%gzmFO@~r-d(?DLJ996a9YF_pci)`zr!UXu9tqbE^DBUWBm+v*M}n(p0#lTLA1TjnfUU{ZC>jypHz8FU6h7o@%-lo|syC9k- zFbt4a;gLft9zL|3z{1M(AOYFVu^v8S#9 z-XK51BU-w2`{gyMOjZKj&GME#aF@)5GmLHxMAYbdRethNTQs!Hi?kPASe6IEiK;sJ z{ID-07A1OeAmQ34KQ*$iLVB_l&-<>tqHj5jfAp!lT4H`nrb__Di*L>BKOW8#H5hJ- z!T~l9xi1bIV7t^rp3$7dd0UgnZ1;*R)=-TQ5jGRX?7p>t?jvz+Pc=bf!Gu^5g zOQ8QEX7*zQbnF5sZ7Y_dcL6eV1wcb9*syad=#GYJtD(8&10?h=!ZaVp1a%8^w{xMn z%~i$#2h$Hh-#^2svm5Z_e@ifYv@?*0MQ4rJzM!Zw%`EsF#^n8j1tCJp!an^kEbib! zB+PBK!aWJ5!t8Wbuqj(ZIBlZ1%wL^T!-*dA*Ydl>S>%-DJf`_;cz!}y1>WT;aF2C~ z$qR}Knlm?pgE6_>_#=N{q|~I?jzmoPmO3a=lOyLMrYu@D1R~@OA0eR&eJ3K(t*FYHr7NE3AISd`*%JRi%)=q2tu zr2K$`q#0bg>ATK&yU}m&1HN zJ3xVP?qg)TVAmPhorT$*1=*eX*`3p~JM*$Tr)78MW_RYu--Is{0pvYeoMyLd159z4 zcMFe{Z&eo96qh}6gnY6f99-@2Tt@Tcq!$Z%n_@xrP5CovMF!ELzR|b1TYfnl1y;=c zrtG>B6IUV+;oewsdS-|}e$?C8@7fTn84Cpc>=2p2!|WmWyiK61QPdNTik!Po98H?huT9J_ufG#!)h0=t(5E2c#7~KRiE(Nqe2Vpjb*F>#Z!@( z=RNN50DJq}V}7hGkTn#bKAds9IO^Ks3Iy?CMU1={;hxV4WBs93GK>(dAYVN$o(?#b zMy4eVRS5>KHu6t}f|lf12ID_jzHm89v)QMHR_)e@*uDS>hM+^qV>Sb;1E6Q^?#vxv zB$&|(8jC=(+D5Xup*OLyyd32@4gh@E8ZLi8J_24fPc@!L*{WbXy3#IAx~AAxCf^iX z_`nXizvp>$W#R?eY@y9<*rcUO&i7~_Y3_VRz7@=oth3Kt0zOoA-1V>teXr&gRlSNT5g z@N>r^7u+1hCcc}aT)E}7nZTZj1v8Z-7U%~M2(+ABD6a$dy#*m>S3zSv6RG7})!7)r zC#ZD@z%xK+eIHJgdpR=$0IGF z4MyMZfgsogXxlw-%wDcp9`#54iRt{xO2A<1hj7ChB~ds`?6>LdPH&UUKCVbrDu-fr zvv|a&uNDv6^kxhD;h29m8|^z&q-=V)%x!wO%xN=~HYeHiCQ(a!6*j$96w%&~R%|}S zMmbg7Yeizfe^_zodaAvYHp{R{&*RUV3Wr1G9CFr>3L_Z7GqwoHD;iRv%3HEKH)nS? zvN%o!5w1Epw%oH_3aMaAtjqW%Px7fCEgikHeGn3u6->x&2*YWnb|(5D*A}uwD$7*Q zfMX#VL~Hd-ad)|XfPO0S%>}^z8Z~|)(vu4-W^+%=w8kg`<~VBnDtqsiF5~AsCfS5n zH^(kRo3o{h`y9I{a~8x#@w4KF>yS_A`s<1fX%2QGBOvfaLG@*xyih_Awc%!Y_qI0D zM4G`KgJEoz#wi&+?R-MYXFr@7G--L?U~@$_w|d`@?1SjyrMV&61Zf!>Av?vJ>a*yb zo52aU25B(@ATJmN1BDs-;F}1Dd;p{5I&hkv3;P`f_>Sa&$RFX1AfxyO#Of@8Q*RbH z5{Dz-fCcl){+@Z|Dkz34uv6ssORLE!Sg*=cS;4Zz)*B1A+wPBu=4)F?hV>MtQ))wjV z%n=I^EDjNce_TiK#F~QrEe^GKYHTUqa3{<+o}XBRLj8y>h2~A^vb}eRZ58_R*{s;6 zAV0DCm;?)TC{ZoF8>oX55TcbvQPgmg?6G|-Z{#@%afSs|au7p@4YULT)%oJI3Vqdy zdEc{MmWnJTzIZY*eST=gXXv{H4Ji_9_~aQ9f}?AzBAZUM<%MIPWyUHU?v6ckZ3?O}|5$7~Gk?XI) zX&rbry;|G|fmF1@Z;>4{-U9Xos29-nI|8?=sQA~ak?(Y5aw?y$npsBcbP{(hC zZyTgGBjh7Qp=q*lQul(;)jM5jUOMY_nLFVqO?vvyL&`Dg$Bl$5#d42gDKO`JBHLu^ zJW95l&9otZV+Ypb$>sXz`;?v|^^ZE_0K8=15*i(VwsfWMU7ewUHp z>%zu00iC+6w>uN31}Xei%Cj2f*)2s)wnr6S&gW#O-m<&dHdqVA;&b2^y9kWL7u1PWnl5#J+&crHcG$~fy0dir{sJce6$-y2=2Y|wy@kIPlq<|Yh-BQr z?~h_q00xT1wZHKj3(#^nmB=3~PVkgC#qpjJV|tK0v9sH_ zoba>}u}HFbrtDNGvhkw4Lwx8esY-JfuH+~HZaWE!2OF=ZxCpo_IcRkZ@#7lcSjmG| zG+AB`82}=IPG6$?%~lkK6rtLY6Pp^VIWOrpNv zVll#1(q9aBm6RQJf$Y8VD9xCTSsCF(5GTsw+7WQX#Ga~>>N*~Jc9$Gl@(gJ>FD%Nv zip;DmK*8A`JT)a{$G_M2D8On9|5CFcBgOy@3kEW9Iotc<{zj(_tTUP-`~da_W7NTV z*5V5$eabgF^;7A7c^;F&b;z|tF3Hgt84kE4f5b%aIxq&e!LW56vVBts@=1uhFGrfR zkC4abaiA-ZIYx;p3jx%vhe^w$lt88V0Vd-2;Ol<|%jLU)f4}Mkz!T1bZu8AVpO*!c zr0O1!v)?~wzhBONwYcwBbA`i`Q{~RtcZqXwIE|bw5PR~fl{x#4oP9gLv3BItg-(R& zsLS&r_XO0m2as#HJy7+OtN^7x$;4#HbE`ZDhchy?;2C+v0HA$t$t#3j?@Waeo@og2 zcjZxlb+%k;T_CppVsa%@88yXe$-|0lkf6qfKu22wgO+$b7F4`X$SP2 zD<1{SEphK4ni{;EBpBT$-qqp{CGv-G_okvZgOPME5ZC@}b{>~`0`NaWy0djd-I2L| zEURo8+cHmp8p3L+H;XAho2?UA^nt4?0NAk9=@&34SE?dh6YjbC9e$VKSvKftW?k@i=$R4LIupm`1e zzce6#E5PAA4J+5LL0q;Re*ZxlzbJaE)Z2tqBG7fP+~t3H9p)Vu>gKLoF!akj83kEB==~}x? z4bN7nLvm^xiI6@RFg0xLTi=A27)ql3-!iJ(bpsN7zlF6{V^v~ zhG|N`Y7ttA`PkH*oO`r6x6s6rj_hktg@DlxxPKGyGFQ~IB#HnPNr4ej?)@XSDu z#{$K3w%Grj#g^v#K;i`ApNdn!mC7c6lh#(YZ? zRbNY~9s|}k7Il3r=Ym)(NJAn4*vJch<`>wG{)^RxTp__Eu_PJ_7cbLKmUB7`Io{Fo zOlVSM-vEP-^>Zovp~10Bcid9ghC|*V@-a{wgfZ89a?J0Cm?=Gs?Z3)XC04LGNkt(Z za6X^8C@{GgtVHQ|F~($BUy?ta`Xz`|v0mN{C?o|2u2jPavYntF16HRjQ_It^M_!Bg zkT%#N$7)Z658Vb8X+MZEcYz+@Kgu1Tb-NTfY}%BnX)s0}p?H<@3=h^Da4I|iMC5sz za3vEFir6PkyO>Rz(b%LvBJ&?(DJu5x!xL;e?k(eCfTbm@xPIwFANAL&6Xh9j7bNvB zpIa4UhEtqo)avp|OFEM+0m&u!uLkQEh>&Tp99?ErM zgTCB8l|Oha2;>Zq9W%lJa=^7!)lW8t%%r)}JV~cI6saD#jcPS^vxF}$?#HoK!YW{p zc&`^n=*t~Si2kXZ&O$AQl{dmLv-XIG{;u*t`Rci)^pWH>$#!rv;yq^B-m1h8Mdj5s zc)yg(#>1pA8J4-cKUnXI^l;I*zYB5g-BIDv zmG=|nx^i23B1Hux+~z*Qmn+>@^{E?+xiH}_L#IdDF&bulNH1x9Jy>&w26M=Rm_sfG z9%~Nxi3TAc_9sL|Jr9b;tI_A%u_zd!^@5Y=Yb=yOMm!5n?xf-aLFtLWTH6#Ac$fDy zJK5}hqh__{Y)u%()H6Z}*|D(}HoqWWAMs9R-c&LB_YfUMosgge8^xWEJ3Ngy@k@$9 zM{ErR;K89mUO>LtJZz0*sv9;N>*=m*ewWB&&0OVBpgC;vUmYoMSwk3CS; zZ3T8wipFv*X(MQprcIDGQ)n}sHXhm(VxxRb*BK(# z?y%d%%On)G(B`I3oQ2{OJUFfFh7vLHTM$oo0#v#JCg~}layb&X@*;ewz1p1&DZL03 zQl~*U9RpB;37lzP0W(K#l7B!nT?W>)5GMJtK*tY+WKwe+B{#rPa;Capvxr|j^hPWs zC{oee#1-NbkD*Gu=YiI|gEo)Q=1z~nDAv>71s+g~|Z?z7F|OVKZXk@`98aOUUY=fNgP`BotWn~xWo*%p)8H%cxwuIV`j*nLsw}CF=ExY@vl`3 zERxp->l=lHMTqTS6OU2c0+?*b>eGBc(gdrXoWKW+IYLA4f9+#3XTR9f&EzlgQwq+hF62qdE%?s7ivKIrI5dAe2DZWiMNgxV@ z;C~24srogi3c?V>tm>D{a0Fqea+WyKWw1#}0|5hCS6CZQjX-1tOSD39ff||UbJx2- z5PeORK`*|nLe;CZc?6pg-F?0&jCJFrBhjT%M`*7HKjazUm~bg0fX%!>GhDlJ(%ODr z%AwM|_(RJU<+j2U-* z8zMqpgPr1T#3P)o4WO3~M}&R_K+^|dtlo);stw8oph%md9E+T#f5L9J9WKBtvHUv2 zp^A5Q*emns(})8Psy4Z9g!+QF$JQ!RZi6XgpZQU2pIuTXR;3Gz^H@IAUvIP)lDLO?vS-WdEb|V3sqj` zcT#T@8)pIFhK;43;|X99N+epyHLZ5A43CoxtOMUCp$%N0@!Spv9a6q0xc@^sC18Pz zE;H{GLuQq@#qXz<*p-d+kE52mC(PWijYH22b)fGAoK5n%WG%y{91-!vsU?;ZxjV*z zPiY0YAu*r%qMnoFQv^Cw@cNL|JQa37FRuXjR#uFco+}ogT2c-*#HnOf?bSK^Fb4J1 zOAAk&D2cTHlRt;|e-!u6EU_vh_#fduwZtZhX!HF{Y~IBtJ&Y9?;7Py_)#ZK(648Wv zVLC%}rtWZ>#)cvRn>ND2I)$j!jrLCYPf%e|EzLF<_MAuvU@=O+G+gdLly*UKK8U@BgTO zmwHdru``C&O=_M#eadXdS+ZjKux!N~Sux@0Y{d$3-OG0O$&Fozhe6MZb%u;`BJG0h z3#10^t^j}Zu2xw8DK8)tP{gt4aX*DAiektxE4y#!&j0Ptc@8PFa0u@p&?y}b*7xN_ z`c}TjJ*TH7UB~+F-_*UsQhzD#-4$l$;|azvomjN*_ z!*nx~zfvj$!cDj$usGYn10)6hj23|BtTZBy)^4dbGn)1ONf7 zhxW&WYcvv~RgHF-(+^YUYRb4&6Z&}H;$r$Be6$|?4Xt@UA5#8F-l#Lw1~rpb zHu<8@i^A@JBZ31>LY>W)MSGYc$oEhED=|{Af(> zDO6M`&rMu2-=p!Zi6K9RqnEGjqQa9cl1K~}!GDUTaAob9q^LeSuYAi5=NIOy1*l!1 zsS)*$msN?9m4%h!{fi3wWw@`BT4=pbBV1$ySc6xE{@h7rZqw*cne+kKQM4z1+9Qsdm6DKw`%@?-{MovYnrX#ZP)7wT}Taxy+(ETy~l`7S%z#8)9&%hX{lRv*OqP`_M09A+BPV z9hE>sx?^+pj}eEzrVbd2SL}Y2pBlpumxT37uB40l|7~qQ@!qSd%SiUNEQ^NSBkp@u zl@=}@uF!TV`-I_narvt%+{v%1W!`7V03eUTuN^Mz8Ozg&XUV!vjC>Utz(>5QmiA|e zJU1P`43<0R({dm{pfo2Ir=T<09};_C!G%A4MJ==bM~-SbieO1B%CU4UVmX!GrqS@J z+#@nsElebak0j=ieT>C;7|XXSfp_y``8EO(foAO=aKG&YUBE4106r5qx3N%aU0A&R zkICD%AQn)7@Hz$QD_L^fN-3fMzXLz#bMQ-CtvOfIHZjGE(x;JIgSB}?hrv<6fL zqv6u)#JW}X+Db&*_)D+hAAm=Xlj%nWPQD-(Z^*L^<0qBY%lMvr6|!pZ%Y@EI#DtYNXZfryv^a14I{@+i9s7PTGT`W85MG`vLS=28SOt|O<+z1Ju!GTqlA z9@?1Kzurs>yF$$vN)5DM8&Y0TPQmOy1_p&epo_Xx!-SLBTu6#iu`=(Xc}QjEaSfaN zAb2|lI=95Mc}C^mALcm~v0Tl&aLWh3sb(cegJTF%45_aooAjM9yPgaAJ{z%sb*f!e zajSP=fOy8SqZM)=fOLw2Fd!d?*9-oMvs5jXC&+SBa4<$z4gBAuO*?%#d3`~-A*PVHH;gK=#DnYl3W zb{Ux>L0(|0Z)r4dog5m}h|6maDX)>EjE;kDEDy|4r--djgtEqN8I_S2xLY%j;KU~FUiLS2 zOM9;bgC1KG;_l_*-qpC(rqy<4gpg~@&3kJdVgy@CemcA6+hMp(lAOklzx>A`bSZwmRFHT>sDmVUILLj z37nZVj0W15i4eFQ>%f&v_%s%TPyMxK@UwgZz2Vs z+lkA}gM5JRGs&PE{TcH1Tp?MubZ5xU#Z_3{d-lrr%4NniLc9fv*T^rxwHds0@kQdp z-FcoN@U$TzhTrpP&b6h1RrSlN_>x%9+V@s*+3q~&7}-}klkEx6&jfh}@Gg|nEE;8n zV+t(0P*z$4{?d!&IF0&Y1c5Ch8mOEjChyMcFDC8ID@r4n09h*V47zDO-2@9)DU1vL z@i%pM=GM&&!G7W^{;@|E;N0o4M4;%vUuu|wi~DW1%|5ew45hKcP|Q|++cP-1#_s^c zm1a`eL?ZOw5nDco9Qn`Z5Fxi%{PFxC=A=$2{7}QK>_&+_@5`? zB)%3A*UPkvkhgs-+{BWv=oc9L-vx{8R-k}xhGpbJNZUnV>Ya>naWqH?Ot6mZMX2Zt zngNd>@AGAvguW90^JJVM7Q*5k3s>sMy8dGD%SfH}^NK?KXdW1uCOS`_lDkjI#k~bB zy<-XSox=MGxR4oor=iv~B-@f~#>f%4dMEPTt=efY4rYfJaU1cG?S0z4(5LjgIG)ZL ziL=tr$Ri+O?2P$!6L~<9?un}>v^9N;hxIKE>{}erx7fdLkzH3!Jy)*I92JkfWGD=H z`4bX52QbG_)(ek5v|=dt42+I0yxe#zrhq~6!F@>N(c#l~_bFY$9X{kk|MF+l?ZWSc z_a#G3t?cEQLrnnK=%scZg2@WrL5y2u?~ePOjpCz;h2_i?(3CkwixLnK23TNZ>u`|n zQqju2K3fatS4)Lo_KBL)uq>GYMG3>6vRG9O%+yb!BN3bY=^*RuV&Vvp( z6jpyLkh|Xk!tyu_R9R}qCZtJpA(D?WCw~BE?L|II$M|PwsPgBBb(Iq5v}N>nXGFHeSSQ zti=z*^;*Gh%O;wNz~LDTxf!v8@**fn%{;VXjJB8ryJiBJQj$dmF=j?(!J?piP8cLh zRPOtj^g9CKkp6gi7BByi2_x1)?xD(Qe4|Ck?&$cWclTp{&_xh6KKq?H`*-B*Zx;7V zudHxv%Bi|7Xa81lHV&6_wzno^1SDYzhNnoNuvtu;UOCX(D5VdMU>OIb82nk47mCv9 zmEL(%LlIE8bX2aE(t?{H#spN;4*A>ZdW3QXo-Qc5fgoiunJ)@sX?ZkV^0 zf?w?xO`~?SdXF}sT(RuJID+^rJnGsmTkZ(T-E66HD z)-TXb)EN-1UH=$O+8Ln&^D)J#*-Lpo0!0jgoDiuR!9oqzFU#rTiG#)c zj(~*$AI&>E)zZ$=tL%!FaV_a6}Up50j0!Ene<=t5UYMP(`5ey7tA~8{tp9rf3YTv zb(Ba?EOd#TPwDJR3H{@k!rc*Fw}p+j#&Q-~DYz75&+wckE0DUOgH@4LWF*7G`rq|MPXn@-LHl+|Q!AYU&kF3U7(K?#q8cZq>pQUC zZ4LPnMt1HsrNG+YEBJwDz7$yi6E)<+Ca0$%$z3m1GYdv?a)Sd&=y$D`LzMskoTsma z=frrI&#${wj#s=B@ZCndr^SL`?F$CoOgPenNI;~9J#(9`SdIfA`6(6^BA&Q~kdG3? z#IuC&Nu5P`gZ?S!uy>q>c??caLbU5D<;_r4a*Y`Bq|RyT@D(td7}{a?E}=ZB%V5`$ zCdLurnFt9nd^DYdaE#-iq#gwi?7zatvJT zW!hh{l%(XhTR0WTGEPM@5)s=bFb(YmO7ao7W7Z)RNf73`QSc;M;Ewqc@q~{fp71Jg zbB2+nI0&W6dom}c7N*fotN7(4Z1&P-7i}J)%_iEcqs`*r%Sv(%IFm@j56xe{B`Lt=pZKo|D7>fW@^TRLB%qGb(c&{Gq{n0T^6};?Ly`c zd|Y4Uk36osT0l?j{)oHJ5{wPfKZB4@B|T}sNet#uwi%Q5D42LxX!{=r75jW7fBOht zz7bHew<}+1y}?VsMOD|on)P_IFt_HHi}^R@m6WcuUs8&Mh!xIbX(0hdQqMJc6=LW= z@?PFD;kLYI6mi^?l`i-)iX?8YqM`}k-n=!Ea64&c~%^uA&a7kYWJ%2fDbKiDhQuc$c&Vj_| zFopZv0HR>ODje$QNV(>aSZEGKVT50VD0%*<_BX`u(Slm>TeQF`KBvvA*eI`vmC*u= zf&k`dK~1eyo(S|MAt^H{iqEG{+f0y5s^lcaE5y)fL3!WSSR4>5;;CX^M}Z9nR{T?8 zBTb|^NRe$(PX)RE5E7dIy?6r0PUg$;=q`=A!wq_8tgec!4F-O40Q7ouCG-JK7Jcc!jnATBHE=G40 zIK#@)J2l`3zCeQ7}+9jUN$Iz6r5%K$(qM*P2<6g{fPDkuIk$*;5Dn zTWqO;vnd=>w}<8kIjATRsH=C3jRkbP!>E^|dAl6VHh&rPqN znUpe#DT}_`^r%hdPZ~l=Dx~}ELG=!V^j`>UnIA%HJYWz50Pj|@#(WL^?Kbqcv$P@Y zsUVsd!fVX$VEcL*n4kxcfb$Y4p9?Yn9;;sx6Li#9jW=2C1L*YRtQ`hs9| zj|U95QA~YvM<>{7Obu(eHxl4H;q$V)4Mz~vjU>exru>&_sncy9Z58H*V#@%MP|ffr zB2piVl}Lxx_m`S8#QpWf7UePiN4!;ETrQrb&3)Kd9?CS2`0C(ZNQHf_PsP0Y;wn*J zUtGz)mFCD29~9?$WOzX?rC7A|75TMO3G%u%6Wg1MS*e@xLg7n@R&TkNpv zAn{h3FMtuqA$C2hwTjMeB%(X%A@FiP^q}_lEu$XRKBW|{v|Z4TTC7ZH@i|^7E*6*0 zb}vCR^92&bfz6$W1?%wnY4rzdsy|@m)Ea-SzL>{! zC-Pt-00zD!dKaF_;-|{8T4kaD;ZB3Nv9ipj?B;*OiU}|*%Y)Tk3&>Rhi{HdZ(AXkoq@Cye(f)z^?a;l9USvU)sQ1FY)KlPD<9Q|$n zUaWJJm2+OXp7t{U>VsVjaE;1WgwIh{!Pe)V!|X~ib7JqFIykKSw3Lqf%m@3()k#QU zfTYx~^{JGrAoCA2@S0&Ns#Tj42pW!N(XXb4wQ^8`)42n2pCe9&ozbZ|Uoip*+JIGB z5E0Ycv_D`DnGcgj{NFI54sljjJk6_;XJS%Z`qVsZccqs8VQ3^wu0R;^QPJ2G#` zmht`a-O8q2G`XqY09yimoRR}lhUrT{df>yfb{y7XB?t?62PxGz!0?&^u4E$M(*3kX zXyTNB;t{}H*D%$=6lmgPETsUBcOh`LvPES*V*XYjgyVY-@*Njr@kb8MdP-Q*W&Qx2 zC9Q2niW9K5mV~(LWD4y(yP$xzKHw0+>@gTp+(WoqCEKH+lzW2Q4?r0+TyBQ3H}m#S zLyibj!v+gnwV9f^%i$*vni_l*%$co=EkOzwQ^QR;?Xt0);K%B@8U^y38qUaRB|U?t z2E^9)wt|<%)PUIfo<5KX{V+AaoY7O6>B6Rl(th>>kV9C3M>#R(Tlm~#&bv3})<=a14poZ;*a_lm8u(xl zi6Z8_d#EON=GyJBPRLc8Yr$d-ex(b(PcWcuUDiuwAXaFBr1Q~Tsq+IF*X z8oQN5N^X!ANu-)1k#Rgs8%sx;i-!5ZP8)XJ9kb0j!XxcWv{R=y&1R?7cDGP7>jQ{M z!_Db=m2FYm?edrO$AJt)m^SkeNUp)6r&-o|cPV=(GubJh5r4j+KdCw7cfuJ^h$6Vc zkudxHu21+pIS-3ky|PDK21No96{xXZV7K8iNU3Zq52eXjOl|GijLc*&o1U4RnB2B` z;ufPSegsR)ME!A3W^xisAn{lGrlwC>_IqYbqVH9KhqYW8uU;c@QX8Vt&9&7<@{hmiA_dxv+SX&d(Ks{F3hHA-bPdC_3W&et=^{hrfi)`#IW!Xmmvh z6BvEP(3Xzkqx)zO3=Y@xbW-k;ur5Tipde|Qo7A~`DhcIq(MX(8-Ntd=5pvRgLLoG>2Jwqs2NATh%n(<^nzsFLas5jg~5UO}R+L zYsLVpKSndpV9YJ?qv#(ZM!sC3Jvt<%6l!9UTqYfo9PoBdY}!+#9V_oRF-5Clxl^=v zHHZ;49V1F>MS+C(kcxXhycDzH6&rvYPbV-s-ywJD1$Zb{@$lFXB%i0Ckmk4WPP_o$ z#Bz+M8&R6D6L4x5ctzT$F`SkH^fMj$EH29{xD1EwQQ{j8x?bz8XiKKPUkK0i4R~0U zMXo7mOQh#oNL&=q@({AFHFZU+iGFV(^1_;bZ#=q;)=1+4m2JvVmnLl}8WMN|YB3^| zr9)5A!hy41PSMb}>Dke3##GHVY{s+1;r3Jw#->)sj#{jaOl+y?ZVI4@l)$PF8+M>c zp_#A1KNsL`eGc{|cA(hkq%rnCy3KrW;&NmMfjjO&>wnn;Yjvr1Z2e6a19>&LOHesT z^*oyXV0$`hQ-)*fcYZR6qJpG~AXu%}q4hWVjrqJ4(JnlxuzEI{emxGIKTOX~KvcG8O=w5OFZ4n(@gwntdamAnq4%f(}IU1FcPwM#A;uVDm+^ zbM~7^`!IytC>11NrcuqIb&*d1m&3dvzl7$0_nyHVUOkWX!lU7H|5fhtHU5jEcMhJED&UA4 z+uJPHaczXtDiGW&-9>$F81^yZCZH4~!8udi7I4Q??CA_!2liBk&3ese{GA4>;C&Gk zjBy1tXABDjKn_yn=2?T-!63tY&6(Y_|6%w zvBWtjkb=WYbef9TG@U&&P6Y6cXIZw+p4x{0rshMFCi5#{A7ozsgw-5pGVbS8i^`k9 zKGE9U+(mjtzn_W{&!nnHdmF!B?dy?nw9Heg_MlqGax5~F5PHeMqHIw8h7#yUkPWy4 z=~N8}yi7*Px2~`fbTXw_zYT6%s%@|U@w*9tSP?;@PHOlAA-t1N;GTnD?>=cQnF`AJ zu2~xK{bKY+;vVDqZ=(@C3a+FY*L?o&;Wq=?JM9DhL(#bjJE6O_)n0!wbU@JR!}~(q zxz_O%@1DW%RMC4)Jg72uz+ppj^GQCyGqv8bgre<}hE3F2n)Y4ZxF z^kI1?lQY>JpClXD$dk$OtnqMT`l{!+ zmw73s=NpjUm#s=wi8`w95D^KiiDf8VQwC;>0x(;&L#Nck*L;#=BgoUd5~OTDnia5R zC5q*S(x4L3c@OAM^!u14(ct3^E&JZf_C=Rz`P{=!e{1(TU1YTl3zg0V+bO1iQ6bO^ zgJRfdWeH0`h=zVfzG& zm1i&8e};F43amS{nAmxK&#($8V?IL9_+Cp=*u`(`i8+-n!cOt zJD&B(vy;Hb1tdt=-HrY48@r418S-|l0QhyPHt)y4uL%@SX{+&6m zm>oJ}cav}>JtFRvi1aEkpBmn0OU~H6{W(=3?iTrzRO+f~zF{UGm~i#N=^acf=SDW| z`Q492Kf!&54EL~wpTcDJh(B)rhkf&Daw>b9#9oL7Uh523hv$)2G*dp!mV7^wAaz41 zFuNo)+x`QePv}6f2_YPeyWwmW{8*6%X|?g$o*yGZZr0ctEfV)_1PuYX5_rEDDS8%- z9*uOJq)b!ohPyRYx(=?DeCe1pL#mL5@N&c4GYrw#W~tFDHKvmU&psbajgyxq`7nUm{#hU<14f1GGHm}y64^r|?S1A~qd^3Y{X{Djo`j0?}ybL(+UGPJN z;g=qxx(;iM7Z?#yR`ebCrXL5Gcd%?B{>j z%4-0uo_JWDV!4_3aQ;fha|BvKDT_ahgps(zYS8h&s!ncSe8nL}yi4$t#v<~7h<8E{ z_6GRd+3US!3;P#|EhN@JBzF=jEzKUIgH^Nq3E3>ax17#~^+x=yCxkzT^q6ev49!XS1&(W*;N|}ILs(yw)@u=#c zauNIj?_ojMjrhY7fZJv%+p|U>i&jb-Bq^o}1OPb+6}dHlo0 zEKs*%bu5~!{%^lo6MSoT!8a*M%h&*|{dQ&~Z&tG-OCI+B$+6aOrDKhH1b31}JZ-~C z+3G5l(c1PpO0zwLwQU}72V+6c*ag|^3C(b+X8@O4i;_}=JQ$+NL6{~H#BzjmIe=An z9l|t4$hYYyw+9!=KY-%AF73YtsMmFf(3B|`^LWkYhlNn|E~gr#xDJhZ}D>wcJPwV^OFNqJF{5g}Bt;k63yV!uDC^KecRKI8F- zCM{mJ9QHmwVTT{prLp~wq9WQvcI%@$dl#;mP$!1f*{oU_KfikOXY7O5k=lOrb+z4c zqIrNu?bSMV+w1DK$sEnbzg>J_IL1c4u1?Q7Dt@u}Dxp!kA86^ok$6r*K9gTpXKa2Q z)9Crv)RyGIEdzNX05&rd#<1 z`)leHra+|hY5CUZu<6a7J*>`X=!tq0mzlyVsF&nO^CS$U&ykQ^JxWa(qZ3tZ~+*3_;^^$zA(?isJT{GngEtnC_Av@L4QxUb>JAl zZcu6%%*`eM6a$X`wQT;=viV=Gf`t9x`6Zy{x#rylzRw9Hp$?SP6$L}uvwYo0AqLXs z)h6-C>j-%l)%``p0h|^w2&~&ghY@WYfHhCNhe!+8Y;TNSj7}t@qyg&gIDR)sCGw4e z!zdxK^)9c`J`CO!7^rY7LgVq<9OB9~HE@^ws)SWbaGsOoD4<#nCBW81V5*-qVq}KO~@0SjmzUktCb!M}PzBhw^d3-*6 z-C;u)Ll^d6lNr;S$=r!V2lgIqtxGVcvx_FPL3cReaLYBWGnq{(!VbG$Qrdz&^m^4^ z`I2mANe(&JeB(+D;6K*3(aKDXn@uU~U7ZFUL8o!1#iVT^nM|I#Qq7O%2qKGxMUU=i zzU;uJff`MUO5ZqjrQ)N@_he%dVa?_JrhfT4mo!*`iFPNZrg3mB`~yAic|g`dxQo(i z@kpCKfb`H>Oh3J_O#K8u_fCL(f;j0E_ZzT-=S=O{-adA#slX339N8i@?$_O~vvFuM zX$>4ExCbjcy#_!Fx)Ju`8hqR0HMnrm8oXzIb9sL7 zd)E1KK^Ac$?F5}>Wp`%l6Y0CWY;OmXHE}YzNh2Wo`1j)9W9zd`*({iC%3}H1rZy~t zgeu$AmK{2;u_lu-h7`>*%2A%9pM#OW&YUx)57aAPNiMPzUO~XN5jg=lz}@}`cjQ($ zU#6fCOFVRdR{_+xUG~d)uxxcmczG3g|3%Vt={h#Hk3F4k*~a4g+Kv2Cu{jB?0@oqX@FeQmEGhV=#9Y1es$DTfKN@q*Yn>zE?%NCpm zE_BHG$PKW5=S_Oj2h*70yeV}MO*C$4f&_&6(@6XG17MJZoQ{Kds4I}@PwXmY45Rlj z-P|FE_+sfs2=YTfIX8pHXaYOh4FhD;dV3pIv)-P5omb<^#&dxxgc5U8IieV~!$HH0 z1rXJA=cj30$S7?6c`o>J>+!KkWnvawgq>e!Z_nOXXU|BnXk2z#jvUUNa{c?W+3V~* zG!?q(y6J3pf4hq<>u=9wCH?Jf*|7eA3w7)dquNB`yMFc@cA}r%%=Y%PXPHGT08V$L z2zS?YXS4d*v&CcV+Rv_IGy2)}VgO*bJ4?i_I$M*S!_xZM9c;==1|z%F*Y0Hp`r)^ ze?cf}H$Z;@OyOxzJl=r95t0VVZ?k^;KLIe&<>HV zbTM~ft2fxQT&bG2U^wSN4WS{zoU8EH=w8yj#2&#rU}HAm$#&m>Cu`nd@1>tmj2f!} zgv~CnOY7|^E>s4BYaH0APlX}BR8rFA9BHX)q0G|n@YW?Zc33ytD|ynb++0U*IoL1l zTCJE#*`cGl9;{3Mw2tQNb=CZ+s0EFqvf0y}tx0h_Qy9m$9ISS%tHC$l#J$xg2`bX49oze^jP*@brC*ge?J*+re9$>pGue|XwVg?HR9-Q^!fslLLm}EIRq861LJRC(ogZQ zYd07S*Xosz5kS3Gf~~m}G%;P!1CPRV3c)F8LYCm8P#{V%QMQ5Ndzz>GE|hMRu2sH} zZc;vD4{SGh*@EpT**9UkAWOmrz|?mmsm=*2P}74?!vg$;SSl0+YN1? zqo2fbGgw02&PJ@^BanV3sZPPcyFpc@Dn!ATI8+0F4SAMxVQjX8js0&JnmbYQs2pqf zX)Hw@H7uM78sxE=&Ni%jrqhd|mO+a~%tIU-1Q5-+#<_<5+1}}9C)$I1Z(n<-kF9O* z?8s)eclKwa+k^Gk-X1;YmkeiH_F;z8ivW@H8e;*79XQ)vYH?~Y3uWMl5gE>QtWAdV zTGp_`pk=pp)En5T9foxDw~WrLdWXT9M4{3eBqEkL&pOZ2OXAIJ*A7DhtJr}@GI||e zVTT=f8JZo2cEmNO#dEtS)9Fj20j`$DO5h^;2LouVY8a}+ZjuLJDBUZKVQGEr-Q_}d z%@O6DrXJsWewEp(H(+n;mD6H6e4bFBShu?&>hzQ9BWSa0z@9No<%KKjOFYW0;1QiB zcg3Up5~ZKlN~O}kEKQasCxbO+A*t$}9dTwhdTU%3d*~r+DqFZCE&=m%PBuHVJ^9o!D5Gr3e&c?;)VR*#!}7&8y}F$y$0N>MvmH6&6Sl{- zxyt*Q9Gn9dw}JM7EOmQa8vAowoR7V;7;%Otx5c$%t4Pe+768)|`Y{ynybLm!`e{Dz9Vmq1XY)?zGj~&Q#x*NoF3Xaw+ z)k>&@F3`2kK^Lo(e*$uRJh(@mRh^lAU=aAC?8dJ0tlMWIR*>Q1ldRl$-RDxA8YSX9b8X;bQMU zhb8ri=djqLBW1JcTW}?GA}1TM1(aCS&GZHJ066#^m5$2DKEj+;RgO-MPNI*Ve#i=n z&WEh+>8qSS=WfFz zK(aiFC2T1as30;2`b07ZK0}J&tLPcKz%;WF4&XWR40#yxZ4lFe-|Hgai0@-s{};yQ z9n!7JkJYG{1TtX6T;R|!DGfk;AP9`eNuA%sjrf*bGX(;$JF|{rwLE8eJnF8LSV5lP zp$|%GkP+wfwc6vHG|iu-ku{$WZwKNr`5>c9d!PISXejn0lcvl!mnE(+J98+aneVUk z*Vk3~;>9Vbm{3JkOTwBTFK@U=t~N~YNhvBzIXkf2Y~$gOd_PjBQBlk=P<#gzWptbx z=S`7ae;7ruN?oVP!IF>imjU~3ihN@;XnIoIL2y2*3i%dMI0Yo)Gb`%Vi80$|_W11y zshlh@-=8@WP?6DO4pfFJYTeoF*4q>8Jd%&ks3P}-&`bn*0@bPQ*qGZBoaNjLR1a2O zVuqX$@D~BK6PlaIGlqvDc8&*Bh5Rkg1Rl&mIx+aHU+2yc(A&b3NWVqvyu87|eKX>S zToL>CZeT|jC0GFA0#t+&LORk`=~gq zq7r#>Rj@C;oL7MiNI^*CxmnzzFeoG2!P1cLB==p_A&JKOS5gDvP{N_+y3x)6cM-wY zPz&%*AZcyu-8I}HLZ3!$#IN{m@D{F@nnk>sH&Dn4b$aVOmm&w1qW4hNgXa^`5G;*{ ztx*&Vmv|?U&(4~UDOJM}o7BN0d`QJc`FTX0j!MdSQ2KU8yy+-7RZq)0tUog_mUcls zKd-VtX`BU>eV3wAc3~j99yHf18h{zs*_Nj*K$-0^K^_)WX4B8xT;}RU{rLe=ZTH~` z^5ED5fYb!etoaJ8`vf^(A?+4tyS42X^~2fh{nPdoR+TTuvHA(#WlgV+^LCIsi3MS` zq*SXu01CNWS`9;2#-gxG@+plsw@Q0rGg4)D=ZV3p^4TvMD96;wT_0Ep8k3i}k%ey+ zjI)$#B>r_^3sYPUUE>Y6Px2w?JkEwm-+MuRh0QxJ-@)!bCx6;B;d^*Wc?`Orv{1%; z{VwvI9>uD@2s8a?&?NW6+U`NI)Zb8H;TT{-Pl6U`y=oDh9wk_@hT&;;Q)M6?tp&FA z93T?MQ3z%SYAvjXDq154ITy`PWbC^^SMhU%Cu={LXNf;ssxt zZMCl9BKN7M_}qkn>0r%Un`w;X2QXZN9gD$X1#UCYaoh1LtBUH(d0Y6*M%yl4 zK!i8D!tA|OW;gfP=fjg+A{g|XGsVHcOQk)-C%?eVdP0gk5WC|PI|1Uqh(F2JuQH?P z3ZFj7IoG{qvm2{kWwthS;ZNB=7t^+92ESS05HYd&=YoaK&0W;_AgHUI14bUsE}M@* z3LZ(My4tpiX&NMMs1ID@Ju5Cnfpzaq;!-GAMkCnp(IkHM12R}7tV9L-@neE$0FhwY|L$RvE4>Z zmL0PR+?bM7v=Zs%&7WIXdY#e2c4nC3*po(0W?Nx`^CRK(;S9%w(-rAtPQ`?zvn+Qee9EW4=2LUQW)_yI2*8<1s;6ToId5_~QW5{P-1+_5y zW^LOc9P*OSKcJAa`5NAjBl~^>2il8|M}~@EHk-NYzg0^HTNoGLcDRWGeBy%w;F1uy zAtD%aPRqS;k}Wl_HzSS{4LmU;(h#mIQns+%o3u6()&@?WAU?|zfb#hImODfYLwTt6 z?t?9Nkrx0k6Lji`TA6!Xy}5hL$>0+Fh);3+$LDgEC~L90tmVn&@(LM-5o}z%)1FTn zQGSr~a09vnSP3v~U$tzX$a>jA}8!Fj33#Y`Vc|y;;}NqHWpKv~0$lqO`QC zS~lgDO^$8hMJu>nuHVkS)x%mpqjx4YaDY$bGt{k0IvKCnWxn5`c`K`VE0e!@tOuwb z<{MI0=i#-q@<9NIBwrC8^X=qMJhn;ywzwC<8=q>~`~p)!njr#1CM7~gOs~a2ie-n_J5xh_kW!A1kTF*KfbHcwNK}hJT58fARP0n13rqs9M-6I_2gfUafyxg zeOi8)m=qD(qr)Ef%aPRjFy}rEKP;-I@xwm-#bLSpF!kk!^@=?rLfBP7@#rt0550ig z9tL1X4V=DXcs1=r)&ErIkpF!YFrK||zimYE_&OAi9|LQ+11QM;lD~#~{RNpoJTx^; zM1m=t7Lf{JZ=rbnRzP?bN)@?9VmJYlj&&6VL)gZkJP?)sR+2@;6`pTgcN)TM!6g=6$Q)5Z9w3sMv4Gr`di zHs`X{g*rR)7wW87Zt=%9s^wC7bpjc0X}RS*j)^m8UD1-sRVMx$^1$&ExjaIK1v;DD zm;YgZ7vQVDff(9LOgp8hBn*VFVM_EnffYu`owOBRaEG2rOVjJolhEWZu{_I;OxJ?@ zX}Z?XfZUU`QZdh#`b+%P$hGyS@w~BoXh?xd6cY3f;A1IR60G!$r1(F@BT&*0Ng$qT z@%=p9A;x9gF>y7~glRVJ12IF<5`ZZE*dRFlQ1jbgp0puZ=|!&(cj}8K(DoD;q^60) zgNM9|(w1oySQ(f)n)A#|KOkN%beE~69i#D;KOuD?``j!QT z2Up^bUf%Hjr^GI7 zrHj4PgQA0HOE2{`D!C`i>!p5x?dz%Dz_NR)SFCy+q5kCT!#pf1Z4K!bXq0$&15jWaOj znm`J+0!9W=lH|xfB>wyJ8KekwPVl-$6p;fV8* z&{c`Ng{sv2mZ#I)*7D8K&N+v?t=GT7|bI} z;XfP+|6wNdah3clR-U)z13f^~@G#gS7a%ScK;f4$h)DL3QxO&V9Z|lo;Y2(D7wx0c z-6&HzhnU;yirA^mdIz*~xYMdov&y}X&#&afBILG@vkh~fmh)fYAbjF{nm>dpXm#M` zqI?{mn6#?=b48(27)tftrQ9+DN1pS$=B;m=x6W|Qkxh?Uz4&AA@>WF5&#H(ZX-l=yA!w~3KGG!4d@TH0qA}|a-x;Q2yLYQUX zWIy@T1h3oVU`@4W3!h&iE#P4Bl!!MEGrIz>nQMp%k5Wak{9t%~i0o8uq~g$U9ZS4Z zuaUj%k4<_{CowLN=TlTsS5c>*#LZ|>q9Pe-M9lVZZq}Y!tg-bK-^4j52g47E#naAV zxA_!V;tPV?B1RXg{e?<_lgGR4QzqLp$g_Fh6T>_};9R#W-?z}&D^_o+^A{!XVc zz#>&9sJ0{ep2rfWsBYFYj$EYnHNESRb5!ca4vS>A{&531TAi}Hsf!c&)>g6H^^=sT z2>nfy|1I@{_05vX>>1`6YXC#{fK-US9LwA6(||ONdPSQaUE^k_rlsoIt}zqO37dUP zi_rH@O=o_gxM^$PuCsapRr#OO)%3}~w2i{! z){y|>-{Y4zVewlG2Ds^{>qHDgdetwgFEGMI-H%#8#D}YTV&OBu==~DhZ%r87%jGKQ zl>?E2zZ9wPVpSgXCB{at3uwoka~hvV6CrqAxn3sFQ;N^^shgPJNL4w+{Npn|RvywdCNCR8K6|vJG);I% z`BF8EmgO{Qm<;#$y(q$VBXB4giVDTo4naR%jF7@8z}E2#09oG!6TAxio}Dl-zk@b< z9})sfl+SQ7GO+jA)A~d}12Hkr$z-R&751oGli>oMAoe55cP$NRyc#c)_XE6>gut@r z%Ht+f*MWm7pexiBvKN-&k!)UOYtQB{v$@%{Wwtcde;KmgEX!cE>(@JDZrShe^sj zs68{~H}Dig(r@J4=$6>nd2uhF)Yh8bIWk?>u5jl@XX7E+bn7X(poy~Il0g3YEa`$4kV3~JG)2BTv)ag20TlfwBLQ{1kxaWk4V~5aRd<=KXq9sxHLBHcy(yeU)s; ze8Xxy_e=uZ(6T(oH<5?=BB}j7^gWu6&Nl!j(O#1YRL25?ZF5Hq;xC^E2=CZ@LlS%A zd3!Ru`*|SXYMuv@ZtU{_a6vc>QCjFr376<_z@?wJ8`VBdW;#oH-kuWAor(z;5-zaM z_5&!kU_a1xWq7b`^M3m1fE9K<0@hujY{nzh|E20(ZiTH?)nkGh z1!Xe>HW=l@z61a3b_A+#lPjTR=EDl}VuJb&xS6*(1mJe5GVR@tnjFA%a*OI?rkhB1 zzq>eK{yJvKp?tXFTG%&r;na?-NCzyCUuST1$c!2IQK!iH*fw$!Vp@8e>2-j*sB{Kb zO23#{YZ$j%RC@M;){w#WYw^AxC2=Q-MI=HHRwee5xC@#N&oPhI;3VMy>)a&`4&(Zh znEQrS&Ey#)o<_DuV*ooV{mEueY792{Z&s}_pbDr4cQjE0fJi=e(auaS5fqTwL*-p*15 z<^2=w_9igSSAb4q2m*R;B@QaaY1KPOEZqth{w<&{oCxPtr>oXHZ3djful|vA5J}Ed zbFV@7z`g`3(Yb}~e9)e4 zd61hD;;H5nVX$E&t9lU7-bHGIgH=ChxAe{BzK+NtFh43eDM#d42=|$p7uaoXB7kjJ zF|q$V066Kd4hC5d-Q>?5&_#Cj69k_eKxowb*JEwr_oL_LWBiE$(bkmx|dNhwy)M}~qr-2>qCuTT}=#rWKYQ0%P; z#8SR`N5FIbMhUO?kq)yJwqG6ArHg)EY$v*8a*~eM$-Tv98{v=NI|xOoXY)Vovq30D z{ThT^CE6?bA7@3(5T*o@i0{JZVJ{uCSv$szs*!b6fi>)VC+10v3{;iYmeG&>nXUi8 zW|8kIn?K%6G=4vFVTY$dUd#4RMsKCqeC=nrhV z8)7uxk^U+$xgqviYuj`6W=@|Kc^AX6u+r_tDm|Rv4UU3e>8GtrwT#}`Gs)a_++Diq8wkvcBubE)HEh6CQ#Ppe6Q_dS``|bo>b}#~?^7VY zB=Hu6ypn$;uMkIkH`r)rM@c*nAunM!(Vvs_$I&mQXN-lLg&s1m7a95aV}isZWBxwo z$&TV)E_oJ99Bj;B=D`SM{+$Q$J&BJcBr%sn35jte29n4o;efDk0{O^S z(vuCF|HG;V89TCPbB#{6E7zFB?jx~^#C#G#5>rUzLyUWiloSo2DDzZx(AfJ(W1+Km z!Xuo3M9>mtEe7vN_-;T+A^tU9yQq-TnO!`}(o%cGD@l!kMWcLdf06th8&V|CV-0@! zFw417ewWqVARpMUT+P&RYD@c1Favi%c}al{Y({*Hd+s{$;M$G6<`FVw_Ueo&h9HVj zE`Y)6_4H)3|55t0K?l@rn)b!1M=54l!SmqsEe3{ffz%IH@Gof@=HkX-98VaD0c{-c z)phPj2qzL+t{{E23hqUvadKn+#zW^)HkN<+%F}DU3WF&63yYjcPed&xNviYmR|v=^ zHTCTTgo|#GZgB#s+TFK-Z8x#2>c^(@9bxPMQ2KAlBjriT%RtvR!Vn&e{8<&y^)IOI z0|EL>WG!@2X;BaMFdpw_m_rlfE+}REE3y`L!>3Rt<*~zujO|&&Ae?PFplcwnRtPNfILb?M$gaiUAzsYnM&u)lLE^5?(EYSZ5i?cw&z8gLpaXGv^PFb zjZ{9rrGPDe5evk!7csxrK%@+bnIXoD5Lbw`e-TDS`inMuiqiUHSn;48J9#7OqnxK@vMj+(lwBM90L~Yl4{xegaJR?wI=;8>CXD<{O!hPD;1|`9cP4!6ZI9)ntiX zT*d~eD!216duR$iznTAGk4`mNr-GC9Dl}Z+-s21>kr{402QH{@r4g#dpi>;EbnqZH zz6Pc=`mf@4gpEPC9peYHutB@!E>Y{MYPalcGVDUqeSD+wc7%*^Fx%tMq_W3%V|d0f zH>N>0eW$#WIi8fy&Flh;DB{l+CWcU9IsxdRg+X;1CdTt1-Pwe^uUW_eAA}?&n@R?v z>?8Rlq&2KZUaudZ{QfAJVTBv}B8Yn5M8eV|K#|=l%~H-+1icB~1omS+T&LgH%TD%L zJu*q&B=IbXM@XzAaVv>gBqoy>LZUlF>N`B9Cwdyf;dMN6iuEVyOSXF+qPKtWKkUJu)um%B|0O61 z!(M`ZkVC>p!bsvz(5ta;NgO9}2tt07Ej?gMkBhv;#caj_oIIUA9!a7v#7vGBjlAv& zsGnLFuoUW*6L`k}aqmTPbqJ2e_OJoIQN60#iL9`4)d)QB1h|~uM$mc%w8f!vCWtA& zg;Q~xv~nMco}$ zgEZ24EEzAuQ+glho#!a$VU{90+3)M@yS^e&S_jtg<~PJHoRHn@>l5f7M@bxjfNQGp z1fWghPM{OqhAnIN7#(IJKzyXI{J;(^kW=K1{13}K0k={ziT{2A@g0d{Bo2^xjKn4g z=uP~r72>S33()={MDo%Y#cyI+T`5vGRxSY1#)<`UBAdGaY#TEd$jNLHZ4D)H4T-i8 z=(3mQMstKC`X^H(tkwjHZ>rFQ# zNVJ+egnObR(i;DZayuWR6YoWZ>{Y1T8UQBsI+(FeC<{NMa>W}!s%=Fe>^3;$rXft+ z2MiLaDL~j>Kn_D=t$)VmygKB)X7rlh8w4cRZ%^Oh#y#9@Y4m$1|Ce zK~h}T981m!l3RpVRbF=TQ&69r_!OP zH{=f`U5c3kC!yFfBBzL+;--G*W=^g#wUwDOQM{!2?2(hWkB3j<(rZcFLLx|F5{bbO z4PmLJtI%@-=cHCB6F>l5K(6Ym%9CJ8X;gy9t?mmhwph>8des8xfa8#5nWaimNtmZT zk`KYpdN)AEv*pR~Jb?oSBThjenacq4A<*G%?d0C|Imj3qx#Ov_BZihAU;Qp439`|z)pk#L3)k# z?x;;?y*g@>SO$p{2>&55ek=UZSlcGiP}dOAMsT`fgw9G0v7{LmvB9@xe>Tb}bfY>lJ zvDG$Jhpx|D(cR*xyZPj|B@-*U)y(s)#yq_ucptxvA0!m zKePtyRmytRyU3n~V-1;A`*H-*dpre$^J-)e2+=m8+(~ z-Fls>J!-uY|G?#75Z?-IK@o3X%QQ@P$@PaHKm1>OKmz$kBC zX8MKyWaR&el6j+9!%;Xk<{dR!8#q%hI5}~7)vr7@FSdUXV;M9t6#-O8L1p#%^NYfP z`SaZ-{t#dw5^&73OUwZP9Ef7OD=ypTmF;nTkq70ySDvk*#g32NDA_9_pxm%hIz^;R?dy`Np8QlQHJ4tVyOlUmFDujpl@CQF0APwGVF=&ZAMYE?~x$- zifRuMNLC`$S%UeTs0<0q{S%KRJcp%v9cts1A(k)-=3x$!Mw}YHRKEuMkmtOis@bJn zlqB?*vD?;yZmD6d&aBzNU)#ttM#pGzPr*vOhLS+)7kq*Mn>#Du`_?jDO$^s^du*)5cUDz*cbe#dvdgBgVW*gCG1A!{6(z`I+JPa12>%?!odNV+az$`}Y zlY@NRzX9A}w8(quPl^~i(a-($6@J4H;>n7iHW*85Q8;K@&AJ~mIyem}%1l<3)B~rZ ze_XhNawIq-U2?XR1Bmirxd?@+?~yvIK2``yY1(g1l@Q(Ldpv$1x09lP`{ z(hvsKt23K!n6KV0H+89Ve*@rzat2OMM6BLH9o+}O-WtZ)gJ8`hAX4=O%*YoIo7=3q z9cJXsuxfgMyH$a6>ocUNJ_VZaWzZKWl->`%@Kjhhzr!1TTzU=u@ZHiw@QB|AUGT>s z(m#TJ-{=s3E;L60CX1;oSd!N86wgFLTWtvSQUZLEtOM`>nM;*4YyFFNlR6NB`)lX> zHu0IDj(|jlLowS2#Zf^JLt=iNBCb*zuJeg>1j|2HwEUOPRdo$?&~QJfcb(HjOH0Fz ze9EY!2CR@pw)U6pXYg4Wc{iw9-NdV?%WD z)jN4#iXNL60Q3TWClBKTgPOrB2^M244fZ`(X?wEys=flGhK5SR_0?sDzr}B&vqA3~ zs&y?Ehh>f~3*vo*s@QF#<8{1FM1CC_{aD&6Dk#ke3tG}9aZ8yakj+U;K@E~l(Y%qb zOnXP$Ee)xWS4y}IpC}<1$4Q~`!}WN>?oYV_jPO$pnBf4)jwTm+mxv*PJlm2QK{{=` zPfP*SgzSa+^P!QXZ4iqls$+%3fY-mne-Ww_q9xBptmE~OmQXEf6C%vxNo0+q;%)M3 z`eSFKM#VefJjb6@HQmkT6;^9>Bjv_5VzCRALNVv{zbJBGk1T9G4u$xRO-9IcZ1?D zD`DJi+aYjVUad#6Lw4XGwfS;$;%MN!$bBeUL^ciu3~d7^>CqgdEyK zXMhrub`$GUWb|;->HK;muoj1^;ipAHbhyU$E+0UxTWz!X3$G6cIuC}O6|B;8b}*dV z+#o>4bL*>+w(A>Fg=&)taeT1OMK!H#C<5WFl-SM<4>au>}eqxZ;@mTUywe zG4amKd(r!nTURv@%f}}Yvb!7QJ<=zjDw=#}ieoT)qrJN^zHwsX2;{bcW8>(IILpS+ znHM+S{>{;i7r)-5Ep05IP=h~Lm$LEp)9?HA$_^<@zCn^ppv=(b3y$eC z@-IjRPE$MjHceGK#wp2AaEJw{0Q#y6#~u(0!#!IKJ2AG3d|Ob#_KDs!PtoSo;0gSKuC zK=9CZJe-&r`*oF_sW?turKcY$T4?dlqN2|R-WL$F#;RB4?Iu1$qB~-&wccu~VS~?# zCB`&8c@NXnS|EZk9RFLHrg???8}`0wO_@er51-D2qY9m`ybKk5?dQce zprRnJS3N|G*9ue(DhYVa;*1JHW?+N>W`G&sx~nw~WJy&fi#&k-r0}>a;w1bu5GE1- zZDRk})1r<2sMki1BmjG2-z!@B#GW{WD)OOfXYZ>u_M%B1S7Xb7XJEHgnjG>qYz+R8 zu&4D9zpWhktL1f?DdLBhb0xIOF_0N5O`gEDG+YaST=(%Q(9APZu@8GVSnhd>#wiHr zO6yC*sRv?rUX0y&L0qJTmri_DNtwSsggoqOJ}WmoCebtzg)PNwcPI6q(nFOWL2mmN zXTP`u_U$aFX9a*wwL@`i%9=W%dK(#|k0L%aA1<9KK(-D*geVEC#Lp;@{W0Rv`(fig z2#^2m@Yzk3hah{O6t%zLxjiLadz2TQ*aAxPn#_rQTFHQ=uPEY+aO7S4e!ikv5EM3@ z?_;qj?9f;Qt|6?G2Z^6d)m6yvq91tK{s2An)Ev+-$`8X4z6(Xb=F2OkOK>(o9;$5SwE7^Tc$)LJU;arh&%dlP=WU~ULd_R5=WV4Ub4COLnE8EU zX2N+CM7*}P4pjilsjeOl4V9sWMG!^gX3;AgQRatx$+wi5y1OP0!aeFo_=A9X>QOdr zL|F)5@feNK5oJ`HJzDl+1Qm;G{#N{iNWr{En;!1&ny%`N%c!N%lF~=jAP1$<@&|BQ zBx0!_gF5GZfiimy59WT%qa{eLJ0eZo*BJ~3>7Hzso9eXb7TK3|0J9C7anh5*?mwvb z*kj2W_|6Y0Z#OMEsMur#O_Y7C;ehf6pOd?jMQ{n#->44cGm+|Vvr&|Cgwh+I(Z)hJElB0!R!q%JFgBGj1EAMyBA4aAN+X$|;G&j?PVgH0%tZC!nWwyn$ z0T!!EOup6Atk(AS6MRO*8N{o}AFGdZuW))OQL|ICkeyEkd(F9IYZChu!Z)9fSDeI^ z|I}jMmxFL~*31Fw z`)*-b$<}sBNk{m#1M>n^)xnDSXM_DyWPX2QORmFrK@}ZlUIWg@Fr;@OLaRk(~9;3j^VXic|NNo zRWF$io+oE|l*#m;`Gu5(y+OJ>_&YJja)_P*Ev& zG^2zKY+PhKhs`JX(24l~uPSUl#>Y%cE9D#@+Wr9_0U=}$VT_f6+pN}C!k;vn(1ij% zo{&|5J<@XVDgtqHX-F01ps90tRb6p8+-<(`@cfWpKP|vly2?zdtm<9GdoxNfiXQqT z`+Kj`Bky8Kdz}{fWB!MIve$_c-6ZyqxR1ng615~|kQhm#4+O9||J&nqG{B0jgp0Bk zQ+bW&TQUC71|m#Q^3H7D7nbgCyo;0Ni~KgyF+Hhb)PrM!*Ws>5rD3NS)1-$33uPE3 zcG1?W}ZLVkkRRg;hMKWyl5bm5L9%p`uH9({tu z0TPdpSWcpn#CQ_DNw^{8SNY9O-Ad0bOPWH3z@NczYruLn90*!F!p}bdpY#%tmm5{L zq7d>pByMCt9ry#dO985DL>zq_^!s$EFPC8G9zx0n18%EQ`9Ye(%fhj|^@#F1NGK#O ztV0}lE*rE15V>{y58Js8;pR;wZh-)85C3o#dw++qD?75o=wMAG9wf1hLEX z+~)oK52*iuin5US?{Srx(AS|H_61;vvqIQ2O8_Xhb`)5uw!=GY{&GR>BtM_D$z0Q()a_kgeTQX0!X-tzaC6DTPp4*ucw^Vlz+=j){7Y zi;qX3itBv^A%a|a-V`mRD07afgd!g2ShtNB3qk&e9lJ|OW&21x2q6c=hb7{}Z#K#( z%R*u=2}a^p62%Zei}*JHQ8I`BVUCRe6F~E@v$Go@j*)nQ#5NLZNX#WMgG3>T9wb~F z0Py>Jy&NyBy5^TN5uRQY9}k;9qNi^a9qk}(JwakKiAIQqh4fl_QL5<$xOCoA4gzFB zFQyW6!x;EfdxEge3mz5;bHvwB+n+~YzY8GJdFbtvfHUp|r8gOY_CEo(_zDr(x4?h> z6kZrbWh>-K@Uga$O+40q60!DY;a^=U&8aHk6Cp|_#v$5S7OF|}GX3nhRPIkfZY`?( zfKV(_9xU!-{tjUI0&2*kSoU34wCv=|a^#rt{%Wir&JlbrjkJN*G%(XVgf9VTqTnR2 zm@81akt%CSRoqBcT^;98bJc9zV2jOR<=)4Fx=MszQJT6AiwV48Nfqqqy^3?F_*%FL zbL(o+<>2T{x?X$-((H=-o|D`<67+#RVzzm`_yW=1joo&yVs~anen983%wTrY&(`EZc zuJq977zMyb$N$0h-lL>v@hbBLb(!Nq$$~gsI5byOl+*pjm*p@3m8cx-_zx?;M{(u- z!mk4DtEOxYsKmqGK78CEMi)$ds%3L;%OvptGFR_HMAMD; zKc*N-urzd;S4%KyUt47gw4|}pE&PKx8fJ#|# z@zABC4jIdBS2pp~YjG4WL}KB{r`U!i&EL~pe8jTuDs5|9E>87F8co`?SmRcHk3LhD30H{eMBL21bMfi`>`5st<1^iTkM z2$F5QDuetxd{-X;srrok1n8sJf%UjbzDXVlt)(m6yGA74`~U^;^$6f>u{2M)gwdW- zno{bcky=<@+YZXKw=b<9h2{Rv<3oP$-_*wnF|7hO0e@{>O?+GS$mg22?BUNf$!r}& zvX{D$ID{8y^H#DEpKDxf$mbe+*Zs62(1++ys03F?vmbWh{HZNVpkj_g(wk>fi6(aY4@{xmSIl2dl?Fq z-NR-qQ>XOczpNO%2UH@pFdR^LSPtctXJU8>;sMVz{w%1eq9ScEJG5AB@kN?=0ZT9c zrs9}-mGKVt*HV1bpG#5N=vxxUNgN`vo5Z~&mXoL>QAA=4iEBx8AYmh+koXaEF#DXu zTM#K4^g3Rkxv;#h^TfJvO~_lYeUJm3zg&r0sPH0ShY-fT3tUmRfGuj4;zzpOF!5a&pIPU1a? zX(M@02nXlGv*LHXM-yHls?i1!R3rN}9CRJw4;uI#K$N|lE~k*t>4MiG?N#2fW(PZ? z#yLvIs)@C-5IS{@Ij@W@JeJ_%H6IJBu%Mw&=kjY+l_6vlPU6LH3jw+V@DxFaP&ny2 zelwU<338FtKeFc!%mJi`;}Qz1;F5-Kf=3QK-|)ijp$0dW*Da0L9-YOIg{VdG9| ztnw-Plg-AS(%4u(673+exoTDjI^1BnFNY66u$)V&3@`b+{vF-;D!TDyoYGc&b~@U0ia(4>L^wfi2_**Ql)JO^FEoyZ z45bjh<*K0I&obwg@|RFq0v}t6;V+um3sK=5JTK+`8VAP>#O&XI9?f4dIfZ#$bOe_! zVR8&p{flEj_dJ8(FN5o;KH}c*4g7@_j7>kQJ_o{Qr>bEivOh`@0lp6Gu<0-o)G&)L zz+e6$+^o+cC2^xXPxiyLa2;rAGGS6l;F~90_8#=`wJ?#xW?sEErd<0i^b5enLn@&6 zpU6%*R6kD@J#1p>X(@%(KkgoSw9!VYg%x) zayWpHMDInQw5s~jI=I9wqPx~(5)D;{-0zSATR0DVEGS(>Q}?{g`S36$?B(6Kxl{q~ z4fA+810SJ_$~z>eXf?*+RG`9_6cv4j-v1uX~<*f?K zq+C+I;RG`GfM~u5`~>+*52Vy+z@2sy#-h@=vnd%SnEUOYv5u@0XfFEKv3^P-p3kguJQ|NUl^1=PSx=5gP2L2l6KaU4-c-03Q&~U_u<8 zkm8j6VmIX3Sn5Ys?I7)Rp3$IGH2BEnVJ-^rpoL&(aD}>`1>45i?ZRD@lB*Qb!Y#fX4|;?$TG(CGq4DDy z$$)(;KdNkMTer`Oi&ur35Cs9XYwrOuc}!amz!6cQ^?_LRB_sZJs5b#Hy&54vOTo%f z35Q34nyLI(`3%^O7l84&51{EwpnjJtXCMH?1&)f}H3U6sLn?(k;g3XwllChl9LSH* z`zXfi4N6#zKL*Y&`uO$q-ix761t8~mlBfyN7PQ}bh)6fmQ}8x{>pV6TJYe z0k#9L7ouGn8sO=w2YfIyO3jujr7;KwSNbz~)H`1Gi3%1Gc+3+{V?*DSn{=a#iV*!|&{vTY=@(vsGF)8_?&6)d8*xpCq zw-^qg7N2{)d}$CN!6zQouA#Oi{m$^fNi<>R)6SFCKE++veAwmSj1I-VDkO6CenfM& z_`n7ZzL#QY_Ch1#gNl8rFT|J6$CuB=m(TM1A9mW*!h(|VrPIdS$B1k2GjVAwEi1Wb zgsgPrit-q+Qn3qxkfN(j2kL5KbfrxEFb5d3hUJ)QP0wuiY1~OG~VLOkBGPc6t<6<$F=F zD$Sx?MGLEn+B{K-veherQ>s+FbPL z_5}`Y3_ry$0w@i$K+gR*{EHg_;r3xt84fOiBy_gJ&|q$7EB!oxYe%X%kn7%qg^NOQ zu7c)ro-!H~Fv;j%#{jF{1Go8F4Ny5L_7rc8n_Sf5hyVkqHhBLovPA z3JkhvRE=?w#FT>_(@1Qt@VBHHu`!hzA`CU~HyS&zJ%w6BIe8N?jX(gmoQ=xK;>8IL zhyD(%P84N(j4l_}is<{6hpR~mm>dEnY}n8T)#JqKCoT5AhO=qFEk~w|q|;E#h?4TI z2q9$v>c)tn$EevzxdwU|S`S2BC`I;s>>A04{O=nx?Xm2c z*gk`X@KQ9!qUZ|Q7$@QA07mUa*gKrMR%xg?0vKl?oCAU0!2JHDq568C1MX=9W3-s; zfZW~5R5gSitQ1jSn33g|arH*^VCq(-@S=iq5j`y`f@`hGrPy&Q9}mj}ZdC#aEaOl; zP*w*62%K*APQ%ocMMn>yXDcPSner&ZDh))eKWw3Qe~S42pd}~vFRU^)A9gsT0gB&) z@iSC2V6uel?_vD7y56`Ol?;k3f!;;2ET(eQ^d=W`i62yLHRL%aRWKCPZN{En^m!$! zyONB=mUmF;rCXAf6GDySpfA-Rq&{MK7yCRs5kRPIg6Vl>*MOA%DfZ=23V>p=NOz7? z)HHKNMwY{ICf4lqtpLA)C3-neBm7BmJRG~3%#5H1iN1CQqU3GLB+XpKhUkX*8ga{f z+d$81{d(l`usU4~4(QC~vAS-3fmhSZ-AlZ<8cag#6vMM(=py$^;bN3|OjKN`pzpjaF!h90mCNK_e>cyq+5$L3mw7IJD4FN}cBr(_ZCISLAZhNF zD&YQ|pf|g{COt>YUYs&Yl>1XCXzC+Cu%LO8e`-5IrdDVdBc0M%_@;6YRdO6bz#k&6 z9b2&TCS>Tvj{Y^-{Iin!*3kalkcPuGR;X`chGt|5>EjB)(`eqb)I z)P%L41J=bEp7C|j7U1<0$1)wgm21S#Oox*S$JApaWOeO_Wz_cd-)g?%sV%_#5}`;g zd#H*5&7n3UTV=W`&dPM;_v5I@&Rr84e9LX)Sj918~y_C8@aiG4w0rEx(!W$9Q9LXLgkz7$Ax$YGkG90dQ>ZB*&xf0M` zd<%6zZh(})TX_1pPG*%Z?y5P>Hjm|@c!jN2be!gLo$2pU$yr)Dp=Er_b-sprj-2v5 z$S(-nY;p3=6&vvT*kYO6&sxpb_hW#7eZmj(Pf8n0ItV6+0XZ z`PxXu3TZWx@o$o~i!m-V`kPY?@^p~aTS$|K%kd+54oIuH&+wi38=AZoG0F|$V52}W zRTM`XpbA4Na7Oudsg43GoXs>O7W-@AvjOr5l53=nyu@{RdU+*~k%7@43?LzohsKyV z6c2JWG$G_iX*3=_S@obs#Zt`iWRuhvi=&wiyY*V?{(4O* zWdV3mEm2;_>OX{~$#I4{_sYGo8T!?TOU%6TLh;>ruq`(9Pf8Kje4B@SGT-Fgf=>3i zW)QKF9!6@!TfjvcLMo1lP$eaU&?m5aQ@*n6fb6e@cs&{si5YPFeg<5BJG#{kh_9|w zD&X+#tE9s={~j#eyE$HKr6!>Lwpnl2+Xv_e6sjuAT+|D|3<~_0I-FnFFs_jatE?}} zz7zB}1?rdkTo&1&xjT0GuWY{{ZVKYhcUJ?Z@EtAe93mky_9Itw2WqJR`vUD(#6?#F z7lFdA7)0jP5S6y@LX^`nXQG(Nj;_v5&CVygp1VkV9FSGIgnQ|7K&9Vu(%PHFtJ#i0 zgKlE^HGUTIMZxc6*PNu%_Lo?d?XV3@JXxnx%66PYz|Px~E-2f7#kg#TL@jsj=|mj< zo_PMw%HI;7haFC~|NOm*VM(3mBU6>_C;mk7C*YbN6YenusxTb(u;k{|iQBUrNZ^s> zus|dokI7KEffpj2g~4+!ir95%q(+?n#C9+u8L=e**2~zEy#R1-gh68o6ur>^+w_AZ z{}UhxFRN{c^xvj#Ksb0U%b)$!bf|gXBEsYisCl;myx9zHnR5~8KU_HlbPb(;)*}FM zwrTd{YPKWl>>3ytmuY|SH!KeG077Pmpiu~=Jf z-WONc4cyPk2@T_iX=#tGrXE`%8o5%7;Y4YISO)-EhdAB}lb^3Yy`G|YR zm()QrH5z9vOsXxITPKEUYnRpdYin~}6PX(j9P}sHp$AJlaoT!03FEHj`S7JOAC7m5 zTJLNiLE+p(VR-Y?^w3L<1YkIzc<3>|-8uwOQ>^f#y6C{29u zEWLzy@q1x#UjzOVinf}9i17g+aWn((`8x|h&#DihUtEW<+J*2*4#epE2ZBvrLe8c; zAo5I!!WmhHBqT$@lHg#5&Q5paU7UvPE8V<-`a&f4#lt}-3c$e}T28kprQ@Q|a=Z^m ze{t*eR=Zerz17Ry|0U=*&?4&)jTqGbCJ#@j`47F?66|jDS<0v-l(5gb^B0C`^qot5 z{sv!DByYCdU=jf52lRcw2oMUU7t8u;=&62>g_=qUz+GW`3jjBO@G^)CHGm3Z2=e|S zVuNxVPMV%ed{r&@z|D2uQVdTr{PkK034~Sg@ zbDUtbz~VGes$7Jv0c7DR@%ezV$D~iW#wPn3p!9%Ueg}Qd5}$WAj5U52Vp#{~$nhF= zpjkmPfn6WkN*>d06hoOiH;Qq9&LMNdXIFBAh{6pQ25yye#}!8-KF7`6Y5|t=`;wj| zwYC^}&d%U|gD`doIUZ)MFNVhCtMcW3%Tp>#GkSlrDh*q7%8F2SMad7$M#PYV`nc zmp5zHz{cnPHl;G9(xZ2G-vk)GB7P!Xb!-)x#|;jKJ;-KX78*Rt`jhznzsSq-&3_FU zvro4zk}Xh12M<2&bo*Z?R{TlhLf7w4bLdal*7f+ourq9Dh?@nn+HMin%+m|4Y%uHk z`7mc?kDm{7&gk*;!co?z#Yp=3aQs~Kr6L~u$4&jU}(eye9ip>=(?`dj9&rqGTc z`jKtM$*U{6hlA-pG}^G`!@t#h(D_=S;KTnIf)OSZwjAxOO{{!h4hZxjr`6Dbh@yDv zBy~@2-fXogTT$9s`Vt?!k(w=Dy8*d@pS{6q6AxnT?7HrkG-*XBXdB)A2on*ZUI(Kr zp3E}gX0Y8$||JQg`HA?5rIjL8d-weJJ%;aZrp&rk57YJn7>NZKcq zhtS-wXIZBPh_Z>0b^1fr(P@5TqxMs1@RI)K0))e1U<73Z$vS+en3)>j(wypF+}whE zUp4Nd{O>O+O_tukfrKSh=#r`!GK%fTwZ0jjo6W zof0xMl5Z{zDkzQVz}zQWL&VeJyv{U|~ zbMpcDy|Kxp3Od&b+d1OsUj~nO|1U#^I7~%56+5Z8jfxFa#8AXCyG~4sof_`B$sSR@ z3*Ot*b8o2UX0YdGqiiZ@c+D_bL9tB!Nlr_sA+99^m)H5lu|Ew)&Jj#4FX+o-w=k{4 zcobT}u`7snux*qNNYy+jJ=bGQ6(SIRPr| zYq0zzQvNg)h-4fHasBq=hHT|mUWjLo8!WM(yBl`GomfgwUd>a5>^-2h3u6v)Rwrw} zL|cy%d-_Yj3_J>S@fNTbU#yM7q+AM)r~a6@j)Q#k?H;Kv${@g;sm6vv$INBqz_-AG zKZ&T7tzCH#hQV}0ydbY@_5(3+D@-?0?GIX=wwJzNKOSrXjhOIZZGjCHpViRH0}JfX zh%G_gRLrKH^Z5G&8uB|cCA*&H78DYmIbI0!Qs|q%H=+21ikGO^j{?C4eAwgiurF)P*7+SQ zJdoT1$8_GKWK}MKn_ho)*V_87wX3?;uIyU7qHB$lQkMYN-YKxxio#m6MVZ125yI8P zJSrxk7%_o+qd&UD7xFc7@3S#XrG&)su*`{*Gm6`rtf>rDr(7>yUTn58<9htKDZ~;I zNnw;{&ni|F;#G0tknESmrHjq^vBUfYU_EI`%IjWb3Lg9bfr#~iUfKL!;#wP(4Bb8KA6B&&;YPJMp;__&?G3nU$ z^>Odxa7{!7rwyUwuLnO_5EO(Hpp?21JM$k5*Du1){xFOq8xZXsh3(M?62ekgA4jP} z5D$_DZkxBjRdzQ(fe|RC#5^(xafNA|&iyD-R38FO@IL?nz8s*1i1sHxe>ad%=A|ZU zeHb!NPysD@;4&- zpVS6~Tmt+BaRho@Q_T`MXR;f)xrC|$z}+}maYpi2-gui^Sf~oovZ+gXvo|&YQ`dE`UJIS}#~v5O(ie-m?lEo@uv<)!{U6 z3W!y}bOy4AygS8tVX$D&3xlcWA0iiLrotgySQ`XeKHnW+OQB%i(_|hr62tP1Abh<; z9j2@R17Z;d&ykv9k$b(vnOVJaKK_9xx{qtPvf6shIC0nwKG&ukqd{EtBXZ;o`oeIF zSo*nP-`;1wFuW*p7!3z;2jUUmMp)TynCGuU_y{qAR3aX+01kSmHUpNMH;`v(Cogg={lty|~K|4g?C}UzR=bfaE`4jlKwCVBP#HtH}KPHHXX@K}} znlryLpE?VU!l}*)2h$m=(7l;MGl<+o@;z{S8UKpk5RRXTm=icIoh#F{9z`Bh5o#VP zLemfhMMLgGvjI*=i1}x7JM?4;9)d;viOxjFssn1+=ANS#w;EJ5FU29{+&aqim zslBy;k|k6Vh&DPO6C1{6dBinivogdg6n!5iGKvy(@Ws&vZ%GTtkIY34Jl90QY~kHN zV}Pjm&|qa~bxAZx#sj=Tzv+891e2H+_UG;t8Dq2Taf(`y9#FEr=aFaQesqD05Rf}x zTLA<5NMy3~YAw)U{|j{d+n6gJM3CEMY6#?ml(g>@)sAS(&k=3;2#lAPD@(ylG7iFg z3Ig5U#>{XJY?YC=e)>_!8&l->MXUWa0U9+s{ix#jK})*Ge%#_xo)_&0Ee_=XEu5U9 zr1KycbKn;a+ginjgBF+Y9YRrX$l_G?(ISWA0=kba0)z@$gS(ITtHWYLR4f(+h^su@ zVR2I7(A((_Ha`NE5ZQA&UAm`~l@737MAH$Ut)68sheLj9xWbwXMh+dCIXC_z+8#E{ zI}h>W_Gu(g;YUd}Asygv)u~W~$ zCG7AoMz5RfCq*y!bFr(~={QHesRkGrz*XDqE%HvxA0G`j)%jCDmMt5+5#f-|ow$)J zZ?C>SP%xp+53Z5=Kx)0bk9wR3oSx;yPP@~bP?esro+doBJ0+niIbl6XygVK8!q?Ek z8k6@|x1<3+E(tdR5C+0Z(Dk}}i*;yuz6e|f?w{m6az#1=`!RgLFpIe1JdSmv&2FDL zXH4i>^*O1Y`Jl>%BlS@b*IcDt&T&p&z=RtZI1XliE0PT1@ zPQG1@V20sb3wCGO3wDvAw7b1A3Z>cd$VqD-7O(Dr+40344x53JuUXo~#vKm3SV^^E)QWl7 zOsWXfBQ!2(xkvnUuOkOjAr>xu`*} zSq{maZMhW6LfFE*sNJWKmACc0(^4N&Sv9-C!F?}o2ZdGnrx=XuQ;}0}SI?uTMk5i} zyGl=5TOzhSj&AuVEplw}J`u-DfGY<<6=CqHK5prsG#UI{cwk$b81lG<)CVkVc|CtI z8A27liMubpd*=tSEF?qQK+QrjwC&g4pMbb-HP+=YMyBsLs=)?3D_9>U2uzi{A6Bv+jW>_)u+WDz=FUii8NO-10rtV}VT)`n4$LxuVvriAbJVC_v5_9Hz%#yq$|BF$DIR_)0eBre(m zd3ea~ETg!2SJqZhz9-8mns#MbMDcE%c-5|~B;nbUWmk66!Xdt=*1nw<{XKDn%OSjf zofHfbF)=0E?~dyir)!oIcgay8>z@Q|&Ob4OtOd$J3Q@xmqwmsY0MYw9QU!j9i1TMS z7uPi~4%MhLRU(JY00`@2%ps4#EJV3}>VR)3QVKaE@^=U_d>tXvyCLaarCCn4^M{@dfp-(M*U>O5Lg1 z{hQeNa;p10`GjGBqT(I_-OciYQ585$!hXw{CsvH={!yG6R{QARtM-a(-#1w~H!&`{ z6!I)CQ58h8?LF~>xvm_s7Lm+HWj~gOl>rA2^KRyDG4_2^@4P9##ukX?nR^qDK{~OZ zKN`s$ERMftvU4`!&Z|tIK_K9dWIiHZe9z?M+^U`X##1|uWbUMtR9$tAh*?QI_jqD( z@dwkzs`pH`DYAQp5k&yx24ta%D9BV&ACMCcToqt`1t6l)-=JrjS)4Th7-Z1z;;1m% ztSLCx*+TU`cD)IiE{FhkqB0n`u)mN%^53xMZikz0xvwbNu$)3V;iXIYH04tbkF!ALiQ2W+ z48z2j(>rGmewKU@viDm*-;J`!*o z$byII`NY~R?(%4iAlmWgeZi^+2y{ULQR|)5;&+#NwBuEz5H@Fv9h=Na(k{T8*K9Hy zba~pdd9TxuIhEm>w98lox7dKpDdN5B%r<2JFGTN6X1hp15$i86NvOu4KW_}T16WQm ze4)_DyQ~Gk53>s!wVNWzySVjWi?VO|q4j>v0|Y84aK02$LW>uXMNnAy7tFeHj(ip} zi_2iCBsLqB8iBWu_^g$p^g7&8$#v$`SUF2_vc4=~U1~EB&4D*1gZ40augH$ePRVBO z_;_=O$Ev0mO)t*xoi1+{?A#F4Kq#%qUJpVhh~F547s|nHC0wj90yYIgeS_MqvP+^4 zUkjP-;zKO9;{ihNiH#f0IWY-1$~`K(786_;%VgJrGZ6y~h?0!6Ppmjc4n<(G#XF6n zyH(exZb{aD27$q+(Y^*i@NOipy&A!dwNUU!L9;O;&g2c)zjlD@a5a0^d2Cc%5tvjHaCfLyvS#*|vxm*I9F@a4JIF zvJP(crR%I#Bmu+1CeB`GCF&O}3dL9)Q+5SUGZK_L)9+ghl{9Sm^kkKv$Y#bDgzsRu zb%VV7&Wgejj)UTXwV)E)vDS(dqbOp94uXOkO8v6?BqD-)ks2`yrb-Bq?L5qFfIWXc zNbJW#ldysn=NMD`Jq8=ol}rSCJ^*9mpy^5^CItb$fxLu=Fx1_LQ0dKpjbE%p5reb{ zuB>SYm_AL3^@BG{!N~UpXhR-Dx=Ap9BRKmaf6XlJSr`u(_?Vp9xyf%mnWM^pX|AdD zA=P@y>G8esO->}=y>}RYG8_!~k`D@jJu8aA-5- zR9->6#Mw{)-G+`YP0WIUW?EkOT*&4!QTXb!n5 zx@$LguihZu4`o|po4RYR>t5a1y?Sl;>W1#sYr0pj?p|FVUj+>QkbESxcSwa8)FaB| zztv2#Yei8g+nrJa=p$_A(G?jli5DBPZN0+?%*=g5zJvMzI6tDfZ+35C-|J!w`nhn1 zvR#AWQ6XY4bQNQ=Jjf5G%KCtZ85v3gH4+~*2h&R=WsP`0n4K@)3uaqRU(HQCP~D99 zl4gH(vckix@=I4O)U*bFsWy!xF(qGlz4gnatX*r{5DcWKsEx@3E|7IGWeS# zpvsgw2G${n)hzKva-R^sV0QN4ct3#fiyh5@CBEdVSb1l#JUF}wi8~KCm}Y>549CRo zhm*2dCSXXzF~m~5jLvc=bnX_IhGu{ba}WkkEAqVm1?%V+U~GE@@a6lF^~9oNKQB(0pC}Wn6V($ zc2?rSWX%nl|42A{T;I=7deq7Mk-v*S=chVE8T85m9@yn2!Dx-(G`gjfgmX_p5Iw38 zEIM2jzOK07|%u@Nf$Kzyq%RP77p?cjGz<1}W( zNd)e2945)#M3#qHKypT*kS;`y`?ZLyM=I~h=86r#{||A3GmOM^WZbIBMgsX3qisNZ zdPlWJM#17d_)|2>!VQQ?z;8Nv6FYx1#C*bmdtEDx)rzrU!})Z)_~4SP?7ibw8kZ`4 z=%x%HrqZ6LKBbPp%rsiF4IM0?>2uK)I5^+qK1Y${I#m%1zSiAoqxrG`)XuQy{;Zfl`jxMo zsri?%yx=Gm)h{@fAPa~~I|2SNXx`?c>3iRP!O>64g9qCMe%5{o%kp!`KYkB9H&<}P z{X(#sj=%tt0cNhxz}|Nd^4G2EC2>04(V)|Hs3vguy~#Xu+u=CB48F%ju;38_(1ECj zpE0?A$@m1{W$kUHPu2A(kyHU#7&#SP8nj}E#Jw23K@kNx_E{F#Z@32L)V z&Y{?n-#F=?@x1`t)CFxK{U*i1R1l>wv#zWUrH^EJG`?|$JUPLyAkAVd_HbS#982>L z!9Kiy$i5V=Z3JYc6oFttATk5N%=6>tsr4-nr}URMjX+|ITeaSR?B29VlC~3~w&@4i zf4MGBZ|PVnF5RN!+e67(r-EzZ@YA|ihhZ>K9Mac;eUJ(MAQ#RK^ zxd(n`=1t1+%aJD(WImHP2V+j7d_8zNC~!#=du&bUu~pP#YrMF1Q7VE~X_3pQNx-m? zb0_Te$`Knf2hcj5iI>h|5fj5sxZ3B1cXK?*PMdu0i{w2vv{cD_J*t?rDAk+P3}Js> zV5Q@JapglvLq}mWkPdJM!))===>RF>IO}+-gtHW>a5#bkyCuXT`BrgwVXFO197-t; zR`TEyLJ|!82e+%fG+u$NdQfZ!(zE2<5N?^a9lwcH3sXJzUwL#RII|BQzvmB%0!mgA2A@2Qr-#+_?_w&^=eGRQN$510LR@()vFpg zTK-A+Xzo&OM0Ug#h#;B|X2;3!qvTEFuMq{_BRF}f9@`WEX#vQt`j@pDAA2s@R<)6ROTgSRWy_VR!E72~|>Cz?pzi^EDf;6-%}%ZV}iD%Efso z?CWI@kA@lU6Stvy|04!(MMlv6DDoTRKm@`;`iL~1rAU1Wf=G8&jW~Rh;yOk47`@=VE7*Z3}4j5+MvPT zp}7u_l`xX!Ah!*@jJUD23uSLlrPf^r;nCp(%*>m3>}**PYHR_z z(C=a<%F-4Hf1st77&Q|@*0*HkD=wr~OLdLomJ~mL!7k}Z3=n8RxJNag6f9t&#gP10 zXtv9PX-_;>G3`I%{_^xZac6mY4ya(3mLm`HdFAPSV&j{l1-_0P3VG|zUpuQeqg`32;idOoz*-icM=bpi-HvB zNWU-_HHus3r{)$wL`#;j)ZF+849#c;Q+Ap<8uHM+msSB-2Q7PcS!2od2*v=Sh@U z6Mwe4|Hi?vQ;UvDMD1N$=-!Zyn~io~St$1--|)B;)7ZW^1@`e@_hqX#4&ux9iC?zR zY#JrD{$@$;eUh6EZyd-6Pv|~)y4a>#lTLo{fD;d%6FcECD0mm-9nyICsP=Bao!7y& zMbqyD5O}yT`F;sd#BKol*QyP0JWm7klYEYye0ukRSKw;UP)9N4&O=m}Oxu-=Y!F|A zFRBAM8Mc670OTEc+w->fwGNV(H=FKUV$!#Pr zb?+Y^giRq7v@+UnB=M-HiXF8skGQwil_73IG4m8^!)1Y* zI*6>MHXb<$lj@5`Ts%vc0dEuyI|lIhBG*qzSZ8&aj_HD(8ow2`T30_|t#xG!m5Of{ zyRu_n(%e`U$e#zM8c=E1Ae$iBwDN|^rvigb)LRDN>te1pCGlf`e=WKUMw+~zd1OYU zE!li2OJuKH9swzIKb}wXA+m#&AsQ3C5r$A;3Kw&DlywA6TBmmHp@f6Yz7&C8(dY1VA>WO?ln(3_mxDRZm{Zq3Ra4Y?jS z1VLal-@QL1xo0!S&>fV)oDMN2jQ&3doC8T$^Sh2$Cao92`Ki4*pG_Hb`DXaz!oIvC zJam(8uU#kKKs^Q~DZG1smL~xEquv+w+=LEgDnl?oUn`+)ArjkemHK0`Mq3Z>>;z@A z<|j=t!1rU2c=(u_4BzY&q$FOWiu}(VX|B~-SJ}c3_4R1D8056G;;LEQ@2dVHW0n3) zvBD1`OG8Zm``+_c=$EJn%l!hnV-iw&YJjHhRY;gorTvlLLm*TzKJ5;E_juF5 zoUBApj#tf&ale6I5`oJym2=u!ep^uNsg7vX(wN#6;iR&LXw}lrmmN-4p?82*Ep4`J zj*UdDmyqv`BT!|q6Iy8lkczpF$Q!8(1}f@W{G9 zAqmjNo}He=FWA>t-ImffXSOfmPw&@rKiBmYV{c1wa2}xU;ed1O+Vfb#>H7M!U@?wH z?EQPz&TI}KronFS*-~Z(LHc9oh@ zt?juz&s_;qPtf*i&)bj`*mhUXTB+mO*s9%q&QeH792;j(CxM{Hjv8_5ttlqkx1^jhOd`SU&Ylkg%6034o>er;X0fEdduXOb zjJ*Xkd_9NexR`C5((~hy%fD`Kb1I2JZkgJy?qaEdzAB@?lGrK$q%D2INu^hJ9IUtsD z103}`GV#6*PE}q=!b1KZa$mC4K~_bjdUvzf!yrMD}xqO z5APr4>kBlB=Xx>QEwU5QnXkF0tCItnSMg2)_ z{Ar^3MaZ9sbkI`YFzGOQ7MF#2!`5JX&p1wP|Pu_`%rpb-Ps5?{vm zqBuDR|wrB4Qk(4 zaMnHn8vk90E?W=hT)jFE64wZ{=?p~Ce~*aa*D-NDraS-z@J8fah$%}kh0Fn%XegK+ zte8T6h2ii`#L~BdIBh$K)7EG|f|I5Obhym}&IOMXjon0dRNfRS00uXSAs|!{Pcm%! zoF>=u`WA$#Hv98VrDj@QA9CD6&sbg$=QmQNFxv+5olt{qXfW&->-A>0xJqv}iwpJU zWN0bX^(ht9j`$$nWZ!%_5H9%r5_+q!h7m&(2Z-e+)8`=j7*$mUB9TyYC}k2~6P3gb zKQwV;h}inI)y3>g<+Y6nmrv)3vYay38i-3#!eWEarY| zb=xQM0X0i~!8CT&mGkOG;r-TX;dD#oXj2eeBv)Wghxq*)Yrm{^ev5L?WZ?gt1H_Zx zSbO!#ry+xWAt{^lHgs)+#}{G58^y)nSS>Lc1j>;BL&Gr=yml!yTC71Rj)Mt;?t7`F zl><(T4(H<-?u={r!d%7gE&0V0E0}Ur{z#7fmSTR{{2N&lvoNwj9>kGv)-m0ukrhlC zD374Q+c1TngipfTlev{t!50BnhG##2J>J4}1;{W+ta1ksjazw@>nVN=7!MHL&z^g2 z&~r?b9)rU?ixy7t9a;|?)H&6~rwF`!3Pb&N^pJHh1(IQ898^dbzzjdb5cn$K3=aXF zb0cS9Z$LOtDeyV{)ofJ*M8jLk(}+~K9WnJ60Hsq2wzK}oq4XETzAurT?nU&A`{1p< zQggBP7m!(K_)`!USnjZ{)uH?{f-NiJs=Bg5Y_87fC2pwB$rNi)3~T0A6AZV6Qg`vs zUBeZ4L^nj~`Hy;vo=? zfXA-&!Z1bkB*98U_)^^>@!n)LU%WdRCwmr!a-KMUvT9XU@Ojf&H# za8qGK;S7^-7-!xqB6AqBOG7Knn;>G7z@%2i3vu5h)jsfin!Gy?rTeMIG>p(F{+#kQ z$Ab$y>@tXnlT@z`XIUz|lT@d$PEvD4+9Wkg{4o*57gW5CBKa%G$|ubyE}f|M zJ)2J_r#ggG2f|5PX-Y1K6$=dH_51^Bp@BxvfUXZYyld_BJDj@nNeUgPIbTKQ!VbiP zUytaK#nACa0y3Bk&%`?zj_!`9ax24Bou?X*#_cTxfje}dvlU|3ey|wdyx*EHw$j>VR79v)ghFW&NB04{G?*8n z*M0z)Qcx&^#KrrpcIAArYoB$9*tyT@7_cDW^b=)Hi=^6<)GZcc_d$O{;S^)ArnHHR zAHyj#9e^3dJZscoer~qJ?cv!bJd=K-5=5#x&#}ra7?( zw_|VmKqEAVHE;|62ZRzIXbxlK4}(VTN`RN{0sqx22;lie)ge~dt9V3jlk@h|sa;F~ zS`zIJSi6RXG|qR6nko*~t6<`~%ACvI;3+V60A^w?s@YqR|)jkMtWCy55!n$TZ(Oc$NlM>zvXvUx{gmv>o${u6BNZw<#D04*9 zZlg_^!3**HZlhg1M8z#stV3}|NkR{sLRsKl*Z-}Cc@^SsSsrtpcxRE?N4&iVo$XmF z_M$*S^jGJreZ{y%7%aB&LabVZ5hp;!EELMkLZO`jS`64s)n6?{afFHvD(<5~pa42{ z>_XL!+$LBIQ7#rAEWnTv)+JgNCn_8-JqRl=;LO8$kezD7*}23cI!lq9?xSDjmVWQ&4B8SzU zMQUUG6~Hq9s1@AJ8D-+uBF7+cOOeB-FQySz++JkQmKdLDmJ6g_6K(^y|dUq3H5p^ zS>FDI6uw&!k3noS6Cfs95i9ixIHw;*g3S$3p#sQ+HUUWv++d^m71+kZNcMCWyk{{? zu`?hZ=A*y;h2$@_rQ16 zY{e;#y@R0{h26@?tN4QhSU^+~n%&}!9cn&ePbH8baIzWkvh8?OiarB-Ig$uGz z(o!)I2a5?iFb@x*!i7R<5FgyDX7^9H5n$xP{$|%7S=s?g{Ce?h@=L|t_u|&>!Vkpt zRIH{VNX2<5lqDkXUfgcmJ?KzwTGLZ;>>kx&ADz&yWQsZ|yQ%=Ax+O8L+zYXPJ%W^1 zAdY`doZ>JYZirvthou2yHvd9gmjkeYUm}v>gCrTm*Wqy}&|)2lX`%eh zjy4d7uDR%8qK}i+=Aws)L%sqiZ@Bny5bI;+q6f+08Lu@L?V)M9!dF)pV;jvB(24^< zfI&NB1HFR^1o=YLOhS-KA8b_DwaBR0yxlw`FGpq)8leNwP7N%SEDHuar}EoFv{o=s zpVUf5wQ}fS)XZ=fvk>&l(aOnxvVaxewtr1J#SF=xNVI6zo799gK!j(r?A`Yd|^BSuY#Ia|3qI>mmarXPF zwX~zV=3w_~J4IRyXd_~s8yY+pOZmC8vXl8_6F)4h2-1n1 z+_}jRKNFL&$D4RN^}FGk77B@x$%?ll=l4a(Ejb_K=s+}d9XuwVsL!dh+Q1EPi+U9T z+G^Ev02Ln&+Ke0!XB=0)LH4{?m^@<(f}<}~n%EjO9h%Dk#SAg#3-r0eaRQA^nie*t zRQjmRifzB^Z0s#UcsX75{0b4m1Uj%-1^)@ry9&P4`*9rg<)5&tw>&9M96%t?<)) zm12_@g$)aAk8dSzyosa6<1ok#{v5CT39ow+){z#xmlnq$j~9qRkbvnC`AoQDbo~a? zVsX%eG>FuMD*W(!fQ${suSWMf@*F;7Li8+=KcQg??n)~oUvO}IlQDkSte21P?Ij1P zmEgcP7cHeeR^bDWyobSZ6=ZU6@`3X*Z@AnQiPk6g&*!%QfFn_b$0Pmn{^Xm2`2tfr zgNh7?M4?C9M-267vqT<>@oju(z6gAF2&VMj#5XP7jGS+nT#gMbE6D;rD_Z5J+&WbQ za>r2vr(MY{Vq2cpqFhM}E2pWEVuh5+w}}OLT8C0X3+D(qMk4&WUQ!8;Bntu#Z}!!O zqd;5z5zcLH3FDX>bN3HrNl;GFmn=~<6}MCm!uD77Jadyo1jsAqma zD$2nK5ACgfO^JywL0rx<5JWCPhT???JFC=|XeXnGy^nZ|SG2j1S)N9g%KeaBb|R1K zKegAR(+R}wT&1oBwjqY@7eP2$Eeu}gp&OQKuYqZJf;vV$LoGx!ct7ps$Q$FtT$rXB zRYmzjo1y#+T-+CsdESND_~jTVwx5JH^ccJ%_iK|O1lJOS(?Lh?6n%fr>PiFf9 zlqv1V|D#K8KL=$}ti2KoV|$rKqkX)+80&`iDJb>r<5B9`&qS$hAC6MfK9t^X`#_Xa z+xvkQ#oyi=FyQ9)T$F3t5hSSns~tEC<4f%(thcr!8bjCJ|+M5pGGTJQ%@bspM2j~Jf9KfsAZaP4xzV3hxG~|m0r>21M~tf+E3rqI|WLo^0;{TEBNc)CAL#eJv33Qul@U)^WQr?TUSiuzT4) zI%)I1nJ91HSAyN1eUq^s*+-|oZ{J9i`}Y;1{>^=8f!e$G^}^|j_TgD^Iy?;?19(!6 z<}B#u+FvnwKBe7**pVBxm%;rXK(zi0Kv#!odvj3uH|XB4z^AiIExsB0KV_di2dLFE zFoinQ&ZKMqw|J`&&`<~w{)^@#Or@>RQ8sB-2}@ z6A$BChrQ=(91I|<5>k;5>f4%%C8LD<0b0IR4Pxvtc@&h7?dx>gmzP(nV-pPGv0K3 zm2YJT5PMD+QxWJ<_mO<52+a>6V|6b#PnrRwsacuA#32<7LxPNxw@BP_z+^9xkLQc{ z^6uq}!}cAGgu$p5ifEtZhpP+uYbc2eDQ^{Z4gM;)&l))@GFod3@C7Ixr7!hz5o-f4 z%({dsMvPRDnI0*67zJC)&m6D8OLIIUFT#f?&nIp?$IncM(&-!M67dtBAQlnbUk`SLdSxzH+zR3DHz1t#J@lIWNJoE}2F*2+PkKT{ z*oSv7UdwZ3ik*3`+_T7RT@hN2j#3W*z+9k9IX>cfeh{vQs#D>o)DAzSYkMgbz_`|d zyf_q`AQt7htejB=l|Yh(pn~~oTHI?%KJToWiIC*#W@H-5drI`mb6HN|?-W0N3h2mz z4XAOi;g8!{3o+HUSA6Dn_0d1fmYmG3DcPdk?Xn@+I7HU?aTCDU1`XU+da}wA5ySD! zG#o$PHiEyN{IPAgD0aJYn8UatM4&VvxXR^SAd<3^IQoyS8tK0adV6yV4k1zjhNnnc z1Gg6nL;$)55^%a+w9d@xm8X^0YVa=$)SKpW#{#|%AsFarhDl;~1^75n*t6r;Bpx(s zL6H2v7iZ4Q$}>u;=PklEGpmoV&dkaZS`@Jxu1Pwr3aCA4hIlavBSOKNB3X~_gpYc0x@Pk1Thxwr;qhIGl z#n{R$TRb2LX;7ZjJ^+K%mD=T6KVT|j0O&S@SKt%o#(w}|K$pP?yck%ODL_&VQ0=N7 zG(MjJ)_o8p$^QgBNDPLH1@Qh%1+04jq6zhA#IR|{5i8efRs+-hz4pU8KYxVIOiLAp z*LrLl7{-AC3NIAgriNE~?)`Vq&6oMbfasjsIUR5Gi^?V1KCs>l#zGVMjb2*3153mN=E$b|7BpPRPf$ETNW+b`}9;H38jv{|u7 zd2mBsI)93TjU})@5dW=Y9IT@Jd)ec8gbs(6g#f$BEaqE>$uqPv$oZX%s{8Xp`^254_9{>nrABY{10Cz(C3IHe8 z1$?HtJvYydpT3s734DB!*jA^tGoleUQjM`1oy2X6pS2p4;B;0tDbjv`@4$3+?zCy? zA8`vr6#yz2TPP|~ub!k%;o$=?209Smi>Eo;3-ZW#?Q}1_x|I2>`0}Am5xU52HbE9#{54Zql9mr_C-nw`6v@{9;^5Oom~9=7T)(%bIdnGJKIdndmDVX!Ii3 z)8~DFvX)iANKp^gI?Sfwz%p}DSoHF^>~0?W!!+gsZyuC3EiY~Zca!S41#O?B<{p6>K0 z>|dT8f^iLbhzTWYD5SR`YcLP;IO2GTK2=v8LQ4(9=()OTh%wKwMm)4PqnFsZH$%qK z%?=@jTqxR`)C7_J#tfIW)b_h9$w*Waiip ztoy5xJID)HyHz_I$SZTvg?sytaK0r;8b^>QiB1it@e_z7+y(H%&Du>EL{`HNN~vB- zp^%*h%c2&}V`Aea>-Hw#R^?DK6=aQl)JzN{AAzXxQ80qt1aQzQm}9CCvp-2W711F^ zxWHz6iP4JZc^i-C zh93@Uu&rH`8+18TI8zPOfoFi}H0oUDC{}#6((C^Pe_6SMD)+KV-a=2|q(c(yR_ccZ9 zy?uC=msLb_&e@mQlSa-|2M7kf{SU;LM)8W`@)o zS@?(&Q-5G3)h_naFl_kYf7E|32jF^=&n;uc?ez$c94%t?T5AmpRMC3N(9V@1ohySo zR|+~;P9>^v9_mMTt)11ic4pUF{FyqZk#|IDz1A&K>a}L&&F!O|x){_>O_>VCTw`)+ ze+N`EZVyrW^t6Zo3$Y#ckelE@zXr(zE>R~)bBH>or$OZJmIw8WZrg+UHA16~B6aSo zh)Q?{uJ-{4)JLFP-3vC0Tj1r{44=>CkPlbFRx$tq3x3e|1YEB2t47y$iVGGc?4}e%@ypgV(36d?wyuG4YpN!Q9?$N8HA6SH1NyvfOb7IN-RO=pQJ&R-+ti)e0W~}=vjg{PD(=7+ z(v9e_;?%m~9k^lb^Bpi==;t4V*~0kOL0Ak7pB{v=tZz6Nz{gBJNLsz?ATFlMKS&qr zf3Ora&mNqJ^?nEOI&^&w;$o)h2ceAXya%B%>+%lb)taUqgpER%dyp>aJP5mh&T$Zr zr?Ve4!U~|X9>j~%S=wQ$&}FydZRxVwBPcWf@Ae}yADMz=K7!$BI&S6h|7|{^+2mA> zPv)fEp}hhA_(kv~4bY~?;EsO-PNat*iLFE0<@xGl44y7Tx_<=Z*lrNC30SgQlm_K| zC=oIRU8nrD1Hg^T5ZmL^em#k%7a7Ur?R0{1%9wba^qRNQVAG@KfOu@XB~xtQZpjkY zQ*j9uO(>MTB6GVXTiMMEF><@bqTfklfcW5gy+s_o)8ee9k!nULv^db{W|puSL7B~* z$@sCcVkNY`X0w5YC2UGumRUz51~w^^x%Illjg2Ho#E19zEEs9F&lBVC1YfC*7H23H zk$I=ZB3;Pe|6s{xxOx0H6^J!~(2p4*TfBIO#kQE=icAYyff!_HJkDkG4DsVjVcW(e zf&_43>*R!Mmtw|2_VyaT&CG91o&i)ape4BPZ#6r_PNObInad0Dv61EsDjuL>6BR2^ zjGLKw0a$c_It#bhQWI_wxm^(W6}F|(xE#O5sgPzVlEv|q_{N~K4Fu5O?_c^WYF~vw z*@AB~8%Z6$ft%wwVVdfEq=xPmbWxBwCjbAk0RK-C;Jt&VIsc8|6TXQ?1$O60F|uCH z!6$^390J?Bfng^v!JxbgM&!$2IG%}?K2+@svr{SrthXR2>;XFBN~KxxLr540A;ArZ z((iyPe2U1eCz$knou(0Jwl5;h6KP_sM4T*0OAzZ5_Rd~%!~5xaHKVV{DA(t*=^ndl zyb>jCc|m+rrtc+=mFY9B&yto<>8p!+?&@62-6gIq(_1)BwkzRoP7bx(?oAF0tMrlk zv$@mdS4Ur?Qqr1{>Puwh6G)s#9TYNRF%KvGOP+^V0V;jXrWMo>Dt-AN?*q6NY*5ws z>bdzilhES+#Mh;IkNBumZ%G5yASo!;o%FOqS(0thf7!WeA zzBj@D(TusgR3-Oge_)UPgw5v&VxjLr=J1Qrgl7OdRfssM6j(|>1|{Dk$(n62m9EqN zsA&?rJlVF>`ELAy#YCL(P~yge+(5uj46tGs#l3eFvyvVE*z92M9Hsi33HDixYGD`K z;d<2ELoc0bDu9S@Ssox7jNIqxol#{u+8om*y6*dX)edSGbW|~L?_de*f5LV@28mQc zfuLY_K<;6nNUjq1b&gSO!+K6illJ8%I&rA=`0Bh1Pya2yab8|i+af)i?j2< z)HF5^+${r9%sVQ(3J$75P>Z*ogn9Z+Fm03kcqS}Cv$}R@b0eTc7np{(4pTa6( zi{lN*{et{CYEy0zx4N@kOfFLCi&lYd#9AlMC^u>oH#ph_T@{LPq&}QCMc!1TJ_Ni& zect`@&0wjfIjRu6?IjJ zSIhMd@mx7Zna5Df8!LZ}6QOz3;$1c>m&&I@++BUW`#5jJ+vvlPnLx;stI>wk&osG^ zWfkP8=!?J({H?ZZFnBd?m!?-d6nNuL;Ji&9WOR2X@y#D(oRQSHA%(I6JI@d=A6J}v zUpvK^rHYn8#>+(L?c9y=gyL{hX%O%KF(#6S;Ko=7ALV(FmQF)ZiWxyEA0e~X{Rl@1 zqW?_--o^^#;>XH!5SDHRZ%q@JHpT+oYJz_GZ^SO%1_TvM7l>ktO!PzLgC&OsWq&i> zwK0j>Hqxyjf)xCZ#$d*as0841zR@xAHmvGsJe!TrN4OX7Z2t;>IO|5#!vs8}yM88& zqYw@nvPc?NMaGZ}I|7Y4i<+&a0JqwZ(=Sm(e$4%deS=V$*H)j!eKJqK1oaO|VuS2>$d`6E>V zaNZSlxeS#*h{8=t7X5=*{a%EQq}!k_7``J3fwFN|gP8?s32Hs#Q2ULz{cWc$M_~0U zJ{3UBU^xc$#tPF_sQglN?AF@`|Ake~;WZ19B8g$25bF&`X;PX+aA98_bOFQrqDhyY z0|%+$9nzmgFk-dm*?+_K+w_)!?(!pnOlN4xI@BK#rw-HQ;8hx46G!Lfkg^~RhciLl z0~jjIR*?7&|E3G!)_t{g?gQ99OfPTd5^~JfFYyN*aMu~wOMn~;2$G0;en7>O^fqPS z7lPlo)CRhi>_SPn)Ja3rH~!$YWImr+m(= z9ruByeVw`tM&1g{Rzty0lY!8b@06oR_jnNaQ0g^dn0Se|W1!+h&-oP+~q4par26Yleq6Smov#Lq!3QROUL-J1`H%Z|9*V%-s!dGZcY{ISdUYUj!; z^yVu=Rg|)wfBoo*6?;#tctpHsbo3JM8XcLo2YJE^ECaP36504 zCV54^z*#5kKl6m`QQ}sEBNtS<;6thPMRXj!T#3OwzRmQWm4W&Ya!@zD7egDZE@QA30<9Y)y&im0-*0Cy^s%1C7p1iVbp-294Yu6MyH{Wu8H?g5$8)tXDR-(N65KfIr+P5_JvL+iX{WNNL9 z`r(q`R4tX!d~nntZpp0YJCDjhCH8G%A8E(QPp67Ee*qoybH7;AL@Nr{6N$$@p15&H zT=WZq9WJD!+7oxQC2q8e(R9>VI4ZU;amQnc8;>S#>}A=CB7&i>K&JCA2h_`biR_Fm zaI#9T*tQcZZX;WNC2}1^FyK{2sbeEQJ94yUpUdA*O#0bsR!YUVpAiSL>1U8ouc9JA z#Viyvr*bC%b_!a@%ur2gO2YPZUt{+zevEkR11 zg7MuSH2o}Ef3oHdqA3r~GO&?icFhk(QXiMM3OOjsWTrE{6DVq@!EX}Jzm7cftZjyt zAc4jbV6RG$3lUDkU`@tsd8RrD77c*0MQbwW@yiMkfB_P+zp0t#)x25qMyQsV>+Bqk zM(wi^;<>kb7?r~hJ21KR%9%-p@nh=iu3low>#of6vgJiFSxkZQ3*pPhZ$e_#Q{oI&jFEuJh;%t#b3`LskPdPec^Dq_nHpW;mSCp zV$0CJ>UdT3>aY&vi=ace=>joMO)R0Z}j zzcb63B^Eqx?L((QZi)eRv-t6lb%5CUxOI?NHXu2_>qi!`O{=E&qVH)Ss?0I!b~RI} z$8fX|gVl5dApJvA;?;~2OAnhZV%4+eq`q_Dx0nHLB=%cW&b+S(6qg=5vs8jdNKsas zHi9)QrnQLm<)-Gn-%K^lRK=jFrpL$9N6XQiqvE5j2WIdrpa8!E9(OzZKIa4b&<7#m zAArDn8}#3q$|-11uY=p}2Bi8pNBhnY+`=ebwr(PXJdwXe9W1O{)GV(@->;Xdg8u)WrC82Vfz)(if+)W=pp3rtBu9kw$=kbVBdFNGFhxL_&IK(xOtVfIc|Vn}7;Z6o_D?=X~coCrdnt5B+$!OlgmYhtaJ?;c@EKYm0D| zmxCiMMI@O_bohBqj6S=3vi`FEGCjUZ)0oDt(j-&XDorFsufiz$VS1c@D`jzd_Hggzr-c%iDdWCW)d~Y7*)03P8_Ktk9&=#ub|6P=p)@lHZ0E+XG@G zb6ig}C88apXz~h;Kg%S2f^qnuAnk<9%4jTvX0Qt%gG0lk*j%+nSGox8aDJ0l zP6_&w2Oc{Iq29?8S~QU}o6+uabc=b55Cvws;zvwbi$7%UQ^_J@lm(9mkMjiTVfCj_ z1pB#T@uyh1`8KxO2vI>2Q zJ|!e)x>z2M9@`3YPjgR}%}>V_zoKP=2)|~2Q>$2T)8KSnwEP~Nn7qoqYGu8 zWZGHgX{<|-J3HW5cIUJ!(32B3c)>n=4xJ67b2}IY`%8@gNj?jCYc{xu(%}tt8GDh( zun%c120&PS1Y*=2Ay?=mT@yM=SHK1@Mak8}E@)PYH1|B_54=YVjlP7gkB>;=?^kqQ zV`o+Cr?rvUAmrb&6mSy*L=B=`b6Z_o4IrcC*EhIXX;aF z-hA22a{6gBvYTuB?p@(-eQ{w~jJ=8JC-VY%bo?>0dk_De!!3Ux{Rtey zb|(WlEF+E9wsyC#-WH)t5UbbubjhL=`_v%X8KLV)Z+dlKJo|#K*8l;Kh9@9*w8Rqj zz2+3uNsFOQ>IBK-HvspxqZ^JxH?(6=zXx`PN@0L>LHri#-Ggdyvlux8lPh!DQETMZ zDqXnx*&nRZIn?@}w^HY(2VRmDdUX|!7O&LlY3?dr7|Z8pM@GF^IkW9@~1dg5p7$tc#`3SLjmc@CschDpF3sn;{$| zIy0g$f?B4cH$#g}$d0%jahs}E=wjH9)53OqS^)vdez-OQs2c@jgSy&fM z#?qURP8kbjUu}Q17Fr9{Z|%5HHW@idj&+801`T*#H=v72x{jgKQ2=OUHK?aY11{;u z5_}2{1djkB*+%1q;^7!@WeWfW=^*+bxxE7b$P}R?e0Oe%7gFT(47v{fbh>Caz~a}- z^B#<7fo=$NXtlAhkJyJcLb;%q?`}O)pv|0}@ z&q_Ufl2K(28qA7M(CZUPtJlZUHJ!dCo!04Xv|Lx4)DHG3c?;e`}t>6Pelzj;JoZ zi%mRUp*1k~An&e1(Cc=fEcpTeqb1;F=m@LuFHqTRhj+wSI1+|~S!ciSES8+s8Xd2< zEX??{q?f6+T1V{Es2YA32Ntu+^U(U+ny@S($Sb2qDK{rro zxFNB=?VW1hR=1w|czt}joZeD>>x^)NuQen>!3}p@h{cQHVf`W;U3$UqPK6uBjB_!b0&?N1uR znFe!VV>vyQN{6FM+{v&wnTm1&T^p|RDBbxR>wxtYbn|KPP+fpse1y*IHMs3e&x-Jj zu<^EXW4h8+QLAc049hT&mMoN_*wGxi|Cr>bJCj6{zHL}rq|B!5$0QexU0^b?3=h-o z-QI}hyS?G;YzB>f(Ui=Nrqh|BzM#EMr)>Dcfay^;l{!_sV_AkuvVLk$X0Kl!C8xV+ z=}*|HMSNs1u#07sJqfGG$)7ZOOE<)Q1>`427lR9>givmAEK4z!wG$h$qaqqtq$IMV zLK^tHA&nh9L`#46@X`w!$(i7hjTJqG(`FPF<`qQ6Msa_5FWaJAhRSjYu&ABkVssC} z`EIE4CxTGe2E@Z5Y+5R@q{cu9IswnvMcBsN#JqbLx|bE;{x8Ljusg^r;@A?78JL;N zLBd#8$t9dp^r+>R%vS0ca`}x}MU#swqhg|BC<><(8DlZfIyRr&4#5M9cmMZ77Ds)b zqO~E5jdjbE25B>6k;XbG%?w$T`su}1kHd=^RX=Ne90RIb-n09KEUx-;Y)nB81wCI( zwN16)i)XLWIMx#0VEiP7ESPqK7Ph~snbjPK?wnV%SnC_>8wX_;j{q~+@>q+hzI>c% z>0~ShGR82_0v*b48JIJ^Ry*&QP~wYAT7({~}UF&zrw zR(|zhNHozZ{HP)|D};DjVMu+fpIU&pnr;WhR8?x`Sw0J*l*faj1B1Hu>DcuA>`!3k=#6m%c+VQg^ znRdpyAZ^6rbZ)H6-k?5)#ky*S$KaCU;>n-`T2oWeL1;xR?6&nmm-eq|W>$HPwZXH& zv+O7hLIHLNyk>UAxGXd!2FjA4oavy_7?;Nc7YecRl zAD_~r5+-N{MK=Cn{DTf%G>6#C?W3E&qK*az#V8#jKfDlpfz9GRTK%ghoITP+lhj%>I0y)r)m0O@xLqn8%T|(5uUaa7MtINkFkH7 zCk&B3K_DeY*GWa!K>u-NiV~v6MT(gnu~i{8fv!(cyk;hS0Ge#|TD|o26eWrJ7c1zr zQxqFLRj4FT>J-IKzZWWv=~|%@!G?1L?YxNb%No!+ytr@@T)x4?nH#n*Y#;6X69O); z_BDSRlBwcPgN-u&M04{`gUkTLa1ge6*ehnLRe$2XL2m%LW=^Cx(yO*3lF*L78~n8X zz5%>S_YHWB`-Y~=?;BFFkA}J7C)1-T_Mk zuf!MHiZ*SOoa&)n9RT+0&;c||?b~9W_I5xhg>D_hSu~@q=wfLIpA!HN;G>^yjpC>V#Qk5vJUbWD>g`~ zshO;*9JIDbVc0c9cyA}hYNTvH?3 zHw!ZRN0S?k~h-XBU75%#s$g{Opkp%a|! zY=B$cp$)%)17_w=V3<3Z1JQNH&zc?DkenW1f~}Jl|Ee)@nYOz9FPaRIY(FFSGrwr` zwCyKN7_InKlc!CV)6-QkIO(FuN!aG|H(WnS2G{>2xn{G&uG)qc6#@pz6nEK^9dA3{ChH{VQh4^?bCLZ}t{m6k zTejuOF12#z=gL?N*axNM%0_FAN=f&H?u+^_#}yYV!9&Je84B$jxe>+#_SpQz-p;{` z?aq_E;SE+Dtp$TB9dj1jK-|ic!`1t7q^B|L2RFpSf;kQP zH*E6xz1VFOQua?^(K~U$Y_+j(ql@to)w33}+f-FpUZ%cVwy$uK?A@dr*B$MSRO7P%B=5 z?cs4urmZoV-o*CiUtm>h4~*_Dn5$kuAcBXW`1k_-eFe z4JChwWg+_mXgp+g^}`PgNsz1JlIikCSlmy4WN1R0K0siJK_3}B(W=p*Pj+w^i%=LG zHF!)GNO6nHBO)Ur(KLv$2IM!}F!p5fjbG>~z|;IG7+QKtDR7DX5;SBlVeQBV4Fuam zoaFufL5yCVa1FW&W(w*leE|omfnqB$lp?o@(@=*YJ|F$}vL;Nj20#^A?M7dyhPw}r z8qv6YZl49fAoz}hX1*ez1QfD-V)xO!AwGp&9mMX>qII9x6}6;kpV+Nf>f$oVzSr%d zzMt6b><*@-z(?~m=sS$kMB_wy_nbYBvd`Ha6x{39(HrONMtby|y(v9))^7FtV1W_E zhLzD*jr!G$63?N12A;Ji()3U5k#z8^J;K1e6a&2iz34b=yr+jC?zVi+9-EAMvuHH6 z#i(YP+A~(egBYTrxHuv{B7VzxpSFcbx}q8#UWH{eTgt*N`95aFy`bI5hMT?u&&-#> zBsTz-PaXU)U+1$)3p%yO4ejbMUy!1P`Akd`kV+>z!i2kin9oMrhx+2^R41H9422z* z9fftuo`6=)E)NMIf!*n&RYQGt8Z^|`MBN>o9`1{w;^96c9Uty%PSL}CP^As`HDO1M z)l(mibX|wJFS##K#|u#C2KTw6=$pOnI6Af$P~%N|-3c^fue&kjR=b&!LWreq)$Ztg zwu*X$ULxeiP$ooho1Fe&}GHJh~Y>t?fIDinfW|EK@yII>Vri>WgDF?4vh2VYits zH*2O|9oI=T+4}+n!x{38ON>kE-vQSg+E}?+K+W2w6E>V^v}n4SB^sp(x(Rh>(7>Y| zEkh9e25gFz+REBOB4~LQHpYcn>bnL_gWz5UJ&mN3*v&!nfMSRbP}O@RC~`VNtYQiw zO1}WXbNU{4V^N^b&YM%hxvm|dX`~*SXYl8?uzR1?9guuOR*1X%5_#$a^0e%=DWQQ(VW-35p?KPudVJ#N4Kw8^irG^E6+lRIJl^z z;#a*!ihR}Egx#NpRi_mq+q`J+gAu-XIK z+XSfX4BMe!AG%!=?G|Q8*Ck}PXU!<8Or4xPqda#;RQu{DwrlnQLnH|2sLKw`nQjc; zkp-3`INcV(Yh#A{2*Z@H6rfl+4v@hBqkm@L=B)Cv>;h9~2II;q2NIjX!5KHH;TKwa z+vgTnu|FP!G4n`SigMlC7$m1ba_6$#Y3@xl<~F#* zN8k3jdaY;sDKDGyw@MGg|1(C^cptYHgLTPNq6jEF;z2HH6v7V~s= z^z?ivtp?6FwGEpHFKDpxm&BUWL7v2J6q)N*q$A1^)$(voo1e<_A;EA4Z3n2Jj<|Y z%|I1U^93f?KsFQlgn@!|0eaCDSWCMB3i=y@bnewWi+aT(WfGgZa-j*1k&~eZ$`d_dh%Y%gY-rffx)cLX z85}ma!HsiraU=h7_C$Jq6}Zge!w||QSL|YiY|G;0GGC{#PGOxI`w~l=@z_X_RBkPa@qAQ_B zTZK&z``0gb8c=s25u3#55PIj%5UW}|8Wj|pJ(sb_NvB^I*IAG&hlRCN-;HMP7n@5c zgxGskKY9R8>up&-^9yY?(q7O3PX;4U2zs-Rxm|8F(UJe*=Jf3?MaE4Wg z+CEmg#9(2ps=5CgQ$?G?Fdku&h~}fu*eACoK&1cMK8uZpz^3YprN05$iYLL2yb!B%4s6(Epllp}9sXH^WjV<0J zt|P1H0NV$Af(_w9s8w1@HuR;p;ovz72<#?+lU@b}=?SO@x`7K+1Elr)2wA@z%FN-o zEkL8H4V&qqcPx=~WgB+>m@PvzcN@AWuilbvScC9o&<>SA(;wW1jVgc3sBI>b9$F&f zHsdzh`?4vGO^_~n`DGJED`py+^D^?YmZZ@yo1ltfM{RLc*9g^*WpU{{uw6vGY%*el zmYhk8-?4aU%ZrF2Gr=~2cD!Ut(4n2M6XzMt-5CUdF-K%))7Y0Vly<*l^4V*-+ed3h zC&NzI6(NieK()F8T7VI7^Kijpd>IwC z0-*Jws4z1$Dj#7lu>ey|R}Qzh0``&B(5Q@%uEI(&3f9nQP+;AK%Lmh?t`p`bVt+hm z4@}0kQm9dGm*D4Q3D%SGrC3j1DM4jERf2lSddCt+hmo&(?;b;h$ZiQ$!%|lv(uq9= zQxmrJU>02G4(ASabGlWKO0c~*ih06TjL$5gtanfdctWk%NVd}h|A(NT1H%K8s*nCG zw$@PTZE-POza=hNzTE&7IWT7smHNYy6(y|@+>q-(6GjSgK1H1fp3ACoQvT3DLNo@i zI`{=~8a6*=s3g%PBt_O_q-{e39ry@e8ZSC*xGL<1oEECRtPBgZvF02Mhp$cTEe>n~ z>UYKLHoH*O?V!EEZ4R;w3$&}9sCo|zOt*Rt+Jb^FP*W}pFh1Y{zZw>Zsm)~=9vEOv zK4=XJp86-{4G*-a&9G*8V4{?B&_UlH(mN@2F9ucjA%U*_Si1*>egXj5Z)3w;OHl5| zKJq(QX%8U6UnN?l9M#>Bcy_%07DEI zs`F9wP+bQ7G(?w79}EF3V*3zX1g#jNi>Aki=xiRh>;pieFI=dKCqo@l0oK_FUxbhP z4#BNKHt4F#O)jk)fezS_?=LsN*NvfsT)(@1r!M8DX4JYIeac*p-gUDKed=hL=>ghb zW>Ut7%RZo=)W?89$eHd;kCuI@bxELZVBAcdv&%uyF*Vz_(6_MRo7J)-Wx6w6vJd+k zwWNL=PT;!hx=U$g0I<5tOo?Q{k)g1%urlJ)h)-E(cF}={946_E^Ne~{U22LmsX$`q zC(cjU7zk#u>i47j!W{c1)Nc=iCa#kd2UX^OG}YL`kA?bIg=)MkJ_7Rc6oCJ(2ycR_ zc(Ra%4d^nF=A}Zt9ZXX^RFn#}YR7aObxT$3w7ZGLW9kg`Hm1~%%pcJ+88GyZZ(`A7 z>8>abUI|`NZ~G(#w=GRk($stBrQlv(iuoOjof*@E{8nog+~OEXDx0F;HNUIod1<)L zPE&>hF4JeYE=0lMx)e-X8R;}&IM6oNhUpB}ZfaPG$VQQk{&IzF1v7jsBe224bS9cV z480?N7ywy)hv@>8K1>%y$}k{hZVknSlSA<$FAvo<;;LV-0PxURD9o$Cn3<0Hx(W>s zQmwhcNU4aPFgl zX^sfGIn>ZxkAy|Ik2VAmK6Ug^gWWn}=?q>_s78n@y#{s_XnL!e z#YKyoS^{>sF~P|S+f`FzQ{xP|Wi#6F9R#|G%`6@W?=1mZXo_i|V>7J#_nTS})}^T> z1U*a30MBQxMY5*p(^z?lEK|UiH68Y1D80?w%-gtTpLeG*O)X{)wxMJ=yc>01 zN_{$=s-|N^p0>*dy82txVoII{&%@7>r-ttI~16L&rg4 z(Zg!?60Fce(L53?V*6k-%K?H=fgHV8Ah22wM$**Mc-dgIPhmDt<6v)^UCtAr_&@ff(ai3DnRb2(*NcR6I*vVh zi9#)P5r`VkN7oo}46?jP^UA%^Ec0f{*lLZUH=8&VcKQO1aygUWDKee(( zw}Eb*6=T`c)^ln6voj_yvlsAi0Xwmq7j)}r_8P#waI}^-WI6q|IuU+{aR*XY)7(rY zXpRhnu2{FKsoXhcs=o3m#vRXf^}-%L8X_Ft2gx33l|7vOPa=&s^{0qq7M>M>BEu#sQoSUNdc zsG`FY3?Ei+%QkpK-MFQ*f+#c?*~q$37=cau*XSlk!726vw(O5Uh$Raf zPfgwdRQ=^6;mv8*5x|xCXzP3=+(83Q;;QdRxD|?Q3???VOoI_R4&EX=eLHFC7QEnl zhr^xqW6hv?r32kC_AsFDm;&Nx_~G!Fa30x`t)`5UD5bBa%G#FEU+6&_$%CUMuN z(uZ3em`N}>@=UaLtHacwn4+x?YlGAF?3C99e~5Lf!=g42KfS)ikx1LOfXIL~6&pI) zHItVf|I}gzZE;|y${rWL#Q_m#v!gqm-t4fcrLNzMn|X^@9sw?`er_C6o}HbST@-OW z;(CK#vi6;Di?)8EMb8PNDXjajHGy>`w^}UkQep3e8-1)@By3tVm!VP;vFq#u%@g8p zXsF4T{$}L4=C9E8&Yl4BNm}!{zm2wP(qks(!o~f-PLMrO^F#HOc%Ua*nWWR`^_c>E zkEa9i4#9*tz~sd(*uFcKiq zomF#nziYB+TE(%4dC7a%WNR?qRLF+5rM9J7$7pwl^orq?x-)lOe=ySI-`IAuu4~zT zGZ~~0H6Q*p$!tWE7$M%n^`N+=GrCpxqU;La*S@b=Q)xlz1HzKNVh15Z%tQqy3R9(3 zh^pDA%KP?M#CVTZnw7lWFK_!AyWw^T44lTK4co2Vz1eapAIqTx{M!rQmhR830Uv_GY8*Cg zTEItE06fw`Is=c6v(Oxm*7O1JGhNeEhKs`%hj+QlD=&M`Y}3c;W8+yHbD3e@capYd zGIKiBWump)8&20<-qx6YI#Bju5Vx{imIhN>G90VW+R?Px<+ai?9(0b6nmdhjMbBpo}63ZJL)@H-;db^ie$I(m*l6nGo1!)rrd#xP66U+ z`!k(3)=6Ydn%seR%K&A%ytXY5`nBy%(ka0qvgn=Izd^btTw?<>nO%&g)rTQ&@`3(}$7`VPJTO$DY56P> zO|v}c73m&sC#snsJT+_NHs7|okya;snBo5g_mo_@L@wDf-mm4VJD1RwIecx$mbe!{ zW8cHDML_Lka=GqhSS5SHJ?T5RrYsjGA!{30DqjThDLzSVgXsq%4Gai6GeRO-ycTb| z+$LF-bNsn(=qJCh1gZNM*pzj=W{G0v1DS$fKziNqxh2jB*U$VJkQh#}(=;mn+|raf zer`!;nWJg^B)3s6H%~QBrS&!ECaFSK!SY2R%#~NB^Vcl^ch;T0blnn$+HaFVrPnN2 z5q5jEH1#^$L9+YVsi_w?DOn>CEfw;+D^J1d96aULvJx}l9;px6JLl(4hH^kN}I0WVAg;nr*Y2RE)p{G~D$)#wOKAMT~ z5K~s^ElkXJQR`KDJIURZsI6?%o9S)or++j!;*r~=V++4jz`Xy)OCifk5}B~$L4&YC5PK7C&AWLixd zmPYV7z*3Msse-*%Y?>-u!eezJkYcH@SZLwCIv57V^>D4}q?xm1WV8?&8Q?}3U_UYf z9!C^&I?kC;nTI_p;|ZAkN_YGpn}ozA*uh8BnK@BTD*jBrln!3iFQ=5N`hU^$SMc-8 zW&K8)-YRN!XC{~Wgw6<`f%WrID9c*I`1&LFYhs?VtswS%3oG3QG{Nv1yvrNHvqFK; z8Lo>1a6Kl(>M5SS>*P#gKLL87vlA12mJ^f>ot+AFEwF)Pb#}U`2~MfWT4?7_H&45 zQb0BS4GJ67;A}wHfcpDsObaM_YQIrOe>R7L$ksxUrAA?m{ztk2D{*qF`o`BX6$?TT zT!i|vkHD2Dw^{LF(`?; zO4r0lIU1(@!F*`Y`85y^`DaJ3HMOZb(wnmK;G3SUOi(7!$hD?_QN?OgQuVF1rf`vU zf0wZ)M7Of^x!*%Ew6~KpNXyvI)K1Q58q&!b!^(0~mrhO_S=a?O66ba=MvsPZA@XeG zS@bPHOrzywrkO5aOjOyG(_!y}F?3`B?A?{+reEiDPDMYI3Z#?z2LwKlqQU+bgvKeY-wibwB(n&_>gTe}G+i(;p}p@9(hnWo%5~oeXv^EUs`D!P(~=P|8#O z(1ugXKeVxA{zIEW-~O(R#v%dF$qi>k;Juk58lkkm^nA%*geB7JziY!VV)5$iw8s4I z8tWQM_fa|Zchj?H#nGHwGZozz>cSJ~^P3@PSAmFoBHXB(A|8?io5`n`4>tpaJQpFE z`e9KBKw`NG?CE|~-XgIWXsY&@nL^k<$XFo0#1ioycFmiC%9{^X&95is2D_pbplHwj zCyAAt#U^u~WV9lKvvc#oDhJX+Z+E)%5U46IJ_Ly9G4^wS{k+V6RWDiuH_yfCS z0sNWQ6v)O1^<`P$2S$Ygi^`Oe+~Oj`BF5-K12c_owKN<#bcT7nWOm%qF!yhFc7iOF zU0i0G#Q-vc!OK%qVis1Xid@4&7HFeBxgDL(mm@g&ED~!%bgNOh^gZZ>d^uU}#viu0 z3-GaJfIiX|LStiWpy#AvK&;0ks~;xOC>04DuRQsxK4=9;|w{KQ>L&m zrp)FJSNy1_IS*kaf~7ONYc#^ef_oI+y?|=gtZaq@|08Wbr(miC4?cqAM7C9_ee&k2 zsKbA@HE-%u%rziV=)w?QPa=p=HxADJTyqdyVwG6Xk^va_9d@v>pwHc(X`LZ2{igMbD)J! zjs=*#U)Q?KgAt>y$iCISH6X`gVr+1w|Kwa)&B~QZrIL)FnIq}jtN1x~)f_`FTs6nj z<5$fAdgvQxSIpsb^|CpN-neXzg+(bLmJVJvyA6C^c*qTJ zNS1BkWn_bzwXsfsdaG|SUHi-&e841q0YUBoX7hd?E@OQ#hFw62YAYOJ1!j8QP3&mqRx7YJ zTdm0uCexGYdIt1>QCqDJ=m(jDG&{Yw#Tv%4K;gXwNR`?n1HFO^Dx93>!&QUQ1yLgM z5mKkfa?^5?`fRpFyM|{Y(m*X6rRzJ_cUU^8&M!?Ft}=N9F;=ey@Okvk+2OQc^m zTfkv{;Kiq7!(5%hYG*(&@O5bda1m>1^g8CkVSSKtLiv1Xjj35yerbvgVGnWV1~vF9P?IL)Ys=VNMo5W3hD&@`IiWcnSfbSE^gLq)$5s>GS# zf*A#xp;myJdNew|HlBt2ya&44rKt8|NYOputrvx$azDZ9c@*03=fUpqko0XC02ikW zZftV-pZ5F@<(z^mbzk<=0zYDFT7S~u6le24^y5hwWUsQH5ApNh3^vpUGeSuw*FyE= z53u2hl$>dBUGWd)RERhWGCGu^3Ltb%6Kn1P;p;Sn^911&rw3*C)Y7kJQ%Sz;OH^Z} zl&bSIuBvoWx74W?=c*N0*M)vPVF=MLCk%G_lKq@zKkwjYYsTp-eaV9DA z#JZxofYu1%C@0kAXKSZv^=3)E-i9#dZ-WQQaH)x8gp76=vcP0W!X8KgN3c&SftzU*bmb?39-Ja%NnZk2^I!OH z{TsM1Zd~Pqy~RF9xb&y=C!H!s4Dfa3K;G_Z=J3!V7ZlbwN@Q~kO#aOr;gr_Q(UGE? zI`kCV%#lQQn>v!LL$dkgWYgN}W)MGZZt6&(Sxup9=aUS(Md@A!Nh$}8YBSsF)0@)0 z42PmVl4Y}G74STIn_lGv$bgRgl?;c0iZVbPjGso*W%FfLZWOg0v3|U$a|s%$UgYhZ(R7E#^r!EZ(y0n zj0Hzb*NColXGXeJ=53_QNQx+qD5iO5k!N)o5Y@FuCaNm)#?k09P%fsjBm9^soE?2v z3QX+5QfNjOlzL-nBKv7miYM`VlS{oeaIG?~3SKiDeZu4d%=X~XEA!@hbJd-}7>%?K z-u(HX=Z(S6;1kZIQV1A$l12|B^*aE9tLvB*h@GQQ_RNG9@-loFjzCYn4n$nj#L3t( zw*=R_5%{hD2$zIZxm8kxoLoKOoNlc~{Z^YBmKRWY~@=};zs z9Q;CYrcO_*Gj#@r$m1yk&gratC*x&+mrHQeeh!qvz46AsKvBI7u)IN<6s)=zpq6?B za&ilBYy2PA@D&PKniiT^4I_N1Gs2nyDlb9r^5^;UXn@-RqBpn0N4En;`|^M>LCZ6i zE;54H!ViJZg|Jt&1rop?rD zH>^u&(>NM)79DK!S>2SHy#x&8w?QC#3}kLBTzwIccUf34otnDiGQMDr>g8Rt!K?qcwE#*~i; zXzG$7Y^Fuyym2A`>f^j#_TzERugNt56AQ4VU^4a{p=fs5KF%9VEN2q+;A})5F3N_B zG2-s#7W%uWE32Bw7qFdlXskCj=@niWa>Hr5Mo4eNB1*9Wg1nUCsRa|QonEKnv0j(> zE&JmRFwuH&b_Jm4g^>m7Dh5(h$m*KARCOG_T8^>aMr0oA_2_|OFU$$NNT;H#c2(vZz05p(A=Gu>mWEOydUByOF27ZBoyA{}-JeWMbqP%y_Np$0DOn~oxjcIQi z8+TXUhrk|`L-6H(-|SSn=OP4yd!~D4v>XDl5Rz!m`xs|Wy>GVB`1j2L_|Asd24coc z#6{~_UYMJO+6MJ)h129TQ3$0$Ze>nL4RWB>L16fs;Ws*Q)Ev<0bnI`WIws#bih}uE zu=FTGD6-K@Q;wR=4Qip&QEVH;qvk})c--i-a@N%#m%#Kh^fUPA|L8q4%+K$cGk7&B zTx3&4Fw<&&7xj71Y-L#+I>&z{f5q><|E}3mLwtrdsmN!z6MqlZ$dQZ|^aKF#bD@lB z2cw?=)%`n~^DyEO2MtU05XWc;;Z3aKcNo@L_hVG$8D?;rmL`L?p3$JlA^H?Zb)|Hd0d@!uey=^HF&-`#*i#s@c$W%CVWnR&yT zOxZV}$^pE_&)H6*gwcX@1>VN&+a_SPYb1r?+YTXg*?iFb_SB?dQ+o&U&>n#JW?}c$ z7TAK{u&VC@>~Xppqfb3yS*dG0)ZK>xm=L`b>rT$+ACiK8JGpaRVVw1=D* z6h_At3N`E(z2MT76YPb!Y_8d^*>vVSGVVH$${BMWsJe&G0}+RxfRye^R}a!$Y4k!K zs_^kVR9s;m>a1^`0+UdlqWq(DkiUZDmTfAu%e2eDAcWG7P6A4E$0Wr|ODEyxl1WO2 z(hYIL;A&BnYhP?%Oid;!v2FhTqTS$$UdCp=e5I$-GeQnAQJ`)BbSulwEd;}Ew(eWq zxAbqc^C$+3a;dPWPhmcL8FNHmxGw$#m(X?47e-2N*7LjfX%ke(hqur6ze>wE&x0V6fh_s{B?i(}bFnWh}Pd0nq zeb|1A@1V3!trIzp1mz45p&%#q-C#7bn-0?@g0D4>4$324X2FqYRiyKxNR^r0jv~#@}YeDNE!lE)%8H%*GsN;i*H+(QiuGCnRt^^liRq5Wu zgy7)s_6B4)H-F#(U{u&H@;9)YA(o;ex;tDzD~PaYq696QqkK7!E#@~Vz^rG zTkj)lHNE`+u3`Ic)9=>qM#?_eN*yU0-5&CIJdHRQF&gMX_^)jOFJ3;zh97dkr|@Fm z1aj9LG*B#9f4&D~X)n~rl^`~34eqvI(Tw|n!>@uRw3~E|f=kcYscOkCu4(dv`1?a(ZmE?t3`3(5{FnLStsp1uUg z>Xb_uT>UO7(f`bi{a}vMjlHG+62{)I7crZCdJ(yIT?E4ieq6NnA`r}Z7ctEGT~vJ3 zd>nqn+kVreClEM|uR6!OuB7Qh@^BbX6J;9>EEfK9_c4S2h zt$YE#NraB(x-5aB>x46wZXR@mHKefti;Y;i1LzNrM+mX)BXajW?o6%)pWZp)Y-VMn zayTHcH906d&H>NIP%G{tF?d}HAXrkK_O^VwSpl@8BSbERp ziKCZYI9=fKG@|h?Pds&ZdZMDE;Ke*%nIYKIHf+srLZ#nJPa%PN3wpM+HU_=|RqaP2dWe=v(OIU|D zLcgC4(??fBFG1jkxN$u_42P2@pd(L24{F<_E?kIVn}{j-g3!#W*8J zA*hZTNyojJ$vq9fVr0S0nKObTLB^Av?|Rhr=-Nv+ejMg$Ll=g6f^GgjHw-JTESQR*vc2Wre}9Q#@O4Gx>j}AFoA;W% zW;!s;6C}q_PZqs4#1ry*|oitf;TI6A>#4`7d1J$Rv& z9yH<%4|>sP514BEcsw>v-Qi<|ix+_2d>C8&I7vnqeHXr3bAV2I06q}E!n1WNwuR&1 zd}+jlw~O;dw{9ZWFj~`xtq^+jnO53HG^Ld`L|Lu0%o70&7mV+k{(L}dp#4rzQFdTg z^{rr%!ff1F)x)wZHWt~v5Ze{$lyr)dFY+6oegG^RDgd8ls&j&XUj^V>CuwOFc$3Q> z)nw7dDorE${SmO?9;ng;>9t2;?Z5m8j^21glSw-t0oh5}Bgow35s*XQuL5;$)T5dv zD7zgXIUa|BIZN+8HYaD%+Rit5)!3*xHUlEHVI%~Vd-udQG6`{-_K zv>6KR3Bf5BFeeZhS^r~&Cvoj9^l)n}blfbP(pnpbNtcx#O=G@PjC?e^*an7?NIwP7 z%MOq_uYyE+F2HY*h%E6Il+I(tBxvT|13az}Sx{ zNwve!Am8x4$cH`;-S<8ix-bMhAnYgrVVAsGUaeyG(SOagRH)-M<5g({l8S>>Q({{a zU};VUYuSt#<$WP}+<@FMAG?i2tPjWFDA@}G?<5Gi7Jx{gt#lb2I{SoYzy#Do`h>|u zZc76Pp(ExawBat~q*1>?rCobukxpt)(*6H}YqPaH(MNCZaip4RW9PY|=)fLF79E58A7#`V9J` zQr`^bmUfZ6bpW`iiHI^IY(`x>ItRe7pJ^4?UQKsIccktLEvwXXs2}j4{Y!G$mo?&u zG(QaK&_S*MpYBMh1;XZhhj^iDp_}Os1BM7N6>}!dfpyo7z1WAs3#g}Y*m_?{216!w zCTZX0RZYiiaAWXXGn^IuWc9bFw_2Z^H_YATbich9|*X8N*;2`GiY({W7jz>E! zo>sFBD0S;=oO@0RCzIgaNlWe-ycX!$^C$5*6j1&=URR`z+TR1~*{OR5xS6n{7w>_S zri%THWNCOvL|C1J&y>Ivmg1%>cMT@8+%p*1P5hL%VmzgnyImHzmjtuGmr^hhYR7%5 zKwNwmJa_m^7Y$(dUPC@=au-ivcaU<|5KG_vW-x>Nf+dXUm&;7f;60gQa2On_7PCL| zLVOdpxM?7>XbvRF4b<=!fcQrMb#8@Q7t^1Yq94XX2D%0}xK+X|q5ofER;J1AKu1Cy zj{?{bI_ijCe$)|yCl+=u8%8Nk`sqDKoPogr{A>JcXu}BX$9B92cZ~WRPrT;{qu%d9 zsU7?U4;uB6KEID;E4T_$mGVE{fp&zL(ww zjCna|Sn%O)J0g^EtaG_}ks0iqfYTf79hd7R#+@>1t;^CU% z?EYA?lmnf|w;+F(0lmhLF0mtC<8PF?&3qr>WBZ7GSU-j#ngDZr-UCF=6zr}WL0^6y zOs>mB=J*^9(!C1^9mgVv*`uM=?g${$9bj#OH+miE%U zYfiAWJcw0}HL21aM1_dSRF>_Nd=e{z(%*L&X+40c^d~#zN2hS4x*(Pw#gw_@D6+JF z5QKq!MkTidhdIb0&d|)pA2rwQ7h-m_a*Lj4nm@fEXcvY;Q z>(SH5xt=Wz((cR!7pJcYh<{jBQxlx>S~b7{FvtJ8|8=!~?&(|#_up_M-UmoRn36C7 z68~w8q?w#_@i(vuz63As5x}8n5gcT@Fb`Qjso8>1yFVbbR=tKzH8#&iI*A>0{a%_j zY!Vyshzie@#ON^zI@osF&r)pC0?h*2{i=Fqpx`D@2J+203&2q4(DsAygL(@>D%kWz zfua~W6C~3cz-za9Bc6AAw#RSkR#{j8zub$#i>!p0njO3{PnpO0Op!ZUUs+PFOjo9> zui9rL-tx~4xF7l91it~~0P8n^LZ~)BIJY<8eP(Y!KK^m*aAZ_92BVeHb$94%H3Nf` zL7W>E&+^c(>p{|i4~6#W zWdLWM&3FyWANkNov!x?=DR_y!B;r=EmMD7-d^-JJ1JiEp$G9o_H8GKXdX;^`t71}J z4Y_TD5g@8~5)f|%(2R^x#;6}VmE}x-RqR30uZkd{W9pWuSMk}u??zqXLM)x!{g(%< z*^LL3>;~?FXU36{`m!H>dTSSM3$iwJ&WPljuE>u4Oa|m_7uQyj{sB9MH7G<8KW$m0aEc~m_ZhAW%q!m@^@V^+FF2z!dbSaU-)1^i%&28^o%vcA4YN&3g%nErj zT}+egv^EXI7uQ)CPoznWDJKnd7u{2&7*lQz3(OT285K#trGg=&Uz+5m8>x~Fo239Y zelSj8f;(<8!U$yn2XzaG!nIg$ zhat3v4(lq@GF5OnRS5+wh_>N=hd_uV4Cl+ z#!jYub{*~Prcuif5Q2ArChUU3PCxpWoI?9aj^PgGZlSLro#U4L2c`q`EOvx&aTHyf${L#SSUdN3c`S5!|5bC7X;O|3#(H=uNQL z@G8sL1hb=I6B+~;d~|iA(XN9EH2@Zn-5X%xe0!r&FD2l$Z0xli4B=KL;a^=QJssO%Ov22HOt?FGZk-@m94KZhXbYiI1XlYH z`q&2avf0uk;39eewVeVs7#55C3T&KjBNq8aSo7yYLCx%(Y!Yk^DseYz^uIt&Tm_NY z0f2&@f|Ys#ybd40x)p%(`e#^&Kf!KokMJV)zzc**NpriHJ}Ln=>{yA}J~xe9(s&F} zIhI?}a-sDfk)2nWQylSgT>>cK(Vrs2>Jrr99`Ose9I{*bmracLiQ6sNSzqX<%d+zT zUW?%2T@j@;C)mAs0_brf{>u%SETMDR+!^KI-HkMJpiFK~QFe4Cx4-5h&NzJKSa`(; zfpM{%fKBXy-<-HSE}^vnGBVCPj+OUcd;a9%y*dvf)V!8naR7o7sa4pKIP(HAeF&m+V2@G+kc%MxBa_X6Bj`Ys=|W0H&J~bAoE|o>7sXI|*Pf z0IvX+iZsQlHfoj}9994lh$)JZcb19F${P7T2d!qkW^?l(nsuQ;z(WRzSY4nH)wqtp zimalXAN=+7ecmnzEe$H+TxJRHT2?tRJGzQ@kco&ni}0X1&}{ow{Uc>1?}){@cANSlnLQS`=3zVCoj=KsKSMZ7SA$C+dVQX6si^6Q+Eylo~ zswHf09%z+*ga+gzU<_UWaD4$r-xx^$tpMi^0h9DI#@)w&pCOXQvA2`BHjq<^)75c z6@?TQx?2qftODS0H6Nz_vgja>x;~)XWSC|S#<0)roak<$)SFMu< z%H_W&jOC_&rWh!n%$3l+%iyyQ<)1A{9b~w|L?P93q&&)Bm1XDh5tBS0R!41Z5*L}q z*4#T+%~!KB4^g{lCB_rxq6kDP2XGD)OxdPi+)}E9!;)eQ`kWvzK7|E^)=pE^QCXYZ zvpgS0Y~vIEGxc$Gj^irw?`w~3OkZAmg5%pXuMCR_emrwGs8vw{ZcN0FDJYEk7mJZT zIJcxcdbavWMQ}|5wxWd5eMN3jznrJ3s72$)wb@vx?I7R8MAlT08h)FP%;<2nGLXbb zV>$yhGATFsY8MB{7~#KIUWs{%8OvuN-kLgSi^_A0pztdS#;Jq92)@=uQDV&t*7o&z=ly1D8MgPd2-m)ZwK&4?ze~ihy)(&a&VXpid^U;Rq7kLy%Zz zKLjW@ZcC%chs^Muthvoh)`w6Y7ZNWO0LsnYtViGM!Ud@WEyr-9HJ!eRPvg=Tj&!u`Cfb0DWe?v3goJ&w^RFS}?>X+( ziC~Rynv-nsiz_IqR0GP}KD2$P*6O)$fP>-XzKnjLHeuE`sPnlvWqZy>aw~2d_uAEn zM@G@e>M@D>5}*QA3ZTBi;hF)OKKD&r9EWyYkVNor_G40hNFmK^Ot0IY^y8`)AU% ze0^w6WFGhYD;TkvSl31#4uu`-{$PffSdE4mAgWFFRfIdd`rRmZTT!k5anWu)Z675Y zq}Kk{3`hWmD|RR(jILBHkDW#3<>G?(#?G9ueEIKucyx1H~H+>A2n5_lJxD=hP$ z`WPCKxta$xO*KZ?R9+XK5hr4WGefVv11~#3lgHhLcb9724W5BmMYife*To$g_6ia7 zSc1(Yj0^E~sgtx&4Z#Oeu~U7{$p((_pm$^zSNnB-#p8 z)og%a2E#0oF8R^(zlF)?ux2YlmCSr%ZGhrZ>V|*_ zsBlyebacc86=u{bI0EX7JBtG%E(kh0F394zEAs!I`;som@AI#6^WJ^;ZTH>f+;hI? zd**i7pJ|yxzv#7HtTQaL;|GACV;4H@7}^R5_&6~lRt1+vLrW1!B7#_BOjRIS zmp>X04v9HZ7pe=TJ|-k2pLc<+$spoh*}*{=XTufLV8@(EI&Q)?9r+~AZ$HA zr*@kw{h_{N?<4_i>Slp>@)c}4(l&gZ?4XXh}iV%)K-c>Yl zH=H8|?>3p6;uq&qnB?3GgfuA5V%ey|KMIa+;mrEWXGi5);(G|G6)~4lmLk&~rgblvJn-~^znHjrc}-wx<}E__5&LC~O02@uEM!jO z%-e-5+U`i^%C@_(=rfHSSHF?Jun_hp0UrrvkM{*r*5EE|L2@yNpI}q?3 zuJf$9tm1NjGkzO7g`2=0`4LTBtaoarR|gS$EC zR~s<8f-5&epOL99fR&D6R4e)_HT=8gb=`54qS>i`L4SHs}|&ZUFr=R3gR5kVP5op-?} ztQKB0Q$f}^KwjdfL60}U2(R45t+pv~7H1Yy~`Og<5c z{<=W^#6WF0*65!j#sW;qkw)Jt(IG-%D18JfEmQ%?vx|JOTFhZpn)lo99FtE4p0?6! z6YnPAY@j}^)+pp#33yvvuQ!8snGoM)rwQc5_j9tElch)u)8s4FV1<~mo31cv?Sn+; zL2rSv6AQ|sSXt2D_3B7jUdB~&eXwLNJ0SY6kzYPoiE!pY_enZy)VioyueAcnhM)8% z(OpA9wj5#p{Z6isimIS{fEcse9AYQHGp5EqQm%$e++^jE541{H0;-V_Ab%@~* zIlwGHZb_bCgcc6Qe)jiRYAReR4-pYa?6NOZrJNB0Y#Z}@Z7^jhGU!DE0_i+&&{}9a z5(%-%4O*L59eqJ4FAOf?ya|LaAg#%&GrkVY?TQovoPio6$q2p?73p z;{O4T4@W@j{W!G6*D4m_yG6uf*F<8KRs4zSebxN=?Vv*Drv&0M4;H{w?sj0BnU9um)37kv)JVn==Qt90L)(jJH z`u?$qA{|uE=Shcpb@4dpvG=X{-Jn*e197G8Sur{@<4Y?ErS~z>6JS`y1N!FE!HMa% zjOry=E=MybiQ?6TnKF?7<3y zQA}HjVq@VO2xMWS0pcLe8aoCV<^x!-RCZ^ciLGPdD*H*GvF8!+;6tCSSSu zqEYX@4%ZotNa=`34-m|W@#*%fMCVG}V{|>fQ-gQ2=v&o+s&Hg!z*{ZX2uPa^vVWjF z>@Et1ozrRk_;g>BkPfeeWn1+lME3(|+mETX!MUdq^V4{!Zn~kTnK1|a2=n+yuzI`< ziuy<44}1sDNtg*{2?Jyw7$99rBaFTOgK+zAn9g@W9={7rmepwQgAp~*f}kE>!#45` ztRvfD0KN_ZBEvRS6MXd0N<$cErv&BCV*N{v<={27 zV)WoZrW~&}9IW@hENTGFy4v@Ye2KC${@QVsLl^Ch@+opIG)MKi;eW~*M&A}Woet3s zBDv!lW32424%XsdRP!7CqsZx!9nSau&1{=5##vN9z`bD9nk+sDcFUmmHTDD&yc$-P)i?L9X-&iik5?KXpne6gwd@@&S~51EZSz= zm|sOxKeW0$3)|-f+wWA67X>KeL#x3PXn$Zq`$%heQl)L_nfHo+E7gd!9rZO(ZS4>Wx>(;Cb}@~mv$_D3zZdQ4{jWwa zj0XI-(7V&S6Nd~L>O3H!VXYex3;V}Hkc0ASY%p9F^F%$s#%q#Al+#m^Jxk|2={$)X zHF#D5@pY$@*`!ILZN;_}z8z@IN6R64|DalfrT}@#7nq6ELB~70ML6T%1oiNPTMQ0^ zAPLr`=om@=6J;*c+i9CY=j4;l(*A{dR~n|o)|Hob4D!FFwIlV}O1J_HJtz}|enp@6 zPvv(_{*n$`OkQ&l`xAi31U&6N_C&5ar-1%A z0j9vA*Jw1!dIsZvOoyi^-I@<{A7JM=`35;fwB+|G5OVtC6LY;n^(~Cv&jEd~5k74( zI1Cjd(m^lioRvULy^n?MQy8#rQ%0cL84qukOsv4ahuC^ZM9+8()G2GEFwl4-rQSeO z{RVZNc!LaC^AOwfbvaSS6LFtzEIh=8`m_Sg3)$p=7 zGF&wDIF0y)_B+2P3PZw_@jm}0lQ2EC7k65Xwr%e;jmMNXLaN}aYLV#;E}QY7S`9zn=Jm`(jhE|)89 zm!CZlMVvcKn;HKi36BA1WK8Xm zJUE1zFA8f|{U@}t#M!B7N(cge%=V*L!ecoGeJ@wu7;t|<{hu~jJdeo7%03!jB3~<> z2e}Eyj7#>rT(X~Y$$sb7eRi<}X?(UkmtZvrd?W|7NZBQ-7;zDV;@bZ>f5+*Oh<{S7 zHsHsL_(#+u$Ra$3GN9Nic4joml_6{aBf{XW3u!BPEq5grhmc5*!sPNCbeQ)+r_%)B zP&pd^NJyn#1c_B**8Unsmv;ed+l@}}7l80r1LG{u+mo^8Y~w;;bOE-xuq5L|=(Suin%<$tEpE+MO;IB-u@2G33H_z^z1m zjCLZE6B|8^E%ij9RC!>O&DKvIdz9d|oZZUHEHUb-U5 zL{D>)Qh?+aY-MMPuF)=Fw%qL7Wptwxv)x(r@ocxHJXfr!8Ukfu2+mLez-$8%k?nNr zMSq9}Lm(s3-!0}+NLyvTX>vaS|3)aNnb3Y`yqGrXV%5H=Sh>{+X5PQiHM89g*UolX zPq*8CiZc1|j&@m3wA+3h5x3lqrbpXlZI?SGY72}-QE8@-T5&HS#fSxw`X|xMBKl{nUGD7*>x z2El7-Sm*?*FX${t?xr5VhfW1B;{8$K)R@Mymd*2`=fxiC0er#45kMrMO`_SAP76Ux zRX5gB5!M@(;zEqzFz3;#kwgc+$WvZ zHZ09f7%rv&C-@)bKjCiI2xM?iEI7}BOmZjGwLuBdSJ8K0gSdT*qD=LPV$fX=WI1Sl zH6F&h2;P#zLe9?0UYK7NIjyN2^rX?)-PoP89k9qabuyO&AEj;~r;X3HObRUtK?=j_ z5kqd~LzxdDw`}Tjgs|jNgP<3LGu-3#=Tr3GVEESTS%!u|)8{6Vh88{Es#aa;B4h5C{)W zEW&f@2ZP+;@Ia?SUkc5q2t)s+@=I|{TPk=iEmJL1>BL~CLsx`VJp^{(Du1D&gPeXk zJP59)IMj)+;H1@q@y@~*qj@0S`OsiQ{KA23F6W>fgPjJsM#Rw<2jY`mKM>>zNE}o% z5Vgurq-8iLZt{cj2k~6wsdno5NEX#q;}rcO6l_LyBD^-Ux^PD z7q4E3oagD$kh7b7=2`x5xJDN~-SYhO4n$+hrzvG1z3bkV(@hBTtcQ>I$FZ`l zG743l?iYEi$E*S!N3F})ao5msS8q~fOR{e?TwjB=ljY$bi#>nbSGr>cy&Hgj?UjJm z(rHP@BTg+1a7p_U3lm z_sNygioIU7372hxcDp;C9OJeax zXyp+7Tqo%2K1m)<+|~v$mvEuDkO~?hV;}I|8Turpb;*n$4b);4jwNY@bS{2lBf+vj*tdWOn_id_R9~QLyo8kjD>TZ1 zP9F&@m|K+s!RSBAH=)vg8l7VmAhP9H*A0b3vO}2!Vz+^M`^4K1;X*Q_-XoV6+jT5t^#$zK~7%e53fx^yYT-*M9IqP=0*`Y5rFeXa#l-$Izuep~6GCGmtv3HgmQY>20=%3QKEL88m z_fI+3)7|CT>}$gEKoToMg9!V<^jfh5N+0t~`Oa|lKr0zpg;=2~lc?VYk(Khb_%hf5 z+9O))pB1Tqs?rQxL7CPreJp;+TdsAOK9rju%UHpBdoOybOzV>FL`DBzMN5fDH8Wj}8Nl!ctSp#gvO&Ha)Kp zm{Y8*Qj1fIy=o7P+8xgT$#q2t#Qw<>sq+nBOE%u1vCs6VJ@AN46om6cq_HNLe|1b< zq%QKQJ@6d5^cW)SmQ@7Q#p>b=HM8qpdVC@Rr3LhetA4#EgH~LxL5$|>HFni~hWlv3 z^@swJcRlW%e7z={KD!Rd!5cK}pzUGmQTYW&L7gcU3)K+Mg3u04)ISOamHLs; zI|o~SJ)ugL5Tzj}pFa5n(B3Bt@%DAol?axt&H>zdYAm-f6acOw7!HgGVFev&FlHDt zs9?IX6DUR6)qe@VG>MmgRQ)KOo(6Bt*QP0R=&@FRjGbk-6kl!B=zY2Gv? zP%{Mk2y**W#O*^K-KXeU3h*IrT++r#p$eXI{ zN;>R9nD`8)z$i=Hufq`d0Qj#~!Z(T+lw)D4%z-g82^hYUkT#!2l)ja)kOqL@>#odz zJNtJaqdo$N#k1V5!J`q9is5Q72un!6WPr!{Sx~sXqu7U_AP*r#?9HmL6c`@4cf*wl zYetMx^G7diNEy$)RbgC!t@JEI}U@U6Z4%{s8+EXfLc7LE{&fXs4ou~ zFY;6gTCy-gnZqs;b^cEOQX8|Hew7P_Lsd%y8GF+3Rw#tw8AwuS3rvN}cwj<|To6q@ z$m48L0MxvpMWJxYhK{@IdAOC2>IU+(!9;| zfhWU9|Mq0K2J7ROTo?;$?&ATdC;*r*R#Lv>JbYr07uN`k_n z0)5&5c;h&g65NCTjm7QLm^^L+8Xy2X0Hbbf5I@eN8yy7L>KOm~wV{v_v7Z*aEbL1+JGnx3$-c^1_IO5l5JkA=bqF@apY=RuARt`mA`JB!y zNOCvHH;x|_xO4NrxdXMH0Wk!y;z-!?S;wLb$FTfIj4Q!KfqLIo`7K%fF&&0oLmx3D z1uOAkg5I<8&ca|A2-9!m7lWz2zP>9z7^+t-S6uF_s(^ny1R2PQ74~uRsI@FqD=nsN z8l$&LlnN{f2bQxCHy!aV>N2FuWeS8sQEN#NN>(0+Vi=W;&&s1-!}1!j5DJNB4>T+f ziv5f?=v0z1UHY5&p)3sob?7hs9&9{~r2 zT5c(plD1YHmpcKr{$9}&kW~oshXF0$4q*As@t)LGWq==+Ok1}N(@_|K*aj(mh-}1G z$S+`u`4@W84mk1NDgfnUA;b$iWH}_U58*T20+`@>SU#Dyt05@r8g}7eE9iQu_>Qev z0(3n~)L|ko-oU4b=SF4#WUIkoc~w#$T6m)glvOvH(r7vosTXB(hL&Nk>n{90}Qm| z?evD0YesASrlhiwnr-<~wL%ALkd&>=Lc6*X&1WMxhwD^b5xenT#jK5)h$vx`qYO$W z+J9p*e5zkbb-}_VeMmdLNF87rxe=^AV10G*jo{n8|9EO<*J+SFpwWeYIhc8voQMA) zElHy{4ilvlj6f*eEy2jsR%Y;@%6Koijxwmo<-5Wg3wI^y7y|j8{4iB*8ny8%ak6|s zejM6*JXQDSyA1u)T`ny%V&f1|#wP9(zgXt+)Rapf2an#DA4h(z*2hURjovu=|9h8F z8%O==k@H|QibVsV%T^(njau&|9_lhx2vVbtWiq=>LsR6C8JE2#h?+W<@78olmGi2@ z1=t>D{vCqGXPC+_==A;xU)&YSQn&jysWWc!KuU_6&ozthoGK1{jsJ;e^V9o&A`3+Vi?@uxql1yVvV_KR&QVmp6=p&UA zPMtaZgl%;^G-tH{k?Pa*Y5b%f#Vi#(2kwI2un1a1BQ%C@LYZ7IoHET&g&c-W=sKYK zhDaGeaC{1m$8CsbI7@Y$CUnyQ?>rMs3s=od=|sMnDL(pbMhY~lGg7>?pOcfbQ~YEa zq0ef${YzD&Qc!o_1j}zacg|#J6csnA?t-dxqI6UmLKdeKF*oFbGty-@>723qo|xR{cjYOhH!+(q_<)0|5~G_dsp7Twj5Kh_)=e zC(BG_UDP=UQ^Pr12O@^}+=1F0I61>&E%Mf^mr_-$OsmK=P}_ypU8&93G*HXFw5WFZ zG85rHf9gs^CVS#at%=s5VpM&A?#D(pRnJDPjhLO%4di|~SQ}4`EezE%=_KX@K(dzd z0$KN!?yF5GjDLQW3BH|&XQrgn!C9#J9kalNfe+!NwX?v0Q9KKk-ftGJ>zsvefO0;S z39(PH(TU&FHEgYBt=vjW7^2<+%;$2DjPwJ@;VfKoAB2xXHP*!$P+`0dCD>BPpK@H0 zM*&nXQTCw7AcI3S2CSZJ<)=kyraUu@*AUVoQR7R-mjp}5DKp|`I?_zt=!^x7^8vHT ztD6!H0B{>k`8DNNy1`=VF3#7ZuL-0j{9L~jN=!^T}@;1_q)SKu5 ztI3vnb*MH}4pT4jZl*YD9S7p1_&Qtng6;+J1Xo#24iRNsTcRzYK~{tvIG2V8=w>w` z+DaPW=i=2qPBU5Mw(w$_31Df3LdP`>c|+WeKI)&EI#a9q2C)nQ*Zw!`KM%kHbc3oA z=Bt6KPVnUT9&&&|*-vw9iZ~mrs&=F4l!O0_>tm9-ECjm|-aMFj93{KRXoY{rs7$^HUd5n`g zIk}dT3Qn%(q(3J!x4kXfl#Df6QC!Xian?RVZeAn%u-Msb60+1!` z;AA5w^N^?iP!{J9n#&L+-A$0OgpGXavl^>rw=3|d z8pU@&YQGCAzMUB1@4y&eqdL1J5}K@xmXk?ib(2P8wa|~rAT&9hjI9rm^zS8J0pW@Q zN%smdjgc{JF3VY}%VjF5F4=19CWKDlEJI<>TWm;|iA7qsT3WZBqbriFb^%{5VpwY- z*w745T%X#i$A-B}yGsaFpU9mzj6D`ay z{H)HQjUAHq;SLCT)C;EYl318yoB`5?uM~qD3iBvfVLC$ zJD|-Y`vJ_f=ibp~bK+OM;D3S6uhrW+VIt)P7L=8r+SM-TYh?*M!H%&{yN~ML!3;j} z9b9hm+c;m%7diPhc6*Q1=hBA*Qgi5;0T|Tl2Bi8_=QZbf12m=sFo<{MBpJI{k8`9l z7`y+Du2~L7We1G8@1RRIBc?GE44wy0@Co1-7Qr^q1MC9df=T@WkY^VnMk`lZbr1DO zNCH&w8p1&Td!0T#`3m(&1|5iuzpT?cY2G@0cN(%z57BF#zBm1GyFOXNipupV>uE1n zCvvpBg;+6nAix?*fxPr~eG1LF11DX{d8qbWt{FeQu~y%e9$l-?;<|?;)LMP~D?rHt zM=hXxUD@jH*)#%Qfr{4R+@5Q3dHzszU}Stt3kVjRYN4V!NIMT|$7tiR$t$JGc3-#& zUznSrp|w>w)n5JZ=3aUupg52EXwQJCKc#BT?}d9F}E z2@hfh+XFjx^>!VX=&PBi7X%Owxg7^5K%hJ(H? zVxY#ZzZA+zO+&lgnuYqkV*M|U^6P+{L2wonwa;16dWu+_@*M&dc!Nldc5&Rq=g27@(hg2Ytd0Gco#8HUyY14JWvawrz2oF34wfl@7+@^i}11JuI?(7Km=9vZpV=c4m3`TB6uiB7)cE1)M{^7W>r zFZt4`$4kB*g2kn`A|l1bn$=LTltA|Ggm*jxHO_7@(%*{ZTp1+rLNLd5L%cf+cv~(& z;rA5~y+>iU-w%OtE2gL$q%fA(qon~*oqNDM_CG9M4+GBfBzXL8QAAW<2kJr;P`bL0 z`>$w&=<8t&Kny-~NB@+w_)j@?;!DNPLeq19L2rMi$twMi=#D&cz<9F^R4svq+E}Hv zpJ=A6A+8IAbq{vfd!WPKHX#E<0foaXHzM3ngEp1iL{mT0q-V%YkEteb$9mnha#IG? zM_7FmWuXKo*20x?i;XUk?PROv<`<1(=9~TaVGTBSCO-mVs|8YTZnu3?yX_n0v8;}vf3g!>)Gr(VP#Mb;z~|THp`cxk^cw9u zrEy7Li60vADcDbQIWchZzf(w#bF!C{zjCq$iF8sv>k~1gOZSN%I)HIod5?m>xGnS* z_o1F36IK17`WlLwm$Ayb59_=t2t7k#qOn6^a}Mq9ta8x&Q+5j8=Iyl1pc5!@q1QTS;1v1*2D zDQbIM=x;k@Jtk^NWQ~T|l4srY4RTxHGe=>49gP4}?3heH97QbWCypAm(lUDRC_*QH zaumAtH<3s&y8S5PP2Y&^(J+5v1jgND&A+(x$kt3*^B>Qw4Pp(RzPRnFU~d;$b!0kf zbaLWItCyR61kT!`{rL~lCr6CVnW9C&&e{+{;1geqP(1?~1HUN$lksEKkp`IBOr>(? zU`;f}MgK%}IgGs0=az3F3K`7(bU^2NsY@n3=d|YYOFl49B2RF-BR}>(@IpO-OVRmLY?)lelp^-;Rh?wA>T5;5BFNVGeQ?Rz1agmBuvv|OP;LjX z?`!b%?}J0`CXD;lkasv*j|(cU(-;F^hUxGg5vyk|7I?iRC-lo-!*KW(EFMpSyXrG7+d0{ z{1GuaAi#tw9B;&Rp>lX*im;ZcvMC&H(SWT@%AFhx)flZ}bU;>_DyZ2^yEdfSrJMOD zpLT9Yb&+fca$aYvcX23aJXkraxX>Ma1dBTjKJyZXy&o9PHAgm#>M*PpZQ zq@%}-*`9Jnh(*(*?Ft0o1|N&szMeNzm!)yi0HL|e@Ra4$rVPJusw8p5SC7l382C#J&`6XbpjCvq98C z3>;8V42E@n5|79GK#d6Nwo9l}V0f+Z&lO!U1{pK3*yj-gZ!9b*kkE`J)23UDS#m}cc>AmU2qBwvmrE9PX`gIL>e+1z^C zdsnJ$kodl_nx#OYOpp5nYp2O4!2KAq&ZG!1jgb4T{l%z{uN{NYI*|Gu72K7YF6|XR z6v4G<7AK=Qxq=f9C&`?gzZ1zvoV>=#-;gvt!>y$^R8nxrdmTvUhXLoj7UX`@u>|ao z_*@ylI{zksNsj~7b+d9YXmKYB|LZhJy{F@r;74EyUJU}>8dx(XgVwJb0G$%FUY~)K z_9bAP?`N%->TEd{ZQn=-OY5;@0s^Z#;s+wR~$W++K zV_9)+8MG(-PqSxnZ!E4Ui&ZBK_*p(~PRPOus2t zfeUNIw&y)D#Vw8Gj{(ojj~GwbHoVz@4^zyZH+@GeWoM(fUrymG6Okm3U$_mW>E70NI4?FkLagFHkx%KqvZX<%6?KWEJ04IAm zd6biloZQGsgp)a(jOV03k|qS4%~BO3rchN4y!e5QTF$Rt90iL8d+R|ii-w%ZqFKQq z03^y@rD&lLaS;PBm{Ka5S6yQ?r2B!#rsBFlJriz#Z(|5c408C6)~z?h$slGEWM_F6 z9pQgL1!Fcn@q#gp?&V}9CoxXSkx2ido_su?Gd!H6BC+oO({=XI zN7trh(}&llrO_Llv~coQPVPb?y+HGDd{~Qke5fs>#_G1sMWVB!RRFR85wDSL*HN!Yc}s-c304Sj@rbWtickAxvyj=N=`6lqUeKZo=o3J%q7-4XA$VLE_4uj0U(qeF~{y7i^YmQ7>UBfVvro+Hu0V@guxhj-Y4!P4OT= zKTQhZ$y)*pZlk=G&iFU|ILB(SaHnmbeVBU9hd+B4PQ3GB_t10l+dL#+BkBJzw+xu; zBT=1?=R$1O1ceO*oQLpMNZr659tnH?Xvo08=qYK%JZpLn?m2u!1kG;0b2B&DlE5O& z*0NWy`#UO}XU$fh6AkO+S1JcxoNKlB;vQ2Hs9-0HM&AeQgHRF(_$R}47K1G&=~m)T z_cC$j*_jTT(!G?PoNINvc&sZ49>Ro>s?sx^Ax3Iay3=4YBI#m|iUG zi{)*xu#a!w*se@-yKN!47sKrVK?Y?+l zkDT-*m2-dVswkIPUJgRp{G@6FoJInG_ZI-OsRT0O2zuWmV7^!a`C<&5?VJEUp9ai- zAFv#EqQzC9z4bwew2NqKZ-JnnAhN(zk#-^NLN9f{0#Nk7VR6yYH!Nlt&6$1U9XuCh}O6_T$-`|(u{Sq z{CT5)vR3sjF#3}e=<91y*TCn)J?|)jYu^WtwYlimS#YKJ621B<>24qqW6`917~w|Yg+IfzNbc1EFsYUT;1_L^K7hoXL9czM&!$Je zgLx$U9qb{KIO*{nOd)zszCDivhtBIcJiQl|n8cM3a{^1>V1xG;?=N)Ed3`1T1>UT- z`GHw$}(395FcmY`{X%_m{l9o#5_*OQ3WJzr5;)jO3WpPjrCq^XFE^2-gKRapH zo0eX*^G%DB?m;5$Aj_K;o1_*$G);xYNof;04-mSTAGwsZE52sa~v4y;@ocLPu?>EFG+P4KPqu6)QCtD4J zREhRZySE}lO7S*BA6mS{&_j+N23n7FdSIJjh;V~(DW*%1H&?}hQGY0p1A4w1d>Ejy zgG~84KIm=uoc$p~eyjK=G~@`=se1qNQfC*ymc&E!Mbt^UCf5z$TS1-muEuJOR&Q+GT{I`^_$HP~miOcjCmU1^*8-vmMhMlOJwg7q^AZ<4o$)1>7ju>fUxc z^OQ&kL}c>Rq~4_7B%kv_j@!~&tH#NY=H%HI7TO;C6h1kA8$YoAYF;&9R!SX_I)W>~ zFMrFt9CupVedruMXxpxh`N!ctJ*EcBN*(?bAZ5(~4H;f%u0dm-#f>RXF-r-Su@}HG zwgy)Cx$u)72o_@lTyKuUVUZcemcocU9v{c0RDfOV08njP5g?!r-b;lbt9Qb8_Y5$F zuY$7SKA1Y{fY$q(_P=McNsTn(JySZ+1N?*7>VWbr;-r|9;qL(?mcv`-_ZX?mTc?lW ztOlBL)MUr~ z)*_J>(G6Dg?vVJQ&#f2<-r{5z5-CV)EouE}iZzV^4*1EZ$<{OnU5Uh#{D1UAK!3$6 z&RNci(>%p&h3W|A@JC@Tz7Cp#DNyTo10hTj%<#uyD1Hp#i5lVbc{LykSWbNoYJnCQ=2yWlYIZ&CQktO&RGOin~%_@PqqC2h4163ooo`)DF}REKm>V!^K_nib(?~ghAt>drTT59pY!HHEGQ9 ziTo^x?#l*m@aeb#43=8kCXvJ^GM}shci9@jV(ZXlweV9ET zL9p&6iutOqpfawmf>z1#t%J}rylr4T}S5Gw2dpK$0WMNM;%oh1( zEnVHZ)t3)=I8h=&%$|AqXr7tkhhE4>)Bg)6YmnI8yhd(qLz7|JtO=&MsBgYGkNV`B zZIp=w!9kjPnB52~W9}oR@it#o{Fvzm6>jvF%50=HDzlz;sZfwOxt^19mDxhWc?(G@ z_2MlXC%-ApZs{iRnsZjmgDVDxcQLp=0N=(iJR7gV&}xRr`Kj`4<#VtuuSOG|54dnY z=v#EKDt`!$s3$;Vcdb+oJ6|7Ik~Od-e|JZdh&Qy{U?3f>x9jHCdG)S1o};jxg|rSN3N)vd%kZsMQr6j_Nkn~6laa}%d|BJGMapDx~tH_D+Yx8kf% z#SgXIinee+CpRIHPLSnRRNt#No4e4yo6Sj-b1SOMj6_02%v5H0U{aI^)5(f38 z5!a|)(O<%ZA49xkHx`Ng7&z-Vl&Mxw&jX3 z%s8pB94>Vgp;)b}#nmFlBf3xoF7VcYN;k14!YUeXvNxHBmmckgA+`w#NTp|%XO=u} z%_y>=%kgNsf29M@Qj!Eg2=0{jbn705SbDP{IF)=ic z1+IMsPNg|xQc{wxP!A}ew!H3R0DTwt5f}MmH1O}@ny-ycu_5>)4&@Klsy;>q4^{v^ zwh97zzDiOah8)$12HF!<{GRkE&@iP^fn-3({yQA>%TRb7{#&G=wGskmE|9QJep+RB zYey|&_9W+a=XNqn_8y3k+Ap6rNOt?i-|gw52vCb+Cdf|D&QbUCii3I%_8YCppW$5T zTqz#c1}qe6GEo=FDak3>>H#!0H%{Z1DofN)sGgvwN^L#m&$6`?pM_sGt)wazLj;}p za>SkO&gSov)9!;OBCl2{K_|}h$*(1d3n{h^@Rq2gttGZAEV76TO?fmLZ17z0T#zR_ z!8HGz=Q;V-V463m_IUR2UU$*z(%Ol~`BFaGaC{PH0>UfUzeA(QQm7(|TcE77!hb3Y zhL*O!z~4Lh6uB<1@V>FljRj0A= zoyGBaU&XrU9<1D|AS7O?@&WStEfhU_pk7=fREr~lGO{2t)F*JxVY_-WFq_jcwdMfz z{|ns74nn~BtKxRB@XX4`s+Ug9fjrWEE~Jb!B+?ez|C1_R8YBOVmVZWxANu+yl}#!n z|4%BrG+6x5V?RN)cPA&;a#F#`)tvN4f*5A!epI>`|>j5)@IuL zy~^L@mq)RC@oCc&4Kkj0k5=_x@S_J5z-~UP+5!Z_qE_X?FL2y^8|K}uf=6H`6g}OQ zP)R|7%NzpRG2`9}hC5OPzBRy#h4|B4XlO;&tr+9v@#wJ}WeyBH}kikhZUtuY&pQ~|7ABZ2?&#n7W zPS$aT}fxkY`^7YvDuiJ8Od0Zz7Ce z%vhKTtN$s$q+dYT(+z-1N1$h&B!q}m1c*8X*|r51j}3sfER{ltX>%3mC7gisvOx9@ znuqNn7IKxN8pClF)CB&lv>{h(6>!#)NKLG+A;!doR8xT|FW#0MrH37VcaagZ3S!%<`(VDdJm0C65OP>D{84fVnzQXHtkG zz=tqBkpEZl2q6$Z(Q$Wp$K7GvGfSC#1Kj9rM`ilHfcItj zw!&B`a4PA^^h%Z`n_kYcq)k+Dr6ySY_$!qHc@$qmr(Lpdk?)7&JUB{cTX*^EOJ~TJ zWpPUr_{U?`K{Hg+C>q@LVyrjygdpq9vS`TMGbP=W@}?M_F?0jzr~4}%L^E!Bh_6@@ zs{x!BjxC-y0m7>S11l_kX_MYcjU20oQJifrW-Xxp=(HY$V?^i5TB)0!Jve*33d zt!(-DRkcr|x%<>FK%!^oOi1)kVi`XlVw(j*+Z!NxZiGfJPpQUS@eBfZRsj5+1|Gu$ zz(cHp95PsSQb7kV*t^j73-+$G;(|Sw_WfZ`*8*ExhtYGKdK?Y8U>~F{Yz%-2M;%lL z>6hQ_IrR4LSO84^9p@nN(6>r_kx|Z3yfARnw<<(X$LgRnCmFO|W$y&P7r3>Boy(ld zc%9&;dmlt(kUD4G#u4^TZHopHG00CiPl%O+c3fi^ZO2*TtP%V452anp3lI;qSiySG z)l@oXIA_Q~n3XWj88XvTRK?C>ekeDMRoabM0LV)Yhb{;_8v=ni?{wZtA4~Rbsi@~v z7=j}8^uqmgw_cXvz^RI@j-Z&Zp&joVRM4b={b)bS*E0lwv z-VRG@beJ*9)6gh%0T);NPkK_3Wpm_<865!%LyYCS8-0qbtgM0Zd5gaTE$fB5UD>9EyBGTudETtV%I?&EaAY632DGm1_@a_R zJ#Tj%u8_F1l>(_LR&ncG`F;O<_p03yUNpv^)k+T@G`J~b&CE$u;T_gYhiTgGFi0AF z-UN4sv=I)_R%>SGRyGRxtvH>l$a5Ivx(0{7)lPdixpK3_tMiL1P<0B$0!2aT?gqS6 zqNtVjzX{9?myN%ad_@$m*j6AvUejN)cq$#_jpdWF?Zw_h>e#$7h zI$hK8YfDVaCdRs#!0#G`%5nez;2eMaQ6L>>0p)0eeS9CB5gLF#@B;z+0dyE^gbo9d z8?h)yoB?`rwa1jyRb7xP@7}!H1480e9>j58?J<*gwI`QqFWQ~vae+_}4ky*#zj^=``yi##`@2dmfM7w$wN~ z7x=kO{9*6kMa1J&m#fP!7fC_(d*6aZxwz8$KX9eeKQO@eMlv6tnhpJzkG;S`8$3Fd zh%J4qYBsQX$p{zu971&@TBos~ zdmYQUhvB7g8>l2|pky1b>W#%f5~k(%U>JH7%ef{Ie_^t67-}n9X={yNz7Mr?FP3!m z(6ASa&|yAEv1b9weHk^l1@jI_?<-@nyeLG)(J=&yi6qxIhJ%K3Iy2So=)x`x$LSAiTL`C|cOZE@)Vgsci&k9MqoI`Be%$LnI$+yaAEo^^3 ze)GiH_G9$GRC|A_nrgpNL=faF$0;D+r{-yPAFY^XH_tdK&u?%STNG%3-(A3SQLZn> zC9+H(e;WIf9kb&Sye9qf*;aZt+mcU*vjM8u&B;SZBqIf~Ew*lQweSt#9sE^?y)QfL z{g?8xEgtLV@-w!pmBI8=Cy4excCw_+x{_t%_)~JsE^wRL2540uDKZtK6)@y(1{7;P zfGIW@a1R5Na;MPE4FP%QA25Nx2{i0Y@b4W46l@Z7a{t8Y=VoBJMnm9hIg*!jl|*^n zlPVl`wa=zhP7jnv*{7%$Xyh8b2JYxLbWMVeuzS)FP-*%Qf2FlVAp`sLVSSiRbx-nv zWCxig6H2!4#iKdodOz2qxB$ByA&#_GuN%Tx!l3y?w_rTNx|Fm}jd4C+Ll51gU zVe?-m#vV3fzoL8`;rNy#U?&>@vz12F#d+X^|A`*;0IV(7LP;_Q5?pWCTT-ATIRVbI zXF%?-8vZ{ESoTS$ItV~Co0Bn|6mXKkiH4K!jwAV)lh--6&_%GBC-Ny zP|A%2tTI*)on5HGIw;;>8?ao>aK$?ye+j@b{GZ4xRIFs0m>Vs!s4^T`WS(Jz-xN9z zS}SxGGXzH7RQOIhoCjKSOQAMeVk&&QL(wS!<(FZN^j3%5adp9p+MuZremCtdAgBjT zg>Se)rGu+B@v;_?&zR*9T0FF9Q{n4QD7xf3@}Viw7y|t8f!Eru&j+rC=^3%A|K&g! zo3`SUK+0Crfc$^9-Iq&GiY&n;UhPh~0rAG8?CqF8lGO{9xXMfRb|ZEPt6PO%yXz*}JKgR! za@|Z}C>=QOTw^I?n!V>3UXs{BngAns6?7xpp_DID^}s^peSqO_f|FYhSZm(KWU)Z% z2V2dT=;rr=0;NzfxLap+Ubad#8fVU@2Oosn@)Hl~E$B_^*|f)t=sEc4BbKm7a>jib z_aS>$t~w8fo3P7cz~q9~w#Bps*~Jv=4U`YI2GdKg**TVx`bsL>Y~;92>fA1BUq9Oa zh1O0Nzt9@^U>7=jDzzUU%<8EgkPi>G6yVP~!JhScQ>rN8rxioo1zf_{MLhuappABi znM08SE?(;{b{FGF1~s2@dgzzC?cx*{?fV{D*?Au)88myWdr-hh7k-3Q;q;Fh@lp;N z5ddcD?`86CI_*uh`uTCvXn#6Xwi|n-*?HGQCOa+^vTMY34Rn67+hy&*itGFx<@99D zb7b=~>bk4*3uxap$?3Fpa&ihSn3SB7lD;LKD<_pcyr|C0)FASVst!7;3a}=RhVkP{ zAkWJo?p&wn1kqsXf79&AO?Q=p5RW#Lrlr$@oYa(-AM;YR%9iIlr*4rp^+-*+N(~<^ zRfY0JrAaDNya;*eF7e&*>D&D^_kYamR}}bsf-}!z;gtseVYOYJI@R2)zZ=V~UJkEd z3IkT)it;vFMSnKv}oo2_(wQ z)>hKmPTCFhX_j^e6=!MhpeOy>?Lu#oEDcjC?~t~tYL%a3?)yb(xvc)4>X~R|kzILqEb~nu-kOQ_J zuu{Q5Z~)*)e#b?OBoz}V2wiQ<*%1eTWE-|h+a<9eJHA@G&7x2g(I9ZTwUyhYfpzZ8 zZQ7i;5ihZP0x!X8?QIlZrM;^ke~ctVw@{TUhvEbDgJEcq;xCxoZ&Ku7;(HjTqkELI zpDMy9bYx|5O`?U+^M#tnTV{>W%#+kNc3RilPYa5Y>@AarYjl#j*|n~~Py6r3GV{V; z+GJG;6bw3wS$R$^DzI&49|4iZ%4C%?7l4Pn%ML7n+MN zQ*iEPJs0fwY_I>O>vid~)o<4Etv!h~?yf!Pl80XMYUqW%-frCz4O#xEBfz(eSw!Zo z@^^)jy&_L)PTFkoD?p>w6<*LU9tHgA?O${i!fKqtR^uBK->AAO)+o0qvZQaM>2jAq zTDb)ZfGm&vx#dbur{nkOyC$ke+N^h(=5DFQ=;O(jRT@^>H4Nbs_7RA04sX_XNwi`4 z@f1>UOLhAXch`oHl@8vmZ~boJrzEGbM_jZ)#Hdghz4AW&Jt@ukTk8CZY(T*pu#TE{ zkA4$*HtW}lL*2Ecq%1B6YPG(d3<0KDPxI-I&2A357==q}+8*PHsn670LU z85Qkzu#Uq1#oB^Yp7gTfDf;Wp8=2!S%Q#lwoRV zlme_9qf~QYvM5rlP!0r`@>wV&dIRC}w4z!bhN$^$>Im0}jTnMKpP9usN8=QK_&u`m zBuIt!DYeT;r_^3SGk;CJjSl~kx@zOc+Le^?bLx$>V@Jj`>hoLb6fy9nKqI2K4rmUw zaw$aK8?oGWDHd$Tz~^;%5|pOrUj=sMaY^q>G>$hUeTM1!&FN6kcs+yp=4e8q)MG#E zhB)J0o1YASLdymvZe=FbUDT~7-9=rLZu>)b6a92Sw=P++*^WLy8>YJ)wEjx9nl@d~ z1?czRbxY#|7lN}H!1FXxag#Ix&I&p3_azM$a-pw4BsGc9+&CF~0(WQG{YFT?YGfnDZ zkfwn_*RFski(OSK)hd&fUn&&MjvYb2!s~4v=|2C~+BRan1mqFD}kt}sq0D@2f)Z{v;vx+d~SHM@{ zBWaouM_=IiS+re@AIac%I`@Vq8K_^w6>i*yE0e2KLdofhUachy0*JN!z0y!%s=9v; zDmrlhPclvjIJxTn*-+QIT=H#DW^}rp=BNylX#uO6;OSieM6%W)s_)&iizuSt5$)5OZhM9u!1ai zd$*Zy%z9*uUy+xUB?c!vx^kXneEhrJwYA3}>J>8s{@dBKEbaf%_9k#q9O>V99}L$V zJ@)|&1EO+?h^WMP;vE$Qk0>h02&f2xpm-||Vor}JO2v2|F&=ou-C&aSO0v03;*m|V ziAmJ#=GY{fxVzch`hKf=x@SQ5{r&&%=Y1!!=;?X7y1KgRsi&Uf`*4lE>V1P5v9b!q zPc@BHUh>oe(*~2azQ?{nj6_jI`#D1ouo4o~)%b-@8&8W}sv)LSI#=R~empkaTkWn3U4H5IV zWaA}xu=rFT4snshM5q^>9dz9dxU`y9D)YT2SBRB1zE3;U$9MyNXDlzf(#LNBRJBS9 zcH)21KDywW(?@gNuNQit$5J`b3zVr;n2pZzd*O>wNX2>Iq|G)+;SN1ph)p9mqiJrJ zDo>gAVe#KER_j*g1#1T+mfX#_e}@2J##n84t8#1Ft)TIZ-8?vsR8K}Oqwn&yr^vv3 z?RpCT{TSDQ9KR47Lmc_qc7~kI1A}Uk@uukyrhff$Tm1x${)ZSF&U|fr+t!TOJOGPU zpfw=0kdM&pfCHM`B(idhb_dgncIIY@{{`0KJ7|snjP2|e;8;}y)M6;YINS(v`xgK$ z-hk0^2g4L9LDKAjd>1|r5ktRVqx(LBIiBTqB64Ucs=k>aP#>4OY+6TghAjC74(+AC zAl>j-6bN^U{RN44-1LMNg`8M&g12_Yq6*IyYO15hP^ZEPbQqBS7BPhQs4lWrg$B*h zY_lQVWNj+_o?AP64ul{rbGVS>>S&T1MD0))0!lFwX&K-p`jf28q-R(>oIwxO44LrZ_Lt4B-i=!yghF}2Q)vL!SrwYe-7H7aMqXOU~ zs}a_)6Fh5wbgDFY%Lqu1p4PJFcPTnW442s*R*HFBuwBH&RM^M*>uw7fl8ouOZ;>cv zD#Kf*FF``w?8@RY>ZAiDG%}+By+o|pf-NPgP~_S>$+`zR-F+dS(L*uU&Da8g3s)!% zHREr}O?y3RG3Z5c%JIv`f(CM1NpF{u9H*l(>|Oq4AEz+#X{s=-iesF|1@Ur z?I0C3kHW$ftwQDVS0TuWpIH*pl-8o*_$;8KjSD>O+~yp##T~C0{$^jZsOHzh*DUeU z+~$$32y#AaLom4+FDc6rt<>Oa0=CxqzggnQC!bn%0nWf!5I?yY@8cfSojgJ91h3+K zDb2$m@3_<*)1{9ss@XShlQD)EXW4p?Mb|Ae$&t@2yIJ={a6LIVrl!HKVH!UJDsG|u>hymYQri#; z#k)H)!dBIS&`yTkwjy+Rvp%HlB}KboaL#Z!6z5!4cgZ(~PIkEm)JFKMyQ$%u#D9bi z&HdW2jBNhKFr&r&S3?#*lnw?BEIpWDEkXpJi^D9gI3O@D+D`W@js)mKc)oDgG<15r zK9jEx-Bl6Cb&q%WH%BCIzu^I07Im|y?}r;w+tN5hKO3r_lgNO*b*rrU*L5yG20BIW51*eSgX zV55f-;GB&J2^z$A0+0oh`ECf^yNsEDaH*_BGV0fmG!p$Ql8JQw1$PsEMR9=^mwus1 zH|Wt$dQ|jFNFpWa3ippp5ApmOVlxc|ew>T~#E0_?=7F9jH-1J=#}|LbmE`A;_GIzT z$f;cTb4U#7_H#%IiTN3|{qz%lxcXBFP1NQAQo3sG7+Ez9$*^?Qx@s`w5C^Op9)Py0 zKaYSRXm;s5U8pXUEXC#I!b6UDvMUKyYLi1A8AH3n%8jPsH@jdY91L0E@92aIp(DI? zb|8MS7`XgK?h7DLZ$n7PX#5)m-~9g)IFgj8=}xlG3Jx<&G~U^1*)zP;V(!G;VLkAD zjRu)!=4$k0?OaWJSX(pQ1n2Bp>e-9ng0Q#3-Xi_xYOr~ptBE4tj|~ZnU~87a^IqZu4BSTms)NvqK$5<`t9njEXvWQGpXOvTDf zyww_LJ*zdTNH5$yT{%%R2W?{S@%9{ziyWJS_T$C5NbExn1AUnpWY@1Do&B5pe%}1e6TXtF-S3@TMs{EUD6% zL-2iwcd7mqdBZI+#Jk-R-I^bA{Fp=VeP~NKZn4Ek>Q0&ON-Q$v5F8+~Tq>{4tFhV1 zq-_>Y%7D_jWu?eRh6btY6CQ$c(kX}FTyl?#6lMl8nQ-?P6h$HwNQP-b9Y(9f{s77vC84TDD+C(z<2t>_EM}R&z2!*FFGpm+WluQS1 zfZNJMG<=h@JB2<)zBwG>se6)1UG(%A@3d)U^SIq@PwZkM4y70YOL2K^g*D}_GqS@J zr5S`wJV3eAd_^4(<*1bAz~Q05;X!t2Vv*nn0;l(r?86Z@-M+w?r%4>n)a{XPN?fseu_=~3Nty*g!^g@Y>pJL2TpVVaJ3+N0iJ$lSxuFvGwV;_q%0@} zRdK0jF}d_>m?ed^1;}ym3ZQxBXq-@`>vwiv^(=go7n;_P#$UtY%V&B^sut+3v5Mh- zSQ>sZaLAB{Ca|;5F=Hoq>onjw{78|5<4Rh7SFz?yY^4jU8amVF$$qD@?$T-I9YG8wH-e784LbfN==kfq#O4!i z&y2P_iy3F0(8>!>W=@?r@o~5;Au}%&`&rN?P5^N6U7sl@u=u(I`U(~a^yV{g;rZz^ zmm>DCtFZWo7My^<0czPl4N4puHw5am)+PszZ#lfzzEdE#w%Thu>-o*#l^#wQ2&2y@ z(9U}JuMw6vShxYJ<7Td?8Rm{GPdu|nK|gW)s?|-}e_%-p=7ea0FtHi-jtq~Z72$>V zEpcrL3!8g-xXd;+&U@dYXsMM>2%p$|AAKCZtp-}1!4RbE?^}`;Jq@MAbMwMZE{{w1 zIQ%J=yzjwLE$TfqcJYfb4hzIG?!jhcYl?TN+QM6>5R1F)153L$jSHF7oJDoR@roXg zG5*)yvm~^=CvKg?b#VJxxok)}^8yl5elx?OWA_~24CRSR!7NJHw7n4HVkE6@46Z+^ z8R`-!#uQEN@uL!#iS%$bhr0a4jh8x-{o^HvQr(&Hl1(bz6TzqyMGvU@wjx-zC!7%| zTd{rPq`?ZoH{+y^(&Rm1bgRTETSCRup(V4&N%6{B=NH3y@{b3l$H?jjr2>+U!a(~% z2;gwU2><`s_AFv2GZn2N8kjI zhroys_`4iHAjDW;oc{t});$OT8o|fG#_%f8N-9CjajBZDL_nP}ZcA3I77!wSR4S8? z&W?x(Q?e7h#l1x?jfhBBe=(7~qf!*1G-S(&2yM{Usu2;Lv_lXZ36~Ts&5i0cVFtKB zVAbMZ;a|znbni}lM}cl}Z8*Sdw-1j<6q6v|Rlg)43C-{b3BGmRQ%T+$Bw7osvn3*mp#VW%NdybjNQQReJ=QkWA9o8{p^slI{_cr9NYy$cPm!Dk>eJGz5e4FHKWS znmYa@$Db4{A&ia0Zel5rAPSmKwZj=L|r4g1hYU? zqvuaRXPd`~3%ERCHGfC!fCcw8ZYWpm%WrnY!Gk=b7*HTZv!t+gLu+fH0i0Fl8>cP? zbJxRf8|qo*7MDkcs|s~pPIywNZhbB6qOx)K+aZn!vU;Dpg6Q_Sr-X=M+(>dZCwy2- z#i;Ob7B(EK)`e&Ee{6a#8(E`AucsS|XjNl;>o@prT+IoO^E*qhenH2Ot~ue4S?CN1 z<)bii;&zEoLEYoVwBmQ`2QRzZuH!|3`Bl2a!--ukDtrxaoNPb2m13nO|gkNE){0!bHf8xsHH$cOZ zYO$r3AH)u=mm`6#uAHy?h6-3yEV3dA7R!mRg{Q!0h<}Fb;DJZdV>;WWB1uDB z^Me*!_fdypJapi~Qkv%RJMF8l*pk5wq=~_~!b46Nw>;`T@OU|VLvD|>B#@;!7M&+( z?9xv084tlqtyX6t1tTr$l6d@Co12^&X^D}F4#CQsY*Q=ED?$*$^P?>7Q-kZ{Imqvw z;^u(27sJvk6di)c$33oclFp+oI=^EB8+7RO)|b);2|NWcePc%c9pxb?<865)$70|| zQZ0ys8_A1@5cxVD&VUifeD(seK+hEVAmiRmc=B(-(l(lpgW3KaU{%fs#@%~>f@mig z;oeE%-A^Mt`UxbSo7S`jOWdDV3#nwwYJvK1D{IW`)qC z{ACCz&+%K4_fpRIHWW%m7o4R3fzkCWa_Bw6Rf{)MH5q9F^VbAGEJfg`h|7d;D9y)X z1(FUt+ST)8*k0ZGB-=o$XLG75%dMLMNG-*X>x+=dj)hTP-DtK6)~CqvMUuOYhSraz znDrG4=mxu@)bUSdR6-pH?1B~pZlmFUXWqNYsWBAsyvCZ!9Efp}I{41j%5kRZ*JW%! zUR5zYZW4kl%Sv_6wLS4iYUUa|fszcQn3Z@kngSJZ!p12~r9yu})!JLFzI`t@uXH-l z*e4)=c4Jxu(U2Mlq~JH%l%Rc+;6JA01_rLug5NB8*dtJnKseYi7Z_xxu&PE zjXgc*U@+1X*da1JP=yLT+n04_8FiW3e{rchS=JU+0S19U60uOU zt8p-z-Va}3BOHxxAQj7NaCdJ68f6t=IkJ$+&;aZG7u=f|-A{2ou8aLppotf$hLv1F)sigsR%yf(_NAnQN4-acX|)-lP`0@fbxBp# z3h8~dDdcQlt*Tb2?yI#+vo@zPDrE-`ssYNyv*GXjLOHj zOqYvk=`ft=XZ%KZz(&Kte4KoM(|;#(>&yvK`F^JKUf!VeZVo7(E8joCgcS-aGn&J-7?mYTPac?-;|{U)-By!a^Q<%5XA zj)(d72se@H9{NjTPrxdl;83@x)#vD>-Vsu1v@@owQSLbi=!`IeC%1RSoD26QoES{KugRrZF&6S$ABRMecE^~> ztXU2{*|{sGFk;>bY)lg!*v3!&x7|es?Ti`E((QDDkcwsYQ}Hdt`tQd=+kkN5BB(p= z19qPgVK$#bn0y}SeVYKiGh4_v2sY zKZ4wPOydO55dO3$Z$1X&?e~u%G6hE+fpPl8V@Q3A!baBNh_53fK}}*%ScB>uI1>;7 zP}F@!{{1LSv;TS&me{MbIR7Z>Tkwb`wp}9czrP$0G~6V%Ir9Lidla|Hdla{sLjO1j z|ER`-4KMvedeiEXXkkTR(Nh^nsd3u0s(IWM^2Q^Y1oHYLh{k!27JE_Dy?+-Si`i^- z%KFl-jT0$}aq0R2q?Lc^Pg zc$^2)zTyW8Xc9GrXK4CB`Wfpb&#Z&)annSNNgNP0fK;s$V#(8!HImpXsux-DvJe|S z6zKo1FI-=cOZ2zZX9W|v@TDPxeoZGk)(KtdMO{ecOZc^Dogk5^yf&6}LbXjeXj&&2 z*l&JwJd%IUTO1t{9inPFcdP~FS|Oe+St~?Rt!5PYZjBH|My?goBN6Zktt}+IPbi6D zG(!jlsQAZSG~F|)-qcMdp3&;b{%iJ!#GKJO_^-&Z(^@O= zc4&jDr1G@ZK_;N!2NTn2)QQ4r{f%y9{I?&5NW_YgkTK-) zDJ?cKr+^-R8ii$4(D)omG0vmwN$n|Z0-1LTlE5@tJ(nc(LZUU(pU-< zfBi$ScdSBwN>fL=6;MtF;5%lKe>|>n>-NIphlw+p+smIP#=k^tF#0U}VR&=+LwT?= zeP=f-CWppz!}^i!cC!v(@{KX(^`zQiUKipU@(i+KX5xvv*v&`DQJZ->x!-24#m@P2 zc%;ta5L0m!dfrvoH%}Iah+V`em=SLJ6X$IZmSDG>hfMRyf?eRDS@|n}4w+FK`K18( zn~21D-SFyl+)s!&x(Kz{J^+<2gY)H$8jB6OF-4@h;9%4 z&!1aUS^;0RxpN&$?s=A_)oD$Oz0=;1@I>2yAnxX`29nla`{@!b{eoUuZW*?x!a}mM zA0ml&^wXJ<2Qsdo&d#r5e@IC`IO64?!1%o0TW4iil9W5b3t%oy*Q2FEb=#9HDV+bL ze_nnP^w`Q&4Z3txRe9NB>>r};-0S3Rb`nA>+=RCF)kU(bd;a=!%I3}mN}so85g_|t z=#A9W%LHv0J+hM#ebM+7a;p!HQ2=^|9({y@Ury%q(OD7OM*on_^v4ETRMGhepE)`o zSJ6MwlfW3l>CJ+k!2jYtmYHoo4p2Bd;NUR`d#Hav`~QSciruEjf50DyG|iNLi~#3 zM{r*O5n?cydW~R5r!`?WHIs@m2%X$rv^&N#VcTNJQjoj(&*2%keilLpzaI>Y3*(1| z2=c{;ux~4VhX!);L&I39Xg8F)-CgnVRKx{`Kp2FLkV}TUtgkb7LyrqWMN0ENjVPT{ zmyrg>aoJ$=Td(~R7?oiWX0KLDe3uMEA|QLQmhz;>6~mh?xfcxyd<7jLov72`4FF!e z1~ge2yRBTzhbvH5=;Xo>mj5Ymxldw=-T+;N41t^sunWpxK7bI_7C`hz?i%+xgs3OE z72Hg7|1?c{rXWxS1Jw1R1=(E--Y}$-DQ_SH>mU?>Xukcr!9fc<`5j06`|KFN(CpM> z^weef)Ft`US7G6fu@{242n|QC@YX~m-Q!$h(2N~h3zh-}U^HSPRkom><>BeA<~#M z(PB9*HirQ2_~3bio{XYjd(a}57NNAb`BxP0)8aHO_MzZ+%GK>47tdo{T{w>+wUv0! z8?5{$_J=%n9??Rzv?!v*2wL=@MLY`Y+MrIDR0?d2dEv{+Rv%7%Yt!5T5V zMZl&8h(|dEqp)41YPLzGWhItRz%-C`fGVqyqs3@Trq4DB`oxM7FTB@)%;)Sthof?e zLi5E~nM&%`3a4#A^cAWLp5&eBEsxp7YW2>T>2}izI>`$+GUy*=xEY6@N>!7*iSWw9 z$(%A^++x2I)0O zJjeO9vyq>9c3FkqL>|M>r22}lk!6U?XGEjtRHXs5Jgf&B2CYtYCucu0S!KBZdfA*Zq{O6{ zgu|c)H-(b*ADNt~3{?)#W}8H@E%K2hm3Gn~mhC|raFGH!vXjz)3uM+uCbyY2Zzf#% z0B}enS|TG!e^gXPyC5IXa#aiBa$%ZSv;a;WKowztkNKrQ1chIsK=q*c-o@3mGb`*5 zvnya5k#)!*LAtln63r}`2_a)!jyEoUrZ;ZF%&M>m)=pSVY?H~Q4^5VWNbxN=K_jW( zb_k_?;0ykta0sA`&#hexkNBi4?U)Ce;vj?n42)gL6Fg7>5LecSAVpKo$yGcsf(*0VMa4q%&Hb zz#%gYkIN~kIh$>uKLGR-0s@52nx3iZBU$>;u5)mGI0zLB#L-CGz(ce+0h_=yAOuUW zbiD|xXer+l^Z0KF-+UB{dLID4H^G9ME0A@YLZibm7Z-$8gjEo}37vA^rce|4eq(4C z_O#?s4S;qBx(1SM8$*-HoQUtfzyf~kcRkV@{ib)4$A8!BNyhJbS2$*4F;FSi(r@wdL&W`# z>3QupeG+8I44_-kOW*lTZ>E=apg%ZC%9jQst4R-JYoz#t79DDy=jF=ZA)%~tCpk<) zBWT4=vYH;%9Rk8+AqlmIBxo|+a>e(PP#wuVXm?73O6Mc_bPhO-SKCh8j>J>yzc+xU?!M5$mq!dnykq4SUy zfutBkjOF?SzXDT{|5(%`U$T7yFaum}MI(-QT|1dxuFv!<_7rN~yZu2*=uimZuAu1i zRhp9RW10F@p<&LNrwa9o^SMe$VyEZ}$+@Zee#j`PFC+RwJ#ujr=(k4c;o%boa2xI~ z{BEv7e3I{r73dYHc?zhOb8rlQ5ZEK`1SSb{rF+n(beCTK3Z?E=7@*^JNs;9IAt_qX z>}EH)T}FP!o^jM;@E)|U?v&gLEwk2p_n-$81J&NzFIk!nN$nyPoi2O_OjwenX?w;) zUv9fcoilbyPNhzIe~CW&Dfp)-ZUo17psDvAlsYgSuS#;3OKVNC`Jj}lTGAo2XP4}O zqmx<>+;8@yqMiq(_QAI^^0W59w@R%GiuH5^B|mjgQuXh+WfUAS@%GbNb&8wJJS4>g zS4QrfK#HIq9Q30-_>1BOzEBM1o+HOc+vB8V&mu0NLp0}q;|xUN>k7LX7aud*o+!0{ zmf}S?RA+)}B3jAx*>=_OVe4%BFsbUkP1gjp-3~2LC zrM;V?i}nvQ>y&598KLToM-e%vR@oIe7rYXDcrK#y*;&v5d?;Y&rYq=4Cw(U*9Dm!VCvjidEFDVQUFx4{$?5Tttup7y!1NJVI-8;2o zOJPo~ni2U!fdaxaPn!j=0BO@`BV9E0D(cvOLq>a0{h`Nr# zN0EzXG=zaBRDNnrmXQ_YK}O4Gxl|<-Qzlw*)f`HqsBu&Y#{?A}xkwPfaTAW@QrAa+ zwQyEF4~;_Ar&iTFUooYOKQbD|Dy3?M&4BR6zneo^*Np+MRzLp8sQ-RRP{_F481E4T zqPFgY`^lQCR-J+|BDb0oCm$I@tBsE*d1ZPe8~VihBzgQ}>;68n6agncnpJWY)%*ja z=v{yw%}3(d1mwwh1&)7p{3HOOxd4806)LFJ0O9H>u$(zNH#r@UY@DIwt&PsfBXdAdjQBzkr$n>wafCY+R)55OT@lC|w>~tz)|* zf0Bpi7Y7l4vHc)s1eFWOx`P!97%m)g_AxxSoO1kc)T*!oUGv)AK9 zvdhKzQUKlyChY0NfA;Jo8GrVyBO71wY)jD#{czJia0q)_B0dAx&_9U%u`OK5-{J2F|AErQ z9dDD@Oxb7aoJAkB4uyiGTU(MMi{31iY(un|dad7!3%{s1#B8YzE!YNIt2?l&uq7(Y zq7PnWT}DmeHn>^FM@Op`>oLd#I>D?Dvi_qdFvyFxu|-BDWcsfkP5Lgu6O0mqd=QtQ ztjA>69{}vNya^jhI;0D>!LY0T$QDiuS=Qu^Rn|JT_D|XdgD&8#6p@0t-*s$q2TK!C z=m^9Pw(SVoi%MOzBaoWsakDWclncnhmvQH2Y1PORa-dv!Qu8Pdd#GOI2%$)zM2rhlUPS>op7j zihntDo;4+*cS7%w^%Y@5u}R8GC2Vrts0y>dww0AGe?3(NP2}y3&S=BfvI^kBB5bXk z%5VO2Gt1^cmjl#pXecVk=uOTJWaK7iE?Kb=NAxmsZId&Eytv6Zg|1^A$@iO_&N_c< z-{jwYj zP1tcghTK`p;eA!ZSMbwSuX@tE&~usedyPLwX1&V47cyvNl80m$dhD2@{NXhEKw;bv z0DZyeJcNIq?}Kd+MPCU16qJF9T5MUw=LL+`&JR3AE$uIQ`UzylyPnPD^UI$4F*FZ= zlN-gsoV^rD=sJp=a0TG7k0W1kAE?=GA!XAp45~3my&H~Q;b}ycFXl#x*Zfu=5uur% zVAVe^oBOC2B)R0aT4h}RtIn%rYOJ*#EnNCq>|ZLK8P1IMnhb#7yREhWDu2E+UpZ^1 zsQg;;w%giK-Z)W86^wtQb0hJ&tw}O^HvNgb^-OqVxbrjTXG#q=GRke$VcVIJDmP{^ zZ#RnXI^U)3a5lNEk)#V{)G54O3OlVot+pB|$V_Cg$J#-?F%;^tR$XYSrXP|{lbe@p zF3V^{PmZGwp3cqA%``9?KU`V_9=;>is?h_;0}gf9sO325yq;A5-H?RQ-z$;4U5SK0 z{i~4p_l-(SF1AN!^YFP!a5lU?ROTiQ5W$&MHI;QQg^--ISO>Xt*%M7Z z`lDzg>F;_vlPi}!k;HPrb0f@G_L2aX8{#?2yUFl(Ja3X6Z+jjQ!(Zaa^%!I(PI=oi z&q`Yp3MR?FENlRbn3Ip=2GNaG7o%_DnRbxU12Ikamq)7(=5^)KKBLcbCLUsPASKzv znbE3jx@%_iU}?k|;8wb#ZAyg1PH(gtA@PwndW9sMiKX0?QwZX`(W>+BIB#@sl3W!1 zRkEI6ibh6p;&=r0@X%yL3H@N5T*`5anz4yX3v5CecmC6th|8Y#rKL3^pV^GPD4elc zG4hHpEYak*FD$B)7328}n<0&W)W3<5U9LfTm$UQBTrXD#S;8ay3o&+5wbq@u`#N=nq(Z0%%7g}kS1c3oA~Y-l`Y zltOqpL8_m!C6Sz`Z0#wPD`HS-dAZkq!p?q(BJQVb2D#qvH`^>^)RVR}^8RL96ltPg zal=kndomMgBkW}JaI;=qVqZdTKWR&*KgMgRYNQP5TMpO{P*&n3+qa-XcJ!^F(S{9i z4hiswnblE7akz6h;}2x%7F#4ciX2r|TwYt_Om-%-?{)s1B#WJk^}-3v#hV;oF0SWp zitPmvny9%*6TA+tGNwgaBHNcvr@|YAG<^J*a(wYY%ynEM z19!>be(aJ@qAgL%R$smkXDK|0*$(0i$~~d<^4H&1LNtPYC}&du_~hMHjmy$Ons5+o zSp5OvPZCUd^IR4s(S_Qq2?wEnX-$a4A+9#D(0HB)4?+WjCdIdIQdFl=ix$JP{(-p_ zrT2L1F$bZ0!c|HHwf{k)l5&8nUsZmOEAkIQhl4BHbZr!QKgwci(@!A<2f?2}tT5o< z_h9v~7ofg@P;mu1%T@Y0aiF?YJB~5v{jFBpP z2Gb;Hzvf&v_EJcXzhqnrs+o*Ri4M+w#^@$@oS2PVW2yWU zq|kc?_D46u3zwWjFm!6PvOyyscZ(Si-=k|*SGL8#z=nac;vAffp*mw;lx*6!tl96G zCsGx;27$SN?|nl^<41FqbbXy-^cCzy=xL@)-Nj^_f=2FGxbZ%}AJljxhY7qO@5 zE}POD)jhFzuX|gHAmx!jOga`3=oeo(!j6vJA6{iL`<#1w(0Q${z1MF`Zc-6xR3V8$ zjH};~k|g`y?u=ASQ50Gs5V>$VBspbeAbKz^yitF_M(W)U!ez3-oEk9d>m*i+kI079X=vytx z3VmOtiFB!y3`d~l>mJxfuD@yRPLgg|RsHL^@AwW;8a0)VPkRK~K3t%Tj#=MYRWXLr zlD~dy)k(S|5W_*GJUOfOqa}JPLjUA>LMU;|cQ>pq{(f1m+Q0#k`ZMsxXLt*@fxG{n zA-HM)?l^*Naw^Ggh?&6GwsbfZc|{5WMh#nxUE-JhvFz zthj+yrL{E`ayi!@_%t||{uY-OH>oUfoOdQw9`zpV=jhyEK-bS4HvMpKobJq^C8=h<0`R-`?H-3}a6< zAU+phW(p)bz3m{HN~UVg%qnClP}5wty|*$8l-|fa)d0_LV1)SxUE3E%<8qV{)@Fe5 z+=2y4HNMzW4FiF2>+cBVJuwxgue+Zr8?j&0s!F^JUU6>QmIYN;$I%RT-m)49uw@mU z;zrgMBe5q!&Bh{(s1tB@5Rz9?N;ihJGyzAaIOK3$M0ML$C7t3}y%iV>HNnSmsTp*# zhrtm}d<^mOrSNc?%l*jJ(8=zPBlk0TWCggtSkkkAa;F+l9=RTBFIblt`+?xJbX0hZ z(Z_Gl;H<~phdwa`n7oqk402|)7)FW~gxeH`=i3+Cjx@{&UrMwy!WWSZ(^0smhu4zX zrQyfOW5wZ1v|I;H*bnINZ@GurdM!=ey@+l&)F}I1eWXEc!~)B--O!DJMqzfK=|!#? zjjf>nFx-Ta-B6E#P+5N&Aq_BTBRh!odAsK$YC1YWS!5W5!i?ThD+mQ+{kYwTna^s2 zv~anvq}qlkAVX8{@X*LPoH$K*O-O;qym7zLD^1wT(|{M7(iCMqjUbipUDIGwEj9Bz`= zJ~xDulPwlgi1?HE6Y;zWl0QxrEn;`gVDiN0@TLSs484@9vj!t;iF(yP-msO2WNHQ{ z2b~-LhRrN?!lmmAktdy1KL1Tyb)dF6=MnyHJCA+-?bmIYv`8R}&fAPsW#E!%45lA# zEOcP#K&q8UmvszGA@Rz2TW_idaP^TL^^sW`Ig@OIY=bDX4d*&?@G#_rdLf+O0F~xO zoM`na-v~gYc<4=5M!_rteOJqKH4(#kGCVDIK5?hVE+%KwVt*!G$|6=Z?bn5v!?|44 z2$z{XaG0A99m*_n{CMpBQZDHT#lB0$74k;I8*>{cEVrh+I5zj8++f0A*mbaSF?!WLk|cgmj>>mHJHL`ynQi?EFv6 zh%g^V+T$cSwh{K9btR5)^3)G8S`z<5%tzvK(hk{IVw~iO5=R)Rm={?@X3URl=s~+o z%O%P&oVSIY0GqvmG1LS8MLwKXJ`+x0gN>Lj#p=ysy6kV*TS1C}>4%Ixfz5T>$g)>o zx3`Tf6Q-PiA`OJu{z=Jd{P1OaY@79lpL8OR5h|-4BdmYf9@Bl?4FFjQxak=HLnsE z?w?5JB*t2a=WmgrWXE)~j-*dF|CKDAVSYrX!RA{mMB>C)z85i0G>(*}>`jJJ+ofhz z4XpB0f05!^#kTra`Kf!8s9c~r!LwDq?jLXpD)Kj@^q{9n>CqssB+@LtN$E^N&&o$A{1y z%;)&cVgWZF2|jv2jQbBjVTq|3VRvcmrRXsJFOaF+3FO=bm?O@-qSKJsujnGAqHW+t zi2-4Yxx^&Arpsu%b_r1|^{ZbAK{GtKNcO9`G`e=lysc;(-3>TYH3iFN(C1ZM1~sCp zRKVL?zRlwyw|+<3t@N|H86nt%7LeFib)SV{3>L6J&5zK#7h_yH((yIj6)FvA_-6o{ z17x#Az#3%n<6ys^1wfAV@~8z4-TG48J6fJeRHsr9SV)OMYfi!bmVcY9%QUBx3VZAT z@_44XmPBQm$ApcBCvatAf41rDFa8h)MULR-p$K!s!RV zG=j2cz|qBD?b0)5b?H#3OAmm7WW=k|7o&drB-l~yWs9*L*r#8a;=h24C^&#s30Jgg zHm*>RAr->Vf&*BU?m-wuK6+n$K9xG}02UH}KdRMISj;b+5IbPR%8Lo)tkE()7< z04rHWJh`+U!B%k@m}gtATXf{&Nwbq|ecqf%`kpkG^oHx9{#_7X97+CEXh+C|&L=)CXu#7VA0Kn4XT0=q(^@xZ9bS9kPo)F6sq8JZ9s*f@3HwtqA|; zypf;HkKz;YRz8L%aUT?vqXyRgm$80{y~!5}xl-UhHf(ZGt z0U#opTMdBK3f<6vO=0My1}vtU4;!$yYA&r@4w~?li%`SKmGd~Rjz6}t5*3|YIUS@M zS58H_a^+-@zQ6K8-15N6Jdl35awHlTy>cjyn^tCHyVz@GFZ}w+N+{Fdo|29;-j!%p z*gGp}4^^y0<3j6JqH&=;R-##&f3Ku{ld}?*Md8d!OvaGQ_2`?>y2bUhE#>v|QTD2@ z!4D<%vqAKidUTQ4P+y9Rht_*h_Nhldam(uSaa>$K4&}}I9F%M7hoS6J4~!(ud-Z)# z_N>oBJe}H;iZ2FVM)(}4y4hy|QJD_| ziYxP>)56aCFrdPo^r3NKPvG^1?OuptBia+T^!FO`lB*kYQ?`cA=P5loH#^eOI6G--qTJ3$IY5c@1k1Bx zp^v}K;oAJNpsIhPp+NbAsp)+Aeu*FbN5eSJpTu-oET?Djz{8xXRvw3E--W8SHc8Jsp(oD}$H()0d`R!8$11hHojmiI^2}>@zuJ%{5aG zvh+)nn|%9)X#!dIg$Y>6!tZclXyD*h)*v*JE>7F~6j*ep(WgBK#d1%VP0=45pNMod zv$`W`jL_ZUQhGDGyCqFpb`bhykSci93aN@2M5)O5ZkAb?;M^vq+L;HJP%EJSGUDrP z>BDxDr+Zu6X&_v!5JF`Ros9fJ-;LMv<*hD-^h_mK7pcHs;%doVW=H3j_K6 zhyW+1-k}4HKEs~Q7^yCsqGlT0ihXpf65$E!R!J(d)0tJ$ z49T&l6UK&1Nf}5kxv+z(}$$a${lqNOXH-3 zJt>sRp-`>=H_|?=d|2wFP#t|(%9Cd9Nv38b)pKgd(f}Ix;-yl%rkzr#Ih}*5xxH{& z7y~~;Ew`2bywTXjA#=MQZ}eB=Y$b zx9Pu;o9-t6{V}_08VS@q^8~Oa(FVmKg4KLvRjmG=HIs3V*k_ZCkJ~HAQxC^ZCn*od z&LO8CimmYb%E6vJ9>KKX++aSJdx~1KGo&%i(88| zZh0=!*R8n&`rQ_tO>Q;A`)c;<7KBIautbsrXD!7olh0Xx;$;+HZV@NW5?(`G!8mRa z4-{WZcRJZJjK0hRM&=cu=n$u_GY?eW+Kn~l0+ZgSKVYDW26eAxe%L%nA$eo9xd*Q$ ze_Cs9Bx@cv&m~hIGVdjCt}<_OFkZuV<`9!I64|Yvg!%d!1T9j1F|wTw&x|a?@}`OS zc%=Pl@Ir6DW12cb}-O1meuYKNc$2LFQ)6CSTo*{QNL z1zn0Q34t0JDeg}_Q0^vlkQi+6A5dE>Q`6V1<+30bih%TEd7r=G*Yn*FbNe_>xB2*V zO+%nIaYg4nlT3d5)Rfth^p5GTd`quaOfT|H^9&&!LSbkW7hu4YA+RV6U+TH;qR+b= zjyJv{R!&_W*LdqG`-wSE?&MG0c*??u`-H`??^s-U?lb+lC);OipgcGY3I8uaOWc>DNzDLYjU2o@qt;hai6z?N_qOH9&zD`=6Vj?%LSycVRZVZ{ zL%SkIxlZ_5SOk=*90V*=fVBcHj&{!^Ken>3YQq>*;&&p01=o8pJiev+rSNrpOUlV` zr(lww3L@rIfG8e^w*fIdVH^RWjq@!!5Q`r2c$9g(v(~Lx-6Ve<+W#lgBxII`UA+B?f z=6C{OD!v2Bn-LX7-ptbWNSeACqG=}1(FGg?{*ObSw;7z=9hhMZBQCPaZD%tqpxa~< z2SPSf3ZRx(6yh7|u#yQ?ZU-r_LL+$fK5ImbkK2r8M5VDPw?ZH1liVtItV*kTiCwC4 zr?;HH726Y8fcXbGp&7a8LSLa=`4MCNn0@!dr>l+i`k@C*s#CL^P9S$*PnvbWpOe6! zPT>9FCN)gbZ{!ZKgmb+)XhAvyggT!)%k>uLAYIi@LIL627t&(IroQd_%qJm{EOSSe^)`90!twW{!!{D^3E>5xbQzt<3R-(04;0^jT zWd30=*-W?WssN`1)15F2$xpPZvd1Hd)^<|yVQ^SHow6Fzfa9h_YjQ$s4#eV(#lpkj zvLIHto1fT8PIa{E0?AGp&tg|-T0T#6z(6|kqkBw??g#g2ezcz7h3yAM>TP71 z{u{Rk0r$h;vppJY>{&4oona5anntTD=vE zU)*5Rry{Ft{x-Nus6Saq{5vr=veBkb4qmkA&GNUwMII1ysuLFCf{qTx}CtN(8=@`M6N1D~SV8}7| zkh1r82Nr9<88C0Cd7#;U2TTF_q4_?^xxFx8ogQi)K#E40*OK!&=B9{{{aM&zMeEau zcL0)@PtP&KDm=(Mj8rU-jv)L{bAKIeoCy3h#OWU*#;uy!>vKbl^(lv!!9*1uaJTWJ zp2m@N-@rrs;#O0LGGS$y)WpL}>5Ai01b4uss(CaS+-k?eOBjJNr9se>+*yPm82MR9 z#u?pvX$c&3)Wi8lxRYE0w5YrJQNX9#jh9M4KGOzxX+UmPZsNNdt87>(5FM{;Ie9F6 znCO3|9h|V2-%R=^A&DZG;R2&?{t+{}GB6L%J!w^Q^yTib7L(G=)@&*4h>0$M>S+7p zW~;gY@=sY0N)wMj(#7^%*%-X=lvT}Fk-goTON!Fr^`5iE`g~{#CmiJS$@-_FVgV() zdm8Oj)o&JAQrzTJJY05eKOZppAz#XSQqFEKBUN07iflmJT+>ua=@#+u|zp*wW@%fu+2 zZ+t6hRpYtjb%y8=ru1O_hKdSP`U_dz8h51Rgic}#4{~mGL^Ko~y$lPOLW5%r8L&6-X{1uVGab)MSic8z)LvNXaGCPruYV@pPmc7um#39;uY-}Q=GV_8 zbvML}uF-oTQUo=D)%Eu8fpMU?EGG}?%L$)h$CHFm;=T~o{>V?kD?7|h`Jd2~YO&J= zJ7@Y8bYh<_y~&CjVn`U}8vT3R*I3uZ=`^Wc$JG`_&2%Mn@v;{N zemT}G2Ne;PLl9GCmWZh#U<65F9e?4nVO1eoM)I4J!S_%2@n zP4w=RLGgQ$4Dv}J!6`X|<_Z-s0u&;f0@Of||NBrosFn2pOs{F|xIU`!%myH8z7ifw zCSP^vPBd&-%8S1AS}JxDj z;NrjGUxKNilJA3%=N|wuL%6w!db~1f{K%1=A|u*O2aZt1qIMDE22UJEzq9a+wLNNkpv`OlY3fL3|I-vMH!ZuiWM=K` zX%$|Vvs6yGiFr^Y>sZ0w6^RFJci`h361vG32#?+Dr~; zuidkNss>bA3J61vy%yx8ig0i8_N&sUrqzbfhyk4NC_f$UnZ)#pkZG)sJAyqQGR-R7 zYR67%EVJIpS_b_4)x&eSbJWWjJEJEF~O?!K{bSfJuq!BQE=jXBkTp^@0iAKp5E zB5yKOq{@;-IaP4s{vYefIn^)^8@5*USo)4BosU$hwKe1Lul64P->us+?o>k!USF%{ zvJ3|BVR3oIBA}lko9TSmwii^C*8ES81vmd{@Nq|Q7g>7cdKcF&t{qCj@&2a@MxSb^ zLLYOjD(Ih6TRRUy5o)fDHnm_yY5hd-+OLFSymc*zb7Zv)1E?GlNyu4j{->JqPBmZ} z0KmuZwNFPC{ZL(n|1%CSZr*tm-mS8Bn73w5X_>c8t&r>Cz+dO5f1tQ@#;FEO7@Lq76;+yg%eb5DRR!fIobYibkzzOO6 zF#M_D2XHTQeWs93OHFY-5XDknQRWkf1bd&`uRnu_mi)=mb8bB!&mmg{^lRxBSzN__ zYyEJel|1=`DNDH>@;StiYa2~fQt`go(4AP+g@BPRTW?YW1OlX``zk1@Dt|K4!VQ7c zoC;|r)iHe))B>{WQ7rGY0nBiu(lxa=V$DU!AG{5(3+wr>5nqn4#G9hC8GXk6(4Zvy z^I(`vByET}Jz>cv2mXgJZj<#myreum2DQfnk(z5s_nI#WWKEHIH-mbJz~%~whrQt` zu^cXqr}=5XY1@s2izS@+EF6M*Dr#xMBSQ-btFd)$6-|zZc_@g8Zn!1yQK%8r3lS(% zV^eV0*hs@3o6kRrt$&u{rEekd;j@$Ixwe@9U5fGiqfpM?f;xTvnQ5BL_^ z3=A_cjbRuD#D=JV1+W7au%I9)igkcdP?{8tngqv)rfAem^h6U)j2buDSkP6B220v* zVv45s#Pr^Gv%A?%zW+J5%naaW-{1H9e((E@K6i$h=RWuJ^PHy^*+Ph+&TJ=No{iQd zLOkfV5@KD%UD&g(b(fzqfIb6)nxoj2(w(wGgEfqaoUem7d*?(`ml9EI>^(hTr?qw| z1fA8P+*T?%{zbS|$VP&uSZ*t#6bXpuQp6-jJsaPw^gBbS#)Z69H>?vlYk_hFOY$227xeqe0uyvGjoV#L&^9 zp0Y?BHxYN~ZoSc4KJf9#JRMNYI;NS$`I3rQy;}!`d1nkV*)p)jNH0x(1j^G5%^_qA z_Z}X!Hj;Lh~he^ zn61blU&H;zf55ebGg68)am8SZ$@}^sMWX7B7;KM3nO2|@@{;MDJusinZtvcKF?!Ep zRzGDm^_C9Ilb0U+yeY^Niu3B#zDN_eWoT2#BvyBFbv@LehB4t`a>bXz>YmkywBL+q zyxD6)!@QFRU&RVn4vR~OARiXzBP`W%VKL%wYG9`@n?KHzeanRr26UVa(=%{qp2Rw( zE@5&_KNqs3W2Y}&UFTYtg8M!S}0o~mj$H!Dpn6;rtXJqer0tz;u|ED# z8Qz%QN$h8Ok?BpVu5GDtOV=JLVx^(zcDiB1!;d;;7Ie1Z_@8W6_H93qcKjVk>B91t#nJ*E<{imT21=m;nmrO8Q!I(#>hnS;A&dME?r3A zRv!tB0*DS$WnM~d>=20ram}!s2X?=^u0d*L>Q>qYHTyLRAa!>49;Y|U1;EF`&Nk>w z6!uvzfHDln*C1~}b*22)y(EkbD~z;8{+koE!hRe=F7r#de~Zn`>n2i|#+4(9s8w=8 zCHvx$LvvKQIgM_HN=@kdNiH=>5p-WX6=UAHz}#QI^k_NSNBJJn@fVr1nT#oLJL002 z9Ca~7MZUxkj}#liyC8;DABDvSC@RboL)^N+9N7iYRC#m}LsSl94AI`I*K|P)tvtH0 zJK_z!yCFs|J-UD)D*PQN=8zZq=)--M1#Ak1kn@Ypo1HpgF@keE1iM3ofGL5p@*(jd zs2u+-JOB+`?ohJtNyK^i&W#W+xa(bV&r0*$*jdN0A|r1WHq)8Mz_ld#G{{JF?;x)> zm;;<<(C|RydPIz5s^%`W<%^C&8Ia^-5I{DLG_B}Pw&*C70bLO<_JHU*3S~eb(=!s5 zvE~SW6$NEEFi0lB!bP!IU@D6DUycqY2`kJ&;0i?BsrZ0}D#UZpXiOCW2w9Us@{-S1*TZIXUHPX4W58G^~^IQ{O98{Uo>AP!*DkFVwsY`Gd% zW%S=c=KNW6F;&EbYy$vy(}~yR@ot#-dmuuu=KWNN1#;5ROS+C{}!RY9{tRu)yzFog5^~W0r}LY zrjeTYM~bOTCQ%LxIqMzM7|oI+aAQcZSyPDTBSeab``DD*G4vDD3V!EjrXUjZQ*cz+ zd(h6kDi$3ld*)k4^j_s3l9m>nZ$1u&HF=P=lPG;f}>U)!{FFrON1Hczv=ITULW8ERMjy!UYIUolb9fZZl za<74{+0z}n+je|hNwKBA$smL2P7<~O;&PjL_i}j#Fy?h_a5!XZ&5@#N3_URk63zj zFiO80^JEe~4tWNzqbcl5+o9%8G%J>;gn4m3_qsVQR3<}mUKLFSZdp4t+=HAd-injp zE_=OU?yKTmd>}f`0D3SVO7WS_QnfX?`3-Y#f4w{?H+TV)c(N^4Lr85qwqGDAO#-9=WW2>< z=>c2coDQAcnsf`Xjf2Z&VS_ zt2kW0@S54e>2F6nyOd2VehBC49it;PQ>Kia1Qhx5bq6aT{2-1jaVaJfs zpQ_$^tbH(ggUcR@L}AUUoQAE9%Rhlf@jIVHNBAv}bU#OI!s-g#!VdG@Zt2(8*Y-Ya ziGhNieiAoCSj^wTeU01+2?kH*9aCAqC=0;8e>xN!T677#9)5v6S=A@;cWXSwcN8$i zJ-Ip|$k_4S-yLv8%lpM~#xA@MvBp0+p%u!nzT%zWxGK4SLKXXhP)QAzGQ#hHY>|_V zU=VuF|bw@IhFJFp|7(hpof{BN%=2D%q(Hpn)L5Qr>KM~}(6Ap`x zm!h3y?Lc#spTDI-AZX!(ke}lYMVhDFp&ElJPg?jOv?x6wItM6>Dy1nmwsO<#2O&WB zGwNmW6n?uB?I)Q7Dtdh3gV1QCI90na*5id&qEmXQ-Nz7fYg+1>;Z*}iag{8|ISY0S zRP7|8-Vu>N+lQ^JpoDphHLdovNz*C-b%X^=Ud`G#3hA1|-C6;KPxhs1V^;O89U2b$pc6)Ij*0MtYD|2Pt~w zg(yp3--!ng0n!feiLx0L%jMhQ37v>scwDE3{X!D30(m$&1TqTYvn zo$`a~ojt92yt^F&cHE+{Wy&o>dc=0ML%a$ z5zlFdasiE?K9rjJ)kawY^aQlEOWL7OP+Lp32?Sy!xg2G&`0qFr8_hBksy3xVg2R8FM(84O>ZfN}S3j{%#$ zT@G5HcXhUbt#>M-M8bY{EM`|;K9$V(3ANtYRbA! zXjTV8u?vl9c4r%o15nbkna5ubSt`bJ`_FMk?{CAtiPS=F>`*O(NKr zc~FA4G^1DKV7RKmERu1<&=73Omg;b)3bGBd#Mg~LV&>1p0u zhs|fcfWaKHjJSjrIO-1Mrjo?3Oe6IR4)RnAW9X;vbpY}tpeq9x=xUr2*m33Ss}9^4_~@Ai z)u!<35W_7nBC#L9m>FbL^OCnGB9>-rfdPTSAOTdi0Hz;AEBNCHY$l_Gub}P0H0Imk?)e(tAI9I$;Qi*=yC7qSr{LtQ@HlbRT`scj1Fe-5 z{-BK{dyU9k9F`fOCud*P_U?EnI(#-yio(N>k~g&Bt4X{z{OrzchDEvwu70@Ds_Z1^(Fdqtr8$Hv_GdR$G~<=$G48-I0qWR9_Hz`DOd&?H z<&q{U$P>JykhEtY@zu6(H6bMYOU++9rhKGXC=Ai@DL82+1q++GKOmUYtz4406^8cH z5zdd6r1$38`&;+J#siK(V<=f{-wQ72rzkUz zhk$0bC{YX-joc#is2taiY=0b~>4rV7Pm_0owfiZ5r2NdD70Z72e;|zi_k)2!3>oEd zC{iqW_;J0GD4Ni6!PPmt?px%II+%Sc=*hRj-NfM;JztcmLpvP#d^PBpg`6 z(3O!5^gN|VIgMB)mK<;gK75Mu@cUl%TcCy*ZqqvtRMHhkHAQ8s#nw>*&pc#x^Kvh+fZ4a%W$zwYR3Y$6NW6qvt3@ZUN#hQcJyzS`hKDWDGIOe8 zlj5V6!{m!2mPWGbh^2{H?1dn{kLW}WuVnrL#L+{LLav7Unr7XGSlX=jjDc+2Y?X?H zUHU`|@|BFBvIFn8E3@>TsdL!RtZDG`xK(|<5iM4#f2SztSLJx?nwLd}&!QSa)mWf! z!)Re>Iw=~b>*c-Lk%qLmpb?BvT|!~Ya{TW?6@9S0mU6xH zg-E=!X@e-#nBrH_*%l%lN)5YoA%Pon=SriQs!TVaO}nT}bL0}p8DQnNKr)m7O2W!P zRnQxtBS{V{NvlGpyb|eKUDMp|imL8JhKy3mvaoXllqxCRY}g#W)|V+3)HkhwU2whf z9!QlIYSk*9V*?#klm(0v;2Z-3%OYA`GwWYjLp)KYnpa<6Uf$xC-wNvMdT9JY|CTGf zX3NR8r#+gW((3xcRHFlMD85DqjF)UZ<+s3EQZl}_gSjV;%rGSMuh=NLVz|GYLLdR! zOj$0a@iCSPt~r*FBDBfPE?r1~#-!;WL1}S1VGXSE{>JgUxxXP_%Q%uVI~v&rvAGOa zZ0Cq4-w;m>eX(Yr>urz%s$z@DFnAIUU>v3!)v$KhEk*}Kvir3({( zdq0GC_h;hi{$((saC`kr!A$KA4=`xSk-mljjE4a8jYtTU2WI=>F{3~SEp9wn?2S|n z5hX@l63ijGKrdkezn!~^r~+VY1|Ni|2p{VBkS`UE(HX zd-dH!RrJdCikph{sRy$dsqZ+gN%Byn_*`*~+ue{*(%Cki6ouMMRs=v(UOrk=TD-&e zUple*p83Mg*DWC=sZ&NH7Fk$ajGgQ1^z8aA%0xy}FI<`P?Z6RJDZC^_v} zeCBht&?3K5juLB7wj!TglUILUK>abqEF-~=9JhU-xn!b$X6~Kl|hXeSV_Hl?|dx1oRlll#D333=m zWrgBBQDimAIT!CFe?1r9M8=+rzmsg*6t|kBwZ$zUg`46s$(FXbRdNWR@$l3~*pG+# z@3?;x!({^^Q)HYEL((T-=*;h?*%h}zl3HM2qOX_hs_=9N3he61@S_6zUVYa2kOUkn z)Kl;F>GoV@dcHK>Ua4<64{ME~Nos`ENi*y!FYWx;9!LH#!#*d-!=D$)_ZN`-vT2&V z)+Px~$8*9k_;h7($B;;TKVmB*n`e5ZX@Gv&Niatv64mhGkX@R|vU;nQe0ji{=2TfZ zI=G>*5l(`|fOD@B?{{A&vUlViw5kQA2P*ybC&4--`_wwjspQFnR@H$~#=@$MgN+|8 zGs%9yswOc3mR--E#O9A|oeI{02do83t9<`}wO7dGlh7DCNYr88MAH6fy-XG#ur7$v zLHDWQ+%(&;8x@{{nBf~?=Tz@jzsbdGN{UIuQHWGRE~Vn zDXlS#TIq!BmoH(Z!K(J;;x_cbO?&;NKwc z=7eA_TOAGLON(QTzIt0O2Aa>R<^9J(`;gr~8C4sfMUREXkt>gdR*}cdj%8$y*-=Bj zGdY&=J(U+ZbQKFSIB+K1*c~E4hS->R(lGK z)0`x7{0_3+uI&>E>xDVc>&luxNo8iTYFW4ksTzo7E-vEc?Sx9e;Z$WMEH1<)t9D>- z|5X5^6u59Kov~AdXhk6lqu=MT?LTeNCirWA=%AjnQ$XMP5TUdk(?u;Pc8oP^tKj~_ zaU(&K?9)I-`xlEgMqjxTn<-S@vfP4deB(%?RXeCpV4+0XTVY7efN(AE3g!IA{Bj64 z&M|KyeZzw&YHFesEDZeXs`b%B!=~R^MMXmnvLY-pmV^zBPbFK2#FvH^-wD3fj_|%& zkb50{#;PInhr|yRSKa9*SKo)*>z=Ke3VsdA*{rdULAPr@==gZErWZeiK0lbp;HeXD z5;KIY{BPX1P^bA`9*;;+mt=>e06{UHTcAy#R>6lmUTD^ud85ZbJURmX1riV>%KKVT zjaGFmLuA3}d<1#>srcssVnS-B+Z1yQxpo}yJ_CE6KFO*Mjfo=- zGi*u-a;bKh0c7`dTd_ghFN}iH&T37RC`%?ii>9N3i_hrj)Rljbt$Fav5Jg2R?+w)O zY&vpYBuZ=#`F;?B#~+zy>!){}iN@qregK7E5hv)uX*MOhfm-Oxbh7wv-fUiYkaKnV|+oO$b{! z45m2CVKRRQf0;y>=X=$Q8lSmmJ#$ z4ylG-?i(H!LejVEYM6CKFap?%BN2#T8sElkM^fh+O#Vx-(OAhP%H=&UI=%gbj%Db*%tS~H#xON4l;@52N;1yck8VJQ;?$4wgQDpJ6p(bx~ z^2Z`ar7s$o5Usx;5 z7sd%zO#Ek%#=I2)&qu&m;wzl955Pq$Py7J6sNYBlP8muw(Uym32awbd?NA!++Dx1w zS_AnsSer#&3&tlF2>ocV)<}b6BdbubHe3p|T^+2AlJ1xgtnEvj6dB>ZlWACPeMw7Q zog3^H*fu@_>l33g<>N@BBQ7|_jL75lEzMv;Tbi0(@gyYv& zEAi{|G!8kd*}0V>(%#To?7}B%trSMdk$_Gr1+&8 zPdHc(~NbnTozJ7R{_0@+28mA(OO%|Nr7}o9szL;$?wdIF+h8I8$czt)=7o}=6fqUD| z`=Ww|hG1(HZ-w*V6d09+ci$(Q?wamgc^8@*mYQti!cM*7X|0Xi_E#7YEd0rk*)jcc z{5W20y30+9F2`q(e@DT#`_-4?2Xt&OgrDMbq#;Lz)NHw(3K~QZW8B;vi%o+szuK-7L72iUk81XaUZ-Bo7eggam_yO=e;5)##fNua_ z17MsH@g?93z~_L^0G|R@Ucfj_vLy}gm>vyx&5k4u4zF^g9RKwj@~x#16ODtJPZZkf zbNFsQCv+mV{T?{X+#pm4C5U1_QWz*0;N|-@0tfvWB3dth9b(cKLx2~@N5bp(6Yd%A zIJX<=ma1EjQgCUDOA0`V)Pk-Ru7u_)H{wnp=OC;;W5l7tocj8NsjfBbhyR^5o}MeH z(eK}J^3VXl4C}Dp>w*E`5_R}Z2e~P=zNUQ@`U@@){Dz`eLO(+5;_rxm{=ew4)}FfT z6A=9vKp*fS-~#}LM8ux}M*;5x-UGY~cn5GC?i&Soe;X>v1AsJq?f|?6coTmQ!TTG4 z*8#5qUIn}Yco{|x5ijAxi-0SD%YYXE&jX$VJPWu4fRRtc(}2GK{tS2u@Fd^~z~g|& z02cul0OtYcP@ojNcLHD}6!9n^3vd=N25<&29`FdxbrHw#;WXeOz$w5HxKX)*4)v1C{}*0abvdfF%Gopb}64Cj|2P>@E}^FAKpg+ zG65q269Bn@96&Z;G++cE127yg3@{Wh1dt9$1Ec~d-9fbf2jW8tU;rQ)&>uh_LYuu0 zAPH~?a6jN4z`XzqPG9fieILMxLOJms4Tu65@b`0g*8?IkZNpHBPw`m?2rq7Ksmpak z165I9T_+3~(pM2b;#cVNCvf5)`6FV9DDu;wfY>b@70S2?0uLkkz6S8LV<3(X^h7@Kl z;jK9AGt)>INm3bBacA2Idcu};(mvX3*^+6ys~cChl&)S0=No^$bdU5YdAL?B>}<;d zGcQLv@FP1{EizY(W*d-iK&yV0ZDsr3A*)|+!j=<*4E_5OI z5^Y^s!luZfuGO|s{f)(`)~v92Ogc8nr=c5P-$G9v)C+#XOv#(ur|zR-t?g=BF0QDv zZ8YQpi2<~77sbo>$&!;^dz&WTEx2q|trPKmp&9)T=eQi|hi zHk2<#FueOSVb`Ljw`NrvJF~^@8t;Pe(dGUxXkd6`z+^;rIhRcqS_?5Es++6o>zgnh z>LEa^Zz`#(b}tERY7gdT~e~CcmVuI7Pnrthb?0!6XCfrXupjEAf0rwA zBl2B!<<$X^v92}rQQ?C)VJO31${9Y@Ra=XRR6z%RPaz=C6I6RHw=;*S15u8;GBFz2 z{xo`wQ_zJ7LM9}E|5gejRb&jS2ud-*UF(yeUu*J#1RDPuCPe>TfDDl64MC79-Dk}? zRjo^2V|8u4U%)9}tNH>?!4y3aJ(8qMTV-V0(Mhn1dSP&kC1;wXy6{bX+8CShPkzb6 zk;SfJ%j=ZRHki9#LxECO>8_^Gb-r+1(JV#~#8EN0zFnhjSQHy}=}zK0@EY{R)6g8S z7ghu$%H(Bt)FsSWQ(s%%EL{VM(5lH{EkFjln8Tll(mHnK~SZL zt(fjRC|jIAS=MjU6iQVsuJZaqcI`q5q#BxN^=Jj9O*o$u_lVOVN}t007143#@qgv+ z@91}&h*pesf^r^7yKt!P#OA_+k z)d;@b+){gOv#oA45lU_;IyNv=U+!c~;JWJamZgYRl*_J4#jj=22Re{}EBYn5Y^^kN z8^Xom{M1-qQ`uchM;GNli67KDHU2%Jbg*xu=B7a`w4|jbVcKe_D6bWekS+DCtY>Hk zmv?S}L?TgD@+f47`siYo)>qYI!>*Px?RBrQZ<0#-w!B8yN~EP9n2-w|gE9e7B~?Rj z5vXRIG{xNn=MO~Ut8pP{;dR$mG@>zlFN_r^8+=jhq?LIxcDSYqs1RmL7d<0wOJ50b zyPN7H0z{Z2@>*(Yn(L{Kvbm;*+kN{ZRDG4WU6wT|lQj=Dan&^EyDOUAtKCh0tb?rT zLlJy57Iki@phHWFFXfBzXZ5xDB$y>NQ<}@&jglI;3m2ehJJB+mxZ+Jp^RPvYb^@Jq zp;U{$3Gra?_z(F@ z5VCnAE8O0u^1Ho1F5cjM&2ZqhETgXZ=c~q^d5nE^(e|1?@z;&%v$(4J2Koxec04rFDIM4p~K_- z!^HEPS3e*-a)|{4$*3Y`WGVsnyw#bBC%zg!8eILbgQKGZn+q1s*~JQP2C5u!~bPvatDoRGsI+BjK|JAe}txLtym8^Axshi=cY zMAkyPqu5g$jo#~NMR77q${l5sggsQ1IQ4!tK2h7*d}J5Z@zd&6~6K|`_- zb562spBNTOQv&SZR(T^PEZ2L2z?(W8ir0j9^902L?ZmSahKv39bSRb2Q2aA!;QKJn zcZrF7I>1J^$;2Dj^aLwN)4_k~j@6KwDVEuTl}(kdwpcVh;_=Cp;d098&Bx&$+s~HB z;?7_r+rHjpA@inM#w&_7x(MN3dV3X@GDyztLH5~V;>o_*mNYvaKyfHaaMf{GMyp5& z6rCUAU|3G27&4+K<~Z~`NKB-dY^^J`q>A)Yxir->Fw*~-&@nzU#Zps6m(XCUeP|V)7M89sCX0zjWATy~5Pn?Hp% zHq6-uZV$DcC~-FS6ssV9a)dA<8BxF^CbP@sC1gNV3L06)_EAZwnW9W zjF}zetq66J@79OvNcMYHZGysB(BiOuUbq!z9(LL94E>te7^81oe^5F6~;8_9C7^|WAFG|LuedNY8yj$@5~AgnjFd@ zMeZsb_bT}}A%}UMD?mDdRPH?_Y#Js;LstGF6q%3WAV`EZp-FI6!1px38T?%a`5=wG5;e4ySn#@hpfodAH48A$meHz3XOe^4>7(R`04Aw|Kvqe#-!z@E3F> za?6k8;)DVun!nSh)m(`&10|ufVHv&KtCie?-WRI-db3viL27V;*pkz$hf zc35rR1Jy+#l7^97xiQ}4onQ4ZB0$ms6VJg)ai=Ek=p4uTRQj@WNRUS?caj&rh~L;Dd>%iW_x4%)mUqFL zzua+M(3q}1IpXzVHL~UwiW9}rJ$MKIue<2bx)HEqzG{%GN zQ*$$P6@Va}utnhcui(0Wk$(v4nCtmv-di$Pok&f~6J=jSq(dl#CsjV*LJSi^%gEdR zun+Di6!>F2**?!%AL=oCaPCMUmoJ8yIxf$34(8|4LWCgF1k!v~@qgia!&+b-zZx#j zS2-^?NpxUI`yK{Amyo&oAfz!jKqOKuj74G0tT3-3hw)MVE_o7KrSOJWLFkLB`sb0f z58~^*^QRv0K00OJiFNse&(h+NF$fAEel5NuJ|{jZ{!zS3Y!jPAmslW<5c`To;Wxx? zdlM_{Dd^v~AjNV85{{4Vh?*aFg{O$QqD_5HLUBti zq$lo12Rqd|+D$f*}Pu8ZSm zDQP16(L~d{+s%^zJ~RyE;PbH+iX-YY9myP zj)x=S`tthb3oEb^CUFYJVojWCxV}dd*H>@9(2zi7QVPP08lUSyq&BXAoR5rqZf8(j z&=3vgEZ>U3*^5sRkBSTVS46$=9Jdl_5g=J(FMK?J`KHL(n6M6^^q0FU+%y<|fRkN- zpiRD?0|BrG(7#CLd5l2LbXP-F3lo$>5Yo`(W;w)^19;D5Ug5xf*kqGnSW~3MnF^*t zJWh23K4V~?giU42&_l0qI9)-FBNaiK+C1dkuu)ULl_ZEcs_YJx>mfcaxGZV*|rqNQ#8i0=H@}?CUI_5MgR(+dwB56{t2CUGP6p8bI+d00)mi3S*~M zwbcFhiU-huHCPuKty8P&{|7Ya9+3p&9`R%G1@SRhW!;aYng5Xs5jNle?}9(sWC$(N zg%}|WmPa39OM95VL!2zOjt85R2}UVJ?1NLkO*D!+F%+l&U*LK4Eo>k@gcZbV!WHav zPr_*F5#a>vAr8TMPQHV0M=s`r2)(%rJNOplp!FbeRtpR( zs`(0j0bj}&@l*MU{5aT{4dn;%{rE)Q&YO7{076^dHU!sGZG&)qs10jO#Oby~T#vOu z4HNN58ze;$; zgLnIZ7;@w#YcKMrm#k*neW5TeDQgM8pY9fAz=Z-0Vz}@S;(EzyiwPHP__nsZ+8s2) z?{gLz^ODs{M!#f@fZbmt{rvYA5whX47p;a&y3dr=x>qM4N73rK)fH8af0>aow5-;( zG-1Zlx@GRVYUmD^$9=979YPrdh_HlP8ubLZ_eE=bE8Q8(s@JSpolsT{bzYVErf%P? z4+HA~9MdG_!$jr71T8W#l~HACc(w0i6?;&1BP!PDa(vCoSKU}qUzbqS0@2XQpxNqI zWYCM&IFj_D)o3q{KoEhl>V~T7mL~1b@*l2>I#=*y^86L6Wm>G5iQoI>!h|Nzg;-#4 zX;{wW)^SlfQ3ItJLS;P+P7vX@V1Za4;Ns_5dEQFh?tCfk=GfH}?~`-v`*jxVZ@w(r z6X)6040apm+1D66qtBZYID3-nCUj4UUELzzD6!Y-%g&pqq*8U?VL_IvX4(76A(`k| zA1{6t4dX*U{p?pDvTlxjB6FNYVeVrQ077X5fWTyOQd$8Lb&nkp0RAs!j|-C)ra2r* zC^6*;AA>V_!YX2w!h65b(YX-a*Cot$HDG^^gwY7M7T+|&C!)9lTQ%Z{CqiPyEumi` zQBXojBWz-uomcT)I(fdtG<`5Wh3C4Os@(C}_^882XelZpf5jgl-qZ{d3AwK3rtoF- zn~o{7OdSH&28eaLrDjkQ@@>y?X!APTAX&NlCw?QoDL#c9gnPxCVJ12oD}O51{9uR~Ud7tp4q?JZ2otKX zj!#4G+0P>Sb|Bj1W9(=V+iF5u!%42yOOXc+iiqMW%sfX6oyWc}XS!+~E9ugJuj1aO z>%k-!^en-75?V_g%-$rUi-Z`;O;2()HzN%b4XhA4hpwWNT#b+$)7%!+POiAB(Y>nD zyq2yelM-BwOI(%i=J-n%F%^h)&Gi)()mYgif|2E9eyFuym~_I?eL+$}t+Bo68tX%i zDrJ;#tE;Kj6|sfd-;tspV~v8d4|zSr8dpM>%}Ge+1MK4<0gZ zG4xUpD2JTv;k!SPh7hZB(2ONZ5Tv&;cN5{7(Aw< z&{V6>0tw|=D4 zN}!k2tzmPv@jBsK{u7)$e&ROrhxnNg zHJ!sYGnA$itaH`6rR0JM(`S?@w0P+FhlhQ!s|Z`aqH$CN=7EaenjT4Ps-XLe}3JyCMrLoRf2 zCUWF{jR5(7=7u3b!)%O}eUOijA&GMw=1Bjzfv|S}DLWIj^jsCKcKveo2h9!vex)vopChygl@}*$C@Hu6_a^vCSWZrP{Qrd$4C1>>Lsk?X0*! zeKrol{}pqHccvYTGo=q2VK zp=Kh|%Qt_=R!K-JUmgr zqWL^gSVhL=G%iobfy}NZVdCuk78sD!S63ExGgYGPshBEBO*>Jl3+3Ws)1~J854C`0 z0^&-ly(BeaYiXmaxyse(p6Mzt_oY?3maz)*Io=2ws+ksBrE&4IA}Vz^ta7b#H;;EW z!UL(Nbd^3C#iZ)!MmHS8Z@|8wS`@N289943B$VUp-7SqZel~=@a`}i%?A&lYW@@0p zM#gL;DwJ+l2AA*NHCU~cp}Ao#78Y4n4FM!e?KHcZs`5*!!Se;!L;5Jt$WYP?SwvT( zMbvynN{hf&NqNnxt*okXmsk5tN4povXMa*!omN+=CQl58b_fyCHt?UpEb0&#+bqU=Z_hdJJMeHP5g-I=f!vzEs?#{L_ za6ZFjL7_C($Yb@^=m|0}+@GB`aDpjxHzzCYArZv-q0E0q6Q;a@Y2 zpXx%w#+Djp<9$tPa))$v2a`HorIwIipiIK)lcfZ6K6}9~lMpIM(SJTGz3)(sVL2b& zyr~M^;+(G5-H`4C%lU06%8mh)thsM#krdV7)Oe+|p;IQLVSlb6s1L~P#%soC8injJEk zqCdua3lBtzwRa9Dj^!F>$7|J^6Fg)@Be-CGC$eGjJH=D*Yv_o2RBK|V+ZFnWJ8*b_ z|GR^AE%Ss{9FAF~Q5k;1j!6uMI!e;$O2~Z>Pab+p(=|gE-|>e}G$x*&A#NZSKGkGK zPS}A1hU#4}Ibgq!8_DONY9cLiPv!+6$>b?QDG+2FI-U^=f`h$QzKDchn-F?&tQd!k z>@Nu?A&+gq$vp)&Ebs9bu)JN*m$1q7CU**^5LLM4RUu92Bg6_Jki>pP>NXn_$h~7t z=8kb&j4$xy_RYrLByy|q2eRj*$UfwBCM>kJX2vE{!>65Fj056yq77R66C7+(=kibU z9$!#jwCiT~38++9X2jhpy?I{^1! zomh;R3rJJ+cSztTVI#a1%C;*=0}&6u#bV4|4B~W!_mq~Bd}wgxWTAzPEtT%Nik_1f zqVj&j4DE?U1;afhklI8awE}lz#cD)Bgbz)ZhU`WPi44J?r3R8}^^uxZ4-Th!HN@9o zGk%ZQynqC$K0h1`1LfsUxl4Xj-}Xh_h5~CW#kVU%d^`WbvLTF%KVPRd=@f{!AlK>1 z=Da)0O>Ip62f+;^)^lxFwr$d`I>0zt=bz0y*8e10TUj^^MKd z%@_tfCZFuqAf0X5bRGw=E))Eyx!^L>L*CHtRY$qTp-}@9vFG_HO{iW9Wx;B&n02t? z{k>YEoerZB72PY-+seZU{7(;6Lszqti_*dz2aChuir&}nkf!n~zM_@5YoW_=VczuQ z-@uxTl7*w7oI1f(Llf!_$GOOjLF&&GRE{zfwYY_O(0)?6q!VhZ#IG_B2SMt_0{WycdY-ou76y64@_>sRaqgX6U86pOYLlU5a9?8^wUk##1mR&3a*MJ#fsjifG%4i{N9)!<7@ z%{Zyi=((#0KL@!Fl#PtGR%aWIplUZtME;w8^rHchr<+A9dxp1jX)B z?MJOd}m@98)ES{8YFaep7#^-pP69`PE~7ebXaxf`1r+z@`}AqZQ2 z3si{i?mQ;CUgD$~7s>MUg2pJRij0fzuU4+hQi?GmD`=$UlCieGtELHD*U_A?W$n_O zzQNk%iPuQUjDo-tRc+3I%@rg5ze?*&*LV$=McLbQ;dNmt!U$}DlfeNl3*NQy9fuEC ziV?>09t(ns15*@=Aukoa!yLa5mMihK)XFQj<5IKM#*>;q$M4Vy|Kvo7a>VQS*M$Yt z66_h?;Nb~20h`^bNWwF>XjMb>#x2?_bi&_A25!-=C97}K-j)=K)e07Je}F?n5!?)K z#Gf2jQ4Nub(X1>cRGaDj+qyJgQYLVsvNAJtVHLwwtchh@tGC8ul9d1_)_K+m8qc5# z8kgQ|C5a74*iiRb{GA1Kv9xfLIq@SHG~9<63=72^sBM0N_W^;gMV6rD--cn|8t}3X z?o;jvQZi0PUXDj#t9>(sZ*yU5FaTx^!TjLhG5v_^j2KJ$J|adD!~WoS^4)1MCMYX- z%qZyx{HY`7PU^Mf`O{)5O^pyvww^`o7W#vCY+?j?{t^6@w$T_Ck{UcJMG#1QAETB0 z)&_R}SetQ3$e`d+{giL-Z8Jvse-VWiRJkr^9t z$=YO$i=<||qJVg6y|KgaK8wI!`uS2~l0+pK<<;y+6L}^xe2_0(8a-1Ws?;vnGYy4D zs65fGSP)<4w(sMI_l?}(}{m&&lQ5GteWgQ10(#@lStQImc7|q zGX9uG6lPJQ^UonMekN|FZ;}iP@)&R;Y=1P^L^k{wetnQ9`fi@w@O3yk^Q-WGMd^fH zI1E+_{1dqRAnx-W9<{uF!QF6?Lk>16IR+G8BO-Er&4sF?!7A@wM!7_t5~G!6BHBA5 zB7+|1q(-1

I|Pf$*RtvONW1%@QhtLr9;A5mQ6OJZ>%m+md}cq~f}8DI$bCJ0T)N zQ+Rg`mMWwWCGAO?Sh9LTL>g3jc$Lv8xKiJc_Dd0Fiay9jA0$Z@=HFe5?o&{VgoVwb zI8Is`6^&y7>w=*CL7KDYg&F)0(qN$nX0m^rb3sSqSZ5ed&Wv_GXw->%7{UI^K`bB2 zui$=#wGoNBY#4$P;g=4i#g)U06W4kO+n;$aVvw2-i;e&w%|k#_73mek*?sKg2xXAa z=79sjz?UPMG@j@^@a%RXAliz$IAe$Lm5BAc2Gt(MC0Sv!4h@%y-206wm~^}v5v`xU z2Rcsm>9De&NC!0@@83(5_`E#`1)!DyX-jBKHChDUpq5IZ6XtRu{C*|YBu9|37G1LcvuH=p*$dIWAL70&cuag@*7f)I`JjlX)-;+v zSCTalS05uXMO$?&^)~HlQTeb{iu;-Z{!4~>sBbO(*+B5PTVJshril71bBYkw41I14SY!X{qZ;rlkLk8AM(42 z5n5t+BT_>?c>_Zw|5tR)`@3|J9jD)j^gxg#P5@JVfD0hT?bO~9vOJAsW@5gSQG)D4LpkgN)VsGy*edavB-oPTj zQ>G!98_NkFAU08d?j$!>{4Br->Kx({o)^!+Z15P2%O60i-2+|RcCaIDVrvVmmoR$A zF-|YaJ0@*3S@*RV#MFD)8Cl-ew3wJERkgSRo)f@k+yOL;W72YHZjsisq{!jX30!ib zbO^yO$I>PVS?S)N)5;@TqY@Bxx z2wB6Cwd`2~U95xnJ)B_Y_lO(CNIKNE@cOm;o3U2flayteh1_0v5jlz8x~Ny(axR{W zuo*(u?uU`|&_uI>%SJxSUsU{<4>xD0!=|UpP76JvOSn>Qq`zL!4`Kt4q8LJ2_OGNn zgpA^!4v8Wv!(GB%wZDZHQ^i$^ndOfbtzo@~d56^}8-dz9SbzQ$9LXQTVCKoKvCeXm z66;(%mLlz&!p{F0Yx-v43%$R9*ki}(4s=T|{yaXFtD>gPn^*znc5MC4S7s%Bw z!<}?WIC=e&W6&KW+kHMyG(P;^7IU|3j7yI}pbSLCk1XetC=(gkV$KTi{=%7*tTZnS zgJ5+IHxwZub8ZWbCFLv48RXp-bGZo(Se3rPD#S>rE4Kx zYztdLA2=@nSx)c=ii6~c-0BSyFAXoL9pV54>6#8}`c-@^*GUX_8ipgGF)E61Bg*P> zu@_?0Wj|q7W171DXpS|6l(nOp=}xO6^<|MXA9}*9gxr)0hw_!RV=3+d(Mb}XG)MR^ zvnU{6-A>g{N*+j5f+peae9|1vGC?ZczV1n6;;w4PiVReRRaa2^t5^w^xX5;l3m_@I zp&%KFE!<*LF)6)e?bxk=s#IJ-jV61Z@+EziAC3L0het<~wZRtEXhuRk)_M(8nm^LN z0GO+HV6N`s1T!2dH;BP>uHM4ySGSjA5p$}$sFI9Yjl9S5P_JosF)YQtLcubSPqvt? z%5x|xjG(wCmg8F*RXN+tCh~l+r4LyiVzJW5!L0AF*&@MqJq~Cy-Ak@-uY{<;X9Bt| z5rg7|U`uayk3tF^RW}CM1u|1nY7K7w5T- z9L}&@&RpNLc{0{Sb>(9#EG|wfcauArPoyQC27AMbmN`2RO;0CEDUHb>F{otY9Lq$S0D@~i4i823dn4I2$LIRF{rPx@ zL8v$m=L%$tReIs063bZssP&kwZdj024NQROlV5eb1mPp?x_NS`nWO03S(ZF`R>(7! zf_J3Y%X-9N-L$WEw+FrkLm33p-)J;jM7U@V>zU_*L|U;+C|Uw#}1 zO+^35QJ(dSU?kIAmh?owtq>JQxws|Amtxs*aLVJ5^VUR;v?3+Raoo^_C!<}kh)SrX z<1S%2NPk#tNu}vW)f#XMkK<6RV#%x1_lqrQzKmX!687+~T$YFJ(i+7A&-ND12{U03 zv;o%1M-X_H?3r)rALI$%97q0ki)AS(x!F?NvEWwAegy5^6u*QF*c9JD&TWjZfzebr zG#=Q^In6)-#2A_Zi09?NJERdB*t=^GCrpDlVVd56BtS0!MwK=ifJImnk9TNJv=G09 z!#70>wn_t<8vL%IpD~%}_M?Gyye1rgBe@21;Df{>}$YRfG+`G z06qtNhVX1*pW?$OfR6zm0X_tL0JsWxAMhUFT>wnV!rlhF1$Yzi2H?q&};4t7}z#jn*0UiYW0dNTL0N^0t0AN4he!xD!eSmubdjWR?b^~?+b^>k#v;l4c zcmV4F^m#V|ZUEd)|K5VjR>1XuwSYB%)qq<8Hv_H%tOBeAv;dj`O@Kzg3P1y3gQTX5 zpoO~yunDjcEj9!1>jD4a_txJ-==wV&IuAt40CNFz0HuK0fLVYNKrvt@pa@V1paq!@ zC;&_YOa)8NW zZ6uzZI6G0|{tOSLUw<-;BB~6E$89a?f+H?H36@MHFB9XJShKny2G2W5c~6@|DhEzd zORU)eXCy2J*jb^N|B|ogNY3Ke z_z2`H>8IopCOIA87!DI_8e{9UyiiKk5s%9Z#yoq+fD!G(%SQZx9^O6W;QZ5W(Ah$9%>sw%!gI%(xcc(^ssv z+V#s%Lg3N^YKl@5iUr>9cI?|XaS+Dd1l}){@_tRczV##+mZ5evosn_?(vbV_vt}w3 z=wT^}_XMAWydRlr6uFuYIewonnGz0lEQjrCD5zz+^qe+BJ)-H?oCLR_{^)-~8+*t) z#Q&iNe)UN(UO3Gu&-5J*Pad+W2I{ncPH4c0^r zUqr^C807PO%WSeI-!d&U|2Wk6{jB8TW)1SwkL1J1`Fx~a_vBmRLKhvM0In4I3=%DN zl7Lt^9ZRz!eJ_uF7e;roRgoExbrT^dyrC#O zsbl$R!!FUHfw>FL{d(bmFp|Fv6a2qJUmDvnCD(F_@2JbNqzUvflft+uG{Uw?*exW% zy)lEkfG_^XZPc-Mq@|n}n~x7AIlr2nG&oFhQ=*?jMWR zR5`ab7XC%#H(Sh{P<#?0yCjM4;=sIE7Xwy3HYQeIdJ48R$P%SUGF#x}q)%*&UBBoQ4rJ=Dm>-?dF{D>)%)o%<7zSIjPvK04=PAoE z%SwfkL|rpSR`IFD><(r9QA(&IZ^p)0yU-6=cnZ3B&{q^qjQ#+7%(YW|m7QA1?ogaW z*d0&(#S)c5$5h}+AVif|Ri0YF?o!SUzN}mwF){H2yWHl>%B6!EE`&csCBugxH7kJa zO-Izf;_l@2B^{ACCmGdq63e#NFdBKjt{ZhxkEqzF zNIs=4onC0?*~tr|ae^5&CMH~8)`6@W>aTL1KRh{>{v0K@uu5xY2U2eUyZe(jj)^gM z#h%w;VAx7K`O5jqn3(vk*fTp|;@TtaL8uiyJ>jL6M2BjL0;0<-!f}Z39TuCP#-<}- zP5gL1)Z^$#21#;xM05g~QW!IY)VEus$mNmIgL?65Z|Y#JtAPU!cMg40f@tjrgsD)c z?k9$a!z{X@)7X8}k%0{jpGq!&9WyNmPkxW&T#o5yPfyNmS+c}cQ$NwwH1jkLiAX7< z3~pp4fiUf(7!CREhnQf}`F2c%|49*RZ!idr^d*-eMd>yR`R?l&i@x}DJ!A%o&lV1c zAECPzUycbQKYtw)=RfR0Ml3oFwGgoVo-AYMeG|h}0cbcp3pHTa(C+kzy`u;0*{7jI zLamez52#fX+4f{qP?zEa&pr*6R}Z&Dl11;tMD%z|$!Tc7{L=CGo^tq|7(Kc0MohP- zl$^%-xyM_6#Vx&PUD<$9D;_-aG*0}u!>^fG2gQ!*f~eyU!wk?%vugZ}^CB6~XK+v- z!M}%ymyZZINdcO`!340te@wFtp^?1g@d@M9cFxElfSV*}qbxAL_z^_LP`{FURg-Q@ zS7rk1Bh2s0M;a(%k}9O5-M=K=HoOZWU+@UViQQKvXctZ7&*`>!|B*)fU3?H8z)3bm z#~Srzw3#5yPY@Y6$`-CKeFP%tB%8FAK%Amv0SY3okL;cjY3?HsLaVg=u|Z79!Gn>; zUVPyrkgPk5QeyA`+UrNDd6{Hvo}c#!Wa}x3W<_)CE6EF^Z2gsyCZmThex#9BUp*@% zJ|AZ$htq6nflDAew3PZPNPN{->PKe=eL-Gy7&7lKIU$GtQapj>;AhHtUg5VFhUtsX zK(FDjD#4HmvP+psb)hXu?G}kjNc9;b-4IpDDeIOA(`+M^ZjtcVSeXKD#VpM(vf>By zGZHxUM*=70&{BVp6*c%JU`qv+kojkzYWGuLGL6o!g|@*;Td`W9VpGnTp=PnEnIxI= z{&bq(+f*$8UF*nlNessjE+F?XopQn$jKDPHy^eo`%Z^2 zxW>KTp*RZC_K#xB-E&I0&JI9>JJe*HY^&OF#5P2s zD0i9QI*TpEA91-u;{35j5=DR+VC}J`voAT>*0QP z28ang^h_}ScdDlt4kzm>grK|6kVdz?4qmK%6s~spk*1C{A+Z~IvFg!*r0`O>X~*=~ z5|(v07|C{F+};bGt|k0;%AnTiU7b!a;&x71;2AITT~%y?KEED89B3J(Vi4C4R%6E} z)v;iQb^HxT^wF2&`igf5m!Q7y;FGz_+$?T=>p2HP8`znj;QHcoPH0^1DpzysR^2sytBiX?#;Zpo{^w%P|rKeHhAnm*Nvs zfl}i447SeF2FEDg!0UL=_;ZPV^o``xXW~^|DtpHAa|z((lxHAAkMa!VT!+W>8ZBmH zRfyyeFnu(CS^R&vd+)d?&h3AE%CZfRrR>hmEDNlN9T7W<1$!4%6gwyis3&CN|Qxlt2inn^VGrfZ^UH`V;!&+IN>?)`l3{k(qvefO1lBD1s4 zJoP-Myw5pvke&q}c=*(PQdb24s3&>daM{;9Klu_YC~=e$;s|Z*9Y+noc zGL{M{Hc;pu1;0S=p-WW;;W zOlA=Q0>y@aJS^fsV=4IiplsF$J^C==atG`oXYDyN?~S?_WPIQVqudg`fnIsTu^_1T z<@Q+K)>`A_jf41l@|%uYWys>^DTkm3NWQ3IG8|-L>>1w zSuPuUS=`(eAf{Y(B%-=~c!I%06rc^eC59ogZn!I`-xUS(R`*z3hw$31mfay7K#itX zB&-cbZRD@%9qS^0J!l<1E~w2F8`^2DU8w18!#nuacwyV{=|PLGAe1V?zWY}4?6B}w zw6%43pzo*R^f(MTkJNhk_jcyYEmhcw{Vm=R^Dhoo1 z4#b9e9CcgJ3rXS-AH?Hn=fjoPIWKw##Jh&va?R?&jIes5O?&78D73MBZvz z#;nZQxvi$m&W(E_XGTt(*5X-{JnumoniNR%hS`oE8}UO&4m`r#cW z4S4&X2FN=yEEwwmMk@cDQ6SK2^*z#a{*);h$vFs^Uk?H78w(6Wy>uWfp9+h0-mj*? z>i*y!yhwa+m%8*sDvtb_IrI9>%BXedtDCbr|Ik2wDMa&ToOp_FCWi5^AP^ON!2ISg zlx&FwZpxtUK8IFtvCN^hd(TA~GiJ>GSBF-g1LtEB2)ZUb&kezO;PVyG(BGYV&z~_h zYSdK3(ST){wX%Lo9|L5=iv~)9+MjzG(dWPaJ=+1^4`Qf6GG~m8XJKmn@nt>!zx$>7 zlJ9s2y-lCoy!rVV19J1~&0gK0)OkXRSsb*btVh}c>i%E$#n%hW3iKc@t0y}TptNjO z>J2CxNfu7gw^zMQU~G521%%o#D{OAHMs)tqv+8?)|C%-akzA<5m$XHDe}|qqwZY($ zhX3i+p#F8e_h>NS!#GoT0gKJ+#RzEW%s2U+WceEo<7Kb$I|{SI{fxqN22K46kL5?4 zWaq?Dp7JwAH$|q4>GawZu^oLiS#%d>iaN6>q;ukI;VmKE!{xCh>{es%iU)Wv7<>gM zZh~%;f?GP@WR)G@0dZXyOc_CuVY{jf05UstbLe|Tw~$sSx_p-G2?8x})xCrPb#=~E zGyCgQ9&vv6Lqqt06XN-c;#NMDdmu)^ZoVF&e>r@06V7^0Z}6E$@9O$6T_1P|Z4jB! zzfL`dhqLQFycrLB&=++Nby6`l%E(4UG5xS9Q(k(kL;Ue!i*;qUEpZ%oO>)ZWiOG+_e3D-E3$6 zdgwb*uZB_QXRe1LqF!TS&=_yp*ni*6S?i~1Kk%6d(5&R>e`%2if(NAoLM(L`?g{DO z5mpDi?!j;!pXraJl!DPr^K<~ND6ZpUmzDm-7&0@Ch8Za`qGa%2q{l>Qw`!(YF?7T|K@bXH|hO9tFPm zQ;z=>x!#+@s=G6=yJt9pau1CI-(>YpD9nsyb&%4BrIIVih~=Hh#Y8*3Qx1e`80|h1 z)QYW4&pPJo5URO{CZamu!x}<0RD0T7w~i@T3ba~`IftMtk9iCyTpJong9!6khhT+p zI3Gt6PcI9q#jUZ&8W;nil@a*?96vzJK&-9%A#O(4E?C?V#iL;j4y|=jsdiby$ZZ9d%5mTngJnBp<@ou7M&k2977WD;CqVK z$((hCEGtt=yRgu`o}{hVm{&Sr7CQD1u0^0G$w5DXO&^ST-pTPh5sbb_7{o~OYRC<3 z4?7?VbJ0HL*zi(tPhS%Tyc9f1Kk{${^iuS&sT@v0e+`x>?#1Aj*~px#_dC+R6x>T2 z5B3|6?m)0JM2ZDW)9GqvJs#?P&s#r24ssL1CKFm1dx* zJr)~`^u949j20V1PI*1;+j0Q7IfWy_$>7X}JX@s#PYJe&`LwZZ$b3@ThRmTOZ9?XT z1d5rUV}IxPzr%mfhzL~eJns)0S_U;FJS&`DBBoiLZoe7guzS~_hq!b4>@tKBiFG-; zlWRZBqvvjgxX5rTq^V(A*+TXOW$cK6OU{KbBRz35q@Q6-*%Pc{x{`}5(%S77Z-sRA zA5{0US_4=Vdza@d8(OBpc>kq2K}~v2otHB;YicHY?oUk%6nbJ!M{#_Wa80$82UwtI z)LGmCM_WNol6=`#Xzd_pt?787>^Cr|!BObHVr7T#WPAVfP=$;S(XmVOLTa@FDY+pI z>h?uwAPqbk(!e5$bGXg*>ZLVh6ky0Q=i^P7RrC)v8#TJJ6N-sho? zx|e7xbyXk+)4mTwYh}ZfU2MNjM?^Nf z@i@{T`!a0M!Vf|RY4728hYh!^3@z_h@7qvX^g-xA-}=TAqe=NNG#$Gmj?;0_;I2XV z^e4Elm`0<2Kq16rU!EI!;a+H4t=@m$3mr~h{usK6(tixyK(~JgT}^F%2rYxbl)Hf> z+O+*MNViMA4?Uw{s(ImkwriUPUS$i`b71tftaMdCAre!UH~PwzfN=UOH>}nbBK|_a z^#(#RHtju5T*Kdk4Ze2o!}ym`3E~VTrSD|9kqIx36`zDXjx6*L;c;Ah$p_F0{vvEh zP*x@AYwbNCJ-t5;q;_9~{aGK%=T?H&c8spo7cj>Gy6|~e_xh+9be^Y${|H;+Wf$jh z;tcp0QgE6uxvt|qgC-vbBh%iS{m`e{?=;!!qgLvS$;hP*7&%N`P}e|NLkNoa0z~bd z;UhIxBt9ssx*_-oxi*lR1{}Hcw$(yKxl%2-WySke2b1c@u}8fJs{59;5nX%RYGeL4 z_zsP(L+DPcZmd=N7#14U)?$QNjX~3@p)9Jc5oap{S8FeyiF$oYOM5h{nyHQcT|13$ z*TIRswMPFBwU*p^yjBcN5QgRg$6tWyu@iGs3_k03kd3j44@#+C4hE@Cm8H4jEVJ06 zeO3f-pBbI&!{X6;2Zmn^t@&1)tzppY69Ob+-xoMe7<3)qwDNTgP#eV(F#815kN@T| zJ6+rO7}?cW?9jrtdA3=Ppy6j>5@`|>=&#P?_HW2hZeN38HDOry zar{1{J!k{o5KGsQ&W1IX56V6Vgh*UuEj`k}y!qjB!ehhg*=^$i)R(=o3#_yD!U(xF z6CTjy$>)+7jNkjM*O>Rav(~bJNAQ6w&D3+idf|OO7D2OB;6W1=JLSi`%-GXY&cWQ= z;@>^p+bKWhOW>)y8{2`k{6bybABW4aUi(39O9F*>49nXb|F-5B@(DP^g$?X%SStCT z(dTiTB0hufNYN%Mr%-P8xN=krMKg$VxqQ}7&1UucPPtjowDUM;YrpW?tnkfas66aZ zKJ7ft-L`VAAyzZ;y}APL#0;KqPj(=XKK|X%9Pm z%A(rmnb6IP2F`2+6brZ*8ng*u}Ke4Vc zwQ@`ijw$G^ecN$KjpF0P)w4B9F@zpL!0~P2cnf|Br8?o4Us>FU!&h2|R<6U0AGWzjmSYPdYO?)eCr)6b>OGE2@8%qDY8P>c>=21>W)Ljd(g)bN^Kbhdo%Q_)M!=6Nh!_4b0+`K6&^S)P9C$WMv@M?{qDHZboiS z#$Z-FuG(UUuTQmA0DnWIGeD@INysGy>sqZ&)>l0cZN5)!<^MiShObUfUeuOI52IBK z_xP4bD1$*~tKAP4NWhqv14KC&|8!PxQMl_iuZB4}(rwcI=d2A*dVVlVU(lW&jyE@< z$RUE=(qJ{%X_wQH;O_XG9-E6YEI3=z-&PJ#qnk=84ZfvJqx83wdvx`tQs@zhxV{`x z8RYPHxVN~zWNB(?r&hkEL<`jSH6>fU@wyVn+gRIl+!;=|%%6a>`Wb#a9M%&NprK)y z+kbUub}{{>hkWxv#BS0>ghf-z90 z;0ifZz43w)!)rMN{QywZY`a~!Q}|~(V|zQO11~EV#eghM9519H*jE;yUxgSFG zF`z3wQFmTRuuff9quk^TE4dmd8(L6GH{cLfUR1uM373?z2F*F)7yey-B6oyq&h17- zX~U8lh<7nD6#r3ZsCwzFqVUxGtg^(g(pfVT#yxU1vxTYOpHnPC13&J4kT78yGBs@B z-lsXOj1wdBYDQwodA+CVpoYzMbp`=8b0A_mxG^%wwYBXfmddNmg* zB-*s0j4?v*7Ii+T_yq)cWMk8KsJbRKgXdEuGtR1;J4DRm>2K{LuF&mv5f8O7*Kux6 zSjA697E3qxPi_oZZU=R@xgDz~MRIP1m8enU>b-5y&C1EkQ{7d{3Nch$8*>@__Y;09 zH<$a48^q?Uqs85brPYnBZ41SPI3h-;f zm8SuFl_%A|ZBr5iFZO*8OE2^YdDUEeAzUJ%VRInzfSn%^;SQ<+HEiPWq|@__n7hsD z1xywq{SM_9>bXtXNE^2*^Yv3}0O>{Gf~`oo`Ar0XqkXn2eZ}!Lz371u2A(tn0qj2A zq9CU67UfW|XWu~IY!D1wIRbi6aBD<0er~feMV+!q8ON7Ci4|v9tNh%JJ?aOSQ8e>M zWD-}oG=yP*3Yy!=buwWs%N}jW@EG+&uyT-m>-1!TlX&zk;Q zz7o$<;0)(?>d_ph*|U|6h>j)}0}pmvm<`{FlY9%Zd>_;yXig2x04~WB-vl##dx8={ zeP=2s=;kcU&iEQg8BLrBwGaw;-w(llq~s!fsU=4NDsYw}8OPQ@wrJwyC}oRit$m^k zUCLE*DK%G_POoPx=e5Z*a``O0%01A!25{bJ&AmaEMwWq6W{n6|+v|<%os4lck#r+l z>8@VQQ920pMyAq%wm#9okKQ&!G^2a^h^lZldS(zy2xdK?3*8Om@k{&+z%oEVX|rF% zclx?AEE*H)St#HJq2+|jgby6Hp7?Xs?(qLj911}=Sj+onwN_o zY^*@aBq0udPyBONux`A`o$4NP33h5Ey#!%ZSB!C-;c0G~<9q5b&T&;?17bunT0}!M z3wwpO{8c^^pS(2d z8T3{MY5;XOeUu*{Q{&Of3femg$4a|VN)BC3#UxKi#dO~psVvhkxCqHFmTt_E8`9R1 zN=jk618Dfq1H#m1>5jKWZz}<0XRX{O1oOLi8&?Qqdy4A+VfYeWx9H;HNJ`!(Sn0qL zIf$;`4u6x@eiXi#Ug)p3X9xoNDApP-NHAwf<1 zKlE`Cvi9YQSz-nfEvAaYkZ0-NrdgtMrOJM4U#hIur`3$Y`Xl}$DDv{Ig&XPD5~VXv zgj6Wc9CWaEgHZaeSoxH;98%`eCq+t`m$J0t5R@fASOo0z7Q}owN|tp{_Cn5ig{PkV zm6c|9&_!5eT%oRx^idDcYUDLFsZaG#I`W0tiq7L&@dQqb#fS;IpYM+2c{!(0`9mp_ zhCY-gis@%!==eiPq08SPQBR|XaAl~zC%r^n?@9UU!u!%%KAH`dfosHx-Gp+XIpU7m zxefU9M=lp%cs}&ZDkX~oRw-L3%#B@STd6!n%@-5rU16VzW z0F^LLoxNIVz|-;-N+C7u9`SdOS0 zyJ7p`@uupgzIVLwD z49^P8Q$FNiK@0)7vU|7{2nx|(0k zFXZR)Gx=#q?cG^yhp_ui#fHd@Y7;G@83Fho!KvX}98jMMcVKW%=f@)0)=<7bl6@!g z9r)IKbG{KD!Q1%|K7i*E;m630t+1o3J1T-v7FPJ9++6{cq3PN3g(&xw&jo=n?JJ*& zKX#U5SWHisr=xtgd^B7^9p%IDZz}JH^1bq&@Jfywm3r9zwym*v(HPswNodu@njxx8XOGn$I zynM73$}2~kpnU#l6w1FGl~KNM)PnM_M`0;8y;ugnR?|ymvr)cWmWlF}GB}W$u9mUp zzFO8B4S4bx{wj3_@ZI3nPGUmRYF^2@_)(7rm%2JPNq zHfZ+`vzL8+csR;$4i7~6;4m~~ri0~dY>LX+*c>XyzAzP+2cRq|#|k%<9$Sv`@UbUQ z9yvA(W!W*-fuqORMTDt5@p4)0@j1dV|`E_Kh_mx)v-1xtBk8C9A?w;<6-v7e;#K2_~|g4nx7AID1Rwso%ywtEwSH9*(m;AnuqdH z=}eS=l(MEAD95OnxzZ^RXw72jB$WEn@hHuum`k&NDHfnPpfnX_U@3;$+@KV*>#r}x z82Gm>?Th8RQu-+tPaV;Rh13cus#u3gipJc^&C~3k%UfvYVyJd(GU5Tb8=JY*`8* zo)v*U*(caXnW81m-Av{e9|tGWk&-_R4X5;9!i?(P-@>Md%~^9yEcx*s@Lz8t(VvB{ z_88%>OxH!%v+85snJ1X)%Fm0xT#s` z)1M_9wfb3_PS<~uCeo~*q{(#XJ81%S{Z5)jx4xCKDF0jBvwSOM+C6PR6t-uOPU)&J z5nMzeoFZ?K#ct_J1;0s4>E+*1OUCc`*{{E$f_=Z@w{3ovX3{IaNI5j+7u@^pXDLf# zk<2(X#8Wss9msIKQiw&QxbEC7%4ikO@U+t~ZbT!@ zG`Z7kuo|9(C++7|QjBTZ>8XGEq95*M{^?${y8DQ9YlqFXmGa z25mE0PAQUp%*9-<6cVF;pQHo`bhL{yiUxI2CW&(|PNno+2y*qHvoemdJ1eu|JWD2% z6Bpqu%0lq*;W(Hw!G3r?Zec69Z#mKfQNTnkZ*6Ey7vc>;hMARkQG1ynr8ua^KN0+F z$q!*s^z6@JP4!DFXW~1u30#?v8V74VHQ$AE&;Rf93ZO}XHe=z=(HSO4KoJf?pjL0d8=ZUQGB0iNUqAq5$l+`NlB%T0jBCOXPJZ_RKl5ZU9^ zQ72G>u(@Xgz)dA_$~eQci%>wsS}93%gwlgsaNT{krP7ZML@VjkC0dzE*BdG`XhK6} zo+;}hv>>sF7(|h$d6}#YmHxEIr7R|wOG)d*M%4)IGE${ohr8=9@Yij{U1dR#ytD25 z-`tClV9Hz`m<;-w{z#6e%TY=OjgL|?)p2&^4WXH*Hb_^ikTP<+&;e;OyCT~6Vn{6O z)3wd5`GDf*@o!*rU;2wK+|Utpb>ta|9(@=fsULhSMZ+gtj3_Xroq_Nd7wL$m6oVjB ze=#D#wCqd>Hh>h}oh~!)`Im)=iPTPrn5$oW#sV`5<-G%&)Rx=QWNno7V8p<=G(;lp z;b@5ixuTA9Qy2vsU>$H87D_nTXxni3dZ_dv@sX>Kze4-I)&v+RrEq5PZu$>y^uYiF%$_IaIP-Y zf+sJ$2+6%mBp?`n$o{grKu|XDs{J=P!MBkidprZ%@Ht^1{{g?259f-Q^kGv|9?8df zb@umiwBS`%q%%6xTlhqH67s?8{2V?6BaqJ4POL5KLI&2dW)3+jBx`!i%y?&HYl|!P8&w$kS-Z9eJVJ;;!7%H&y-FQtgDL zIvXot2^LcYwh^F|X zkzsTxPBGGq+wuU@xC<}`!c8K9ZtE3U9r=N*8vb8g97dAfC7UPgJ>0G5W#w=odFv`C#!{IIKOQGeY%Ka;Tf(s z&Vk1A@Cz{S$9r9%8Ry{n1aj((tMV>hZTW)S06_#~y{ica^K&G83r6EWTn6`{V@O-x zw%$moonMq+~^POvA6p>uC1{EUm~3@)B=^DeV6u?EhDU=}7DG4BrxM?u#9fAJIhTHmr@I z^XKvNg!8hSUOOk}(#&&mI{kW9oSTHrsLMb=8-c!SL_+~ZzIS1M$O z`eX&z2s(CHPNi{&&2?2Kbz(I6c3)+l(;q>c)oNP7=q zjdVJM`F*npMQ)LtP39upbM3*Oi3jB@W7>rv5Ljy4!fXd1j^yzA;m7NDrTucNB(8I-8kA4cQ|O6p#x+=!QlvfY1Lqa=jVRBzErk5p2y`|0FGe zWpV{F%MUD%$jpI^*s}&*5Gl?8MRt0Y5bFzg>0P%g*v#}qQuLid59FBM#dqTV&dhQHoJ-e^)&@&+e_py4 z-ZfZDUV(&H-`^?6h{m+@dF)7+V7ow|WJ`t3k6sFm=qi~J30T|@1Ns-Jw>#>68i!Oh z_HJt)84MQ#(B307Vk$ihi5Ny>LL#0vq?`xe-vVIbpBp%+NeI$?o(PT@K@)-_QVqk; z!|>*CQPLzOoLU4&v@xWf2j<@8plut>4#*|4nQrcoTZ-e(XVD$A%}Up=8O*d|YN#Le z+yZ~zA>Z>MRP`6xNc#co&`&%MX{re&@4(df?~uED)x`@qaWWKCt$8Lydl$%7n){Ue1bw(&-br!WR!Jpt5SvKinsQY3uR_B(_Pom^aVEdMDm4j*I7I{7`-z-5e`Rq(TdqFOIG6 zTtKdu*)R&IU#^jDf_i7EoaH&c4G791PDQ@TML0+2;DqVVm0_}uIGP1zo`)}T%pBjk zr1)}JDl(VL0X$_dl^4;R0(q-A@BA=&y%X$JD5lo1+=QO^I1*nsYf0FSbXma z>5yS&bHzBrBDnorcV7n<*6#oY7#--v5`Q|kMmQ-s$zV3Q7q6WYV^@;U#h-I{tz&h%PRaZR*v0`6%C)O@jf=7B>ig7c%)*`9!cx z-Jv4s1WR0uw>K&01JD?!$4S_8yr(<~t~XM43)(`Whp+jCs#_Mwb9u^|hsE;wTzLic zoGX`N5EIC?8VZX`x5I;J@f>uibw7iSsup44M$MI7+9B)DwdVjn9)_K@AJpS6xRRFK zM>u5LZ%>lc>dx{o-Z0h^ihxpf;A}xKh+e#D$~lDPh?gPUf;uSF7dPqac)8kJ=V(r> z6el5@%PAzu)+5GlIug5{=GZX?r$S!@Zz9zS#;pC!>(4flw*Y? z4~g&0IKXz$@n$2O@pJqH#0q^D5k>y=8F>!YDu>JCgTqZc2YD}AqNIJm0*q=YcUM1X zB}25^(i9^;g_4>g21$?I5yAA;GZ8)bG1PK*L^KV+zp2^oh}XOntRn}!VsGI?VIg9( zp5TWfB-{>AumC3-K8o^AhlLeFGfvlA$gOcFweC(nyEFdWNa7bLUYgvYwFG|j*!TvTAUET)i`C_yT|DI+LX?I7<(@dG?hBBWJS6fQ?#VUKgMHDoJ?rgRC zQTkJ`e}C9ePW28kR!)hS3PO7j;XCd^C(#929}2nd7-E-U$Iq+aE@9ncLxj7}e`WdNVyIDBSKCWhn(w01^4Yyq(;cG zln^10^J+GdHO&74*>n1fhX$EmtHq7%L6lqb5G!MQWzCla&IzYdRybrCm}t{PKh4w z#ip^oEw(oId9rU5gsyWjQB?I$^k-w3#iVv=Apey&4nD`=!!C{;h6=r+lV3M1KL_q9 zE|RuSF@{nPot)K~Z5DrS7-Qm6V4c`6uykiTp#b>;ogU^9-h8|o&qFagLp%6~oP|67 zeY;gP>E(a&;;3_Wdi0yUgSzrJyBlGuKrl_8_(MBm0ZI+WIGZA&YUQSDt1k*c(Du z=n4mc(R>=*N;KT))-a|%EM(|exA^2Z)bIT~ zp-O<>WHTsump}_;{pd)$}bY69=8mrykesO=;tIc9WWS&pw_nylvOpL0gW4t2YVfg&Bf^ z)PSt_Z*fmD`XZ~Z-M6@_ zX^mEYe%Edg)UMa~VsA#94@9ag@Mt=ui$>=^7#Ph-cr{oSTPVq*m|wo3gCg;NAnsFJQ&{O zQOWbOa%Q^y)`e*gd!bU4+fe6J&ClC^M8K`kvtWV}=s<4-A`xorOFYt_0pX*?Il_JD ztUuxBgVv1Z+(GLco?3Qg0KIW7#?Oy=o!V$tjLtyIp0jVKu@~)|slg@tw`$s1`!hbS z35covqD62+4x0_!)m-2VDCzqK9T+MpT77uV9wZpt{%0Yhccg>+onh*uQ+AOzO+4$u z=0hH%daU}fQ}#|HJ^L6ohf`?bM~IE`GM|Qn_#}dvc;q{@6z3=8G_AjNgCoUoy}Sa# z$W#?Nlz11X$q*b@dd4oO2g>c`jF@;83Kf9uJOGeN;-7-%ryL3ekM0NGv(KV+07~K| z8t0GQ^ISV!V|8$)y*;l%+R1&~UZ7qpwomuXKU#bo`u4A&2a5*tkiq7W*-514?wEC$ zdKqxW$7eIXA4n2ER-KHdjy~If>HL$YIK$O(rS>EQj5%xGk(VDvkG{3)$z5z8N_!65 zGu1fY9d&$0vP7&ebUzT28$2vK6@+nI{Ub#bwD^mXYRFx zYd29~NyRtwEUXb3d85vPT|<_dEoe+Yk^OsKjo)M67#6k*ZJ;%s?Va#w zYO>5eU#;0|?qU@)?gAne4(0MVEb_fvA9myiyZuza;+i>XrwhOk zdwaF$8T&**oS@Do=Wcr!qILGWUS%URcKd-0`AXP=ci#YkkKkVND5`s#-A}B`P$5CZ zyJ%a6Eu1bt3u!v*XUU=7SdR^;4qa`x`fy_-m_zmhpvHo+xB|H<7FeUJI%SQ0ub>WF zVYl!a!{P@LFE$2LvIGXbHQYF;{09U2u+O7-qMqq?Os=$UEV>Z-XP_dqSt;HT9X5AL z&b;g>b&}hTTtq{b+TYW73O%%RAQ;)e$Hj9s_~Rs(j!|i>VjSOvhGn7si*9V5^&HrP zl{nh}fw#YmKVIdU)|+PSpYBMt1tweaK*D`GHMMY&eY&8&n{Q9^tWrILvG63c ze<&R8rl#9F>Qhy?lK`gM-X2cZGVBrRt_=GOfgYsU)$Z&CMyB?i2n2=#L|YCP?-|_i z$u9WbJz9l+qnV5#obLJS=4)N?o$C<=x<-a%wJj4PJlUP{#^U_AKE}SCr<64NewsMW zUPQ|mMHFeBF*0c9J}rpo93hCGg#l^-W($Vsx{rGvk|qDA=!le)Vh_+EeicAy1MN*H zZiKx(Jw4n$ojMM;XV6WIy*?1DBV&NQBfZ<-KAw*Cv#07usyMcqQQkhJ zEqT2k!Yy754)muU&j$x+@LU6EI2hewK%;DgDf@Ls9+TM8SfndZ!E=Aq7tG|mzV>W2 zqK~}`Pc^;Kx3RtP>LH2tYNuy;z(KPFyz<8g(Hn7#b` zi`w!uLBFe6C;kCc@IyXjfTG7Ei z0#n-Bez7%st=VITNr2bgLPR;b!cW1G7VU4qjXySfdn11}3e5^S-_&%`4 zT5w)4s|MB4%KiyY-CEl3Q*kr<5e+h+Lka?MxG)*$g-W3ZB*Agel)%a2@ej2&*%3Ku z_IfA7Df?&_MI6@kQU^D;pW=<~nP+ktT$ke4!e#h+Q~O(VCdOXTj*W&6+g$iN^1b!t zMne9+4ZBnaI>Ok?;NS;lEJfJNefvhyQo z0@^{Zy5@h5(;NL?#OYOkmF?BMaiTY>ECsW$cN$RmS`Z?@BBpFSl{@Ss_2bTf??)Kn z3J9E96yG;mI9pM_7S3_>RdeTfuhiR#6Dz!ePJgHYYo~pClA<4V1~B(X3O)?|p;p85 z&7I9K-B3G5(m@B%*?AREoHl5H_fBcZG{oP2l4dt@?)SD6{Q6NG?B8lC z*?N=8EEkx;6ndqxbBte4taWE?m}oQYY3z)phK-%0#8GE@P;iX1(~cM2Fbl^x=a41F zIhsoTkjCM=M9+7N&LC89H=M9M-G3xaGLAR{hNK1DC$?`eD|GIW)J{_y8UQmC=V4kG z!8)-C?8^qK9%hRQTCyJF1?Y=Ud#yoVF4gG3R(>rZJL0fAQob;V4Ud8A#epCD5XQY* zfOu5l&m7!dHFEt-xb({o7vp{ExJUeC&4hT5Kr}X^N$=@rjOeJ^4JU8?0h=>dR& z8=Wg@#X9FKnzX@rs_=7z&ZbAc4>7>}!LVioLyl!TC;16CM0vctfV}OQARNpbZ?D2U}P{w!BI-pKnJ63E>jWS|eMi zWsclfNFGkEHFCVVDhKvPjnMluLVp;Wj2S)p!@9Q_#Qrwm6m_Gh?j9;ngH+#Jo+oJf zWbJS`3UHd*)>IT5r zUV&o+8boFcZ%WA-a+ab0`DW;CphxZ0BtvdSr_$vVame{5Otle7Yt!Xc`qAebGf~mC zBot%#K}ZmNHy--70+ zB3ICdlc8GAn=H>F%VemzMxAd#={h(Y-AMx8|J@9^V?C6s+4BE1%5_%G)cIKbV@oID zT>szjg9ZOb03oWgl;Q|9N0%%@*{B5JD9te?b3m$NOBjl=RY?}^G%W!l)ZDCO0?NT9 zY2ZjZm*B)RwJ8~jvTex#lWlaEC$5V+_e}8Pjk0ophnHzi*r%- zD9%QiR1Epo+_QKh%3j65Q<@5<7mvjMW)(AtY)&yil;+;WXqPFs7{E!BR1C(&+@~0N zBy->5R=5*d3@ntnUopf`bN^zH7}LyR)~o@=tXUU}S+j;0vu2GbX3ZK|%$k*Yh&5}} zAvRj04*_^;PCGOW<(Ps)tSw^?rJ@{nXfVq0hkBu$aEOh^#6#@GlMdm<=JZ4C#Tkbh zLVoZsjYAnwiaY*+rEG+(rO_yDrBNuQQYT7#DQlKo3L(v`l!l>nlmgIe4liwhGNKes z^tY830HbP-EcHVfRVtu#l@y?CSi;&n`4B9-<|&69C^HYSil!b4MLCUm-e(H!fG>5FIt9jMiE;XGmG+3<`!XPm}eES9?veCfikZM6X9T!eN<_Jo$g;lV=I7MhHD zdiJ-l0HZr>OJ?Ml~;i!h1yH-{zX#qQS5hSA5F8V4RRT_A8S>VgOp?{u*?6$c-0 zNv-!ffLVQrz-PE0OOc(dQ)yOb>uUNu!Mawz^f&~e7W8lhxMTP_8fjyKb%J5}@g_{0 zOAivP;j}3M5=heoYm#P|F)$75Jm5aM^T*&%QieZ0A9wH;C=48Ki}pXSM#(2V^D~Zv z3_~DhhJ*4r>qvd>@fda^_#=2@CdOGu(Y99Br|7p>>n=Taydi6o_SLn^Xw$Q?*2%h- z$6Zm>qovhGAGHiK(Y=<|&6L>Ex=A~;G(WG6Vl!a72EiF~IdmB{IGLkZ(}sGEX1co) zQF`wD7-*!A{t@Cw8xKkI)&4uBUSeUnRUZobG67@rB7nKS;>76)$0%l9Zo|82BT4i1 z^Rz@YloSrBp)~<73(HKnTD3{~OeowW>BFE`*daEB!gwU~@5=z(I-;3kYESd_bZx5? zuXb4{rHS}~F3iZmRQ@DX)dcYF3sB|U=T;yTwbX_-Wl3$!?%)kwrk{r149fmhfKfiX z0(>1pR>bRPoW@*7GPj>_b@vMCq4xe52*5v&i$rjIy)6mDp(VT0D6{R6gp#yGTT;2vB5wf{Cfl8W?5KL~{fg7jg?lTrpo z=m%jBKsY5pp*_b9q;10;t=Syq>&Ki1qu18MTcp1bV4|SelAdOzNt>t}EcR3oEynWqY{+GR@V3}lOCpUpsn8aTVrD}l~2lpE+AZ%9406rHisjq!lRbPRNM(2qO? zfJL09#iUoqN$tIkOyfB*8{F+482!p&<#~%N+br#a$85-Ev*gr(u9}$GdYrV#IQ7&b z5EE-OC4JsNp)bcueQC^CX*Rt!M%qj{W27ninWq4SLnxpC_>kQRvzo{`MjC7wdkP{l z_J4I3#oOGk21~Cs^w7IV7F+HHIK$`pbU5~|)A(Pu(Waf6OWof>HuuD#QY;-9EHzZs zA<_WB>^7fbxl$ZJuOtM{Sr3P_;L2 zI#x%MzJ4vmF{h?eULarr+6eCJE44-Yf#vYFKdP^kDo#3;P2Il_h@=<$NIlehiBfOD zD+JAA2IW@5A?%NC+%1n&L6YQ-tpBE3dPS|fOV@So)~6;@)sJxEO-_{dsuAs^K*6iS z$YPkAMBy_y93{fsuntoDD_*c_(^Fj-|L@dd`(euj{RkWGW|w3$jL4WjcXsZ4wM7T% zEuN10J4aEfzcaNE7ky!LrW-O&jYM~lEwzt7^sQ!RPjB0ofVyDJb72@*$s4&PY%xzT zF5QT;0$ZHUnw*Ie zZjO~+;k|yTB^^-dVb+~? zsu>Fn=TURk&H)P(=x*y({33k#s5t2;6*Q6DRN7d2mmbAPWt1EvRX(*xr|OK>-$d+L zIE{o`?U9eWgJIqucO_H1gj@gWk^J>s5rdQ50p#;-w77^n!NE~G&1ti4geEFR^27

w;wniijeUeziC9&Bj{r@(!C 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%0Da-?y#Q8zsIS%g*~) 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 delta 243407 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 CK`D^{ From e1a94d0ff5932ad23b930e4ed75a5a7a889632fa Mon Sep 17 00:00:00 2001 From: xathei Date: Mon, 18 Mar 2019 13:20:08 +0000 Subject: [PATCH 0232/1002] v1.0.0.4 --- addons/Debuffed/Debuffed.lua | 67 ++++++++++++++++++++++++++---------- addons/Debuffed/README.md | 5 +++ 2 files changed, 54 insertions(+), 18 deletions(-) diff --git a/addons/Debuffed/Debuffed.lua b/addons/Debuffed/Debuffed.lua index 54ea479188..d3c177e599 100644 --- a/addons/Debuffed/Debuffed.lua +++ b/addons/Debuffed/Debuffed.lua @@ -1,5 +1,5 @@ --[[ -Copyright © 2018, Auk +Copyright © 2019, Xathe All rights reserved. Redistribution and use in source and binary forms, with or without @@ -17,7 +17,7 @@ modification, are permitted provided that the following conditions are met: 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 Auk BE LIABLE FOR ANY +DISCLAIMED. IN NO EVENT SHALL Xathe 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 @@ -27,8 +27,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] _addon.name = 'Debuffed' -_addon.author = 'Auk' -_addon.version = '1.0.0.3' +_addon.author = 'Xathe (Asura)' +_addon.version = '1.0.0.4' _addon.commands = {'dbf','debuffed'} config = require('config') @@ -41,8 +41,18 @@ defaults = {} defaults.interval = .1 defaults.mode = 'blacklist' defaults.timers = true +defaults.hide_below_zero = false defaults.whitelist = S{} defaults.blacklist = S{} +defaults.colors = {} +defaults.colors.player = {} +defaults.colors.player.red = 255 +defaults.colors.player.green = 255 +defaults.colors.player.blue = 255 +defaults.colors.others = {} +defaults.colors.others.red = 255 +defaults.colors.others.green = 255 +defaults.colors.others.blue = 0 settings = config.load(defaults) box = texts.new('${current_string}', settings) @@ -68,26 +78,29 @@ sort_commands = T{ ['-'] = 'remove' } +player_id = 0 frame_time = 0 debuffed_mobs = {} function update_box() local lines = L{} local target = windower.ffxi.get_mob_by_target('t') - + if target and target.valid_target and (target.claim_id ~= 0 or target.spawn_type == 16) then local data = debuffed_mobs[target.id] if data then for effect, spell in pairs(data) do - local name = res.spells[spell[1]].name - local remains = math.max(0, spell[2] - os.clock()) + local name = res.spells[spell.id].name + local remains = math.max(0, spell.timer - os.clock()) if settings.mode == 'whitelist' and settings.whitelist:contains(name) or settings.mode == 'blacklist' and not settings.blacklist:contains(name) then if settings.timers and remains > 0 then - lines:append("%s: %.0f":format(name, remains)) + lines:append('\\cs(%s)%s: %.0f\\cr':format(get_color(spell.actor), name, remains)) + elseif remains < 0 and settings.hide_below_zero then + debuffed_mobs[target.id][effect] = nil else - lines:append(name) + lines:append('\\cs(%s)%s\\cr':format(get_color(spell.actor), name)) end end end @@ -101,13 +114,21 @@ function update_box() end end +function get_color(actor) + if actor == player_id then + return '%s,%s,%s':format(settings.colors.player.red, settings.colors.player.green, settings.colors.player.blue) + else + return '%s,%s,%s':format(settings.colors.others.red, settings.colors.others.green, settings.colors.others.blue) + end +end + function handle_overwrites(target, new, t) if not debuffed_mobs[target] then return true end for effect, spell in pairs(debuffed_mobs[target]) do - local old = res.spells[spell[1]].overwrites or {} + local old = res.spells[spell.id].overwrites or {} -- Check if there isn't a higher priority debuff active if table.length(old) > 0 then @@ -121,7 +142,7 @@ function handle_overwrites(target, new, t) -- Check if a lower priority debuff is being overwritten if table.length(t) > 0 then for _,v in ipairs(t) do - if spell[1] == v then + if spell.id == v then debuffed_mobs[target][effect] = nil end end @@ -130,7 +151,7 @@ function handle_overwrites(target, new, t) return true end -function apply_debuff(target, effect, spell) +function apply_debuff(target, effect, spell, actor) if not debuffed_mobs[target] then debuffed_mobs[target] = {} end @@ -142,7 +163,7 @@ function apply_debuff(target, effect, spell) end -- Create timer - debuffed_mobs[target][effect] = {spell, os.clock() + res.spells[spell].duration or 0} + debuffed_mobs[target][effect] = {id=spell, timer=(os.clock() + (res.spells[spell].duration or 0)), actor=actor} end function handle_shot(target) @@ -150,9 +171,9 @@ function handle_shot(target) return true end - local current = debuffed_mobs[target][134][1] + local current = debuffed_mobs[target][134].id if current < 26 then - debuffed_mobs[target][134][1] = current + 1 + debuffed_mobs[target][134].id = current + 1 end end @@ -169,9 +190,10 @@ function inc_action(act) local target = act.targets[1].id local spell = act.param local effect = res.spells[spell].status + local actor = act.actor_id if effect then - apply_debuff(target, effect, spell) + apply_debuff(target, effect, spell, actor) end -- Non-damaging spells @@ -179,9 +201,10 @@ function inc_action(act) local target = act.targets[1].id local effect = act.targets[1].actions[1].param local spell = act.param + local actor = act.actor_id if res.spells[spell].status and res.spells[spell].status == effect then - apply_debuff(target, effect, spell) + apply_debuff(target, effect, spell, actor) end end end @@ -193,13 +216,17 @@ function inc_action_message(arr) debuffed_mobs[arr.target_id] = nil -- Debuff expired - elseif S{204,206}:contains(arr.message_id) then + elseif S{64,204,206,350,531}:contains(arr.message_id) then if debuffed_mobs[arr.target_id] then debuffed_mobs[arr.target_id][arr.param_1] = nil end end end +windower.register_event('login','load', function() + player_id = (windower.ffxi.get_player() or {}).id +end) + windower.register_event('logout','zone change', function() debuffed_mobs = {} end) @@ -247,6 +274,10 @@ windower.register_event('addon command', function(command1, command2, ...) settings.interval = tonumber(command2) or .1 log('Refresh interval set to %s seconds.':format(settings.interval)) settings:save() + elseif command1 == 'h' or command1 == 'hide' then + settings.hide_below_zero = not settings.hide_below_zero + log('Timers that reach 0 will be %s.':format(settings.hide_below_zero and 'hidden' or 'shown')) + settings:save() elseif list_commands:containskey(command1) then if sort_commands:containskey(command2) then local spell = res.spells:with('name', windower.wc_match-{name}) diff --git a/addons/Debuffed/README.md b/addons/Debuffed/README.md index b9b6900870..ae986b15dc 100644 --- a/addons/Debuffed/README.md +++ b/addons/Debuffed/README.md @@ -16,6 +16,10 @@ This toggles the display of timers for debuffs. This allows you to adjust the refresh interval for the textbox. It will be updated every \ number of seconds. +`//debuffed hide` + +This toggles the automatic removal of effects when their timer reaches zero. + `//debuffed blacklist|whitelist add|remove ` This adds or removes the spell \ to the specified filter. @@ -27,6 +31,7 @@ The following abbreviations are available for addon commands: * `mode` to `m` * `timers` to `t` * `interval` to `i` +* `hide` to `h` * `blacklist` to `b` or `blist` or `black` * `whitelist` to `w` or `wlist` or `white` * `add` to `a` or `+` From 30662e15d348ed89ecbde6d64ec6e81995f2654f Mon Sep 17 00:00:00 2001 From: Noah Jorgensen Date: Wed, 20 Mar 2019 21:33:07 -0700 Subject: [PATCH 0233/1002] areas.Cities +Rabao --- addons/GearSwap/libs/Mote-Mappings.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/GearSwap/libs/Mote-Mappings.lua b/addons/GearSwap/libs/Mote-Mappings.lua index c1b681cd8e..d2831d8c38 100644 --- a/addons/GearSwap/libs/Mote-Mappings.lua +++ b/addons/GearSwap/libs/Mote-Mappings.lua @@ -241,7 +241,8 @@ areas.Cities = S{ "Norg", "Eastern Adoulin", "Western Adoulin", - "Kazham" + "Kazham", + "Rabao" } -- Adoulin areas, where Ionis will grant special stat bonuses. areas.Adoulin = S{ From 84ab8e6579bd6e5615cd4e96d7b4981a12970ba0 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Thu, 18 Apr 2019 00:41:05 +0200 Subject: [PATCH 0234/1002] Refactoring TreasurePool Refactored to use packets instead of memory --- addons/TreasurePool/TreasurePool.lua | 176 +++++++++++++-------------- 1 file changed, 87 insertions(+), 89 deletions(-) diff --git a/addons/TreasurePool/TreasurePool.lua b/addons/TreasurePool/TreasurePool.lua index 780ad75c65..2b5570ed14 100644 --- a/addons/TreasurePool/TreasurePool.lua +++ b/addons/TreasurePool/TreasurePool.lua @@ -1,4 +1,4 @@ ---[[Copyright © 2017, Kenshi +--[[Copyright © 2019, Kenshi All rights reserved. Redistribution and use in source and binary forms, with or without @@ -26,7 +26,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.]] _addon.name = 'TreasurePool' _addon.author = 'Kenshi' -_addon.version = '1.0' +_addon.version = '2.0' require('luau') texts = require('texts') @@ -54,115 +54,113 @@ defaults.display.text.alpha = 255 defaults.display.text.size = 12 settings = config.load(defaults) +box = texts.new('${current_string}', settings) -treasure_text = texts.new(settings.display, settings) +local items = T{} -treasure_text:appendline('Treasure Pool:') -for i = 0, 9 do - treasure_text:appendline(i .. ': ${index' .. i .. '|-}${lotting' .. i .. '}') -end - -goals = {} - -lotter = {} - -lot = {} +windower.register_event('load', function() + local treasure = windower.ffxi.get_items().treasure + for i = 0, 9 do + if treasure[i] and treasure[i].item_id then + local item = res.items[treasure[i].item_id] and res.items[treasure[i].item_id].en or treasure[i].item_id + local pos = treasure[i].timestamp + i + table.insert(items, {position = pos, index = i, name = item, timestamp = treasure[i].timestamp, + temp = treasure[i].timestamp + 300, lotter = nil, lot = nil}) + end + end + table.sort(items, function(a,b) return a and b and a.position < b.position end) +end) windower.register_event('incoming chunk', function(id, data) - if id == 0x0D2 then - - local packet = packets.parse('incoming', data) - + local packet = packets.parse('incoming', data) -- Ignore gil drop if packet.Item == 0xFFFF then return end - - local time_check = packet.Timestamp + 300 - local diff = os.difftime(time_check, os.time()) - + -- Double packet and leaving pt fix + for key, value in pairs(items) do + if value and value.index == packet.Index then + if value.timestamp == packet.Timestamp then + return + else + table.remove(items, key) + end + end + end + -- Ignore item 0 packets + if packet.Item == 0 then + return + end + -- Create table + local time_check = packet.Timestamp + 300 + local diff = os.difftime(time_check, os.time()) + local item = res.items[packet.Item] and res.items[packet.Item].en or packet.Item + local pos = packet.Timestamp + packet.Index if diff <= 300 then - goals[packet.Index] = packet.Timestamp + 300 - lotter[packet.Index] = ' ' + table.insert(items, {position = pos, index = packet.Index, name = item, timestamp = packet.Timestamp, + temp = packet.Timestamp + 300, lotter = nil, lot = nil}) else - goals[packet.Index] = os.time() + 300 - lotter[packet.Index] = ' ' + table.insert(items, {position = pos, index = packet.Index, name = item, timestamp = packet.Timestamp, + temp = os.time() + 300, lotter = nil, lot = nil}) end - + -- Sort table + table.sort(items, function(a,b) return a and b and a.position < b.position end) end - if id == 0x0D3 then - - local lotpacket = packets.parse('incoming', data) - - -- Ignore drop to a player or floored - if lotpacket.Drop ~= 0 then - return - else - lotter[lotpacket.Index] = lotpacket['Highest Lotter Name'] - lot[lotpacket.Index] = lotpacket['Highest Lot'] + local packet = packets.parse('incoming', data) + for key, value in pairs(items) do + if value.index == packet.Index then + if packet.Drop ~= 0 then + table.remove(items, key) + table.sort(items, function(a,b) return a and b and a.position < b.position end) + else + value.lotter = packet['Highest Lotter Name'] + value.lot = packet['Highest Lot'] + end + end end - end - - -- Check to hide text box if zoning with treasure up - if id == 0xB then - zoning_bool = true - elseif id == 0xA and zoning_bool then - zoning_bool = false + if id == 0xB then + items = T{} end - end) -windower.register_event('prerender', function() - local treasure = T(windower.ffxi.get_items().treasure) - local remove = S{} - local info = S{} - if zoning_bool or treasure:empty() then - treasure_text:update(info) - treasure_text:hide() +function Update() + local current_string = '' + if items:empty() then + box:hide() return end - for i = 0, 9 do - if treasure[i] and treasure[i].item_id then - if goals[i] then - local diff = os.difftime(goals[i], os.time()) - local timer = {} - timer[i] = os.date('!%M:%S', diff) - if timer[i] then - if diff < 0 then -- stop the timer when 00:00 so it don't show 59:59 for a brief moment - remove:add('index' .. i) - remove:add('lotting' .. i) - else - info['index' .. i] = ( - diff < 60 and - '\\cs(255,0,0)' .. res.items[treasure[i].item_id].name .. ' → ' .. timer[i] - or diff > 180 and - '\\cs(0,255,0)' .. res.items[treasure[i].item_id].name .. ' → ' .. timer[i] - or - '\\cs(255,128,0)' .. res.items[treasure[i].item_id].name .. ' → ' .. timer[i]) .. '\\cr' - end - end - else -- show item name in case the addon is loaded with items on tresure box - info['index' .. i] = res.items[treasure[i].item_id].name - end - if lotter[i] and lot[i] then - if lotter[i] == ' ' then - remove:add('lotting' .. i) - elseif lot[i] > 0 then - info['lotting' .. i] = ( - '\\cs(0,255,255)' .. (' | ' .. lotter[i] .. ': ' .. lot[i])) .. '\\cr' + current_string = 'Treasure Pool:' + for key, value in pairs(items) do + if value and value.temp then + local diff = os.difftime(value.temp, os.time()) + local timer = os.date('!%M:%S', diff) + if diff >= 0 then + current_string = current_string..'\n['..key..']' + current_string = ( + diff < 60 and + current_string..'\\cs(255,0,0)['..value.index..'] '..value.name..' → '..timer + or diff > 180 and + current_string..'\\cs(0,255,0)['..value.index..'] '..value.name..' → '..timer + or + current_string..'\\cs(255,128,0)['..value.index..'] '..value.name..' → '..timer)..'\\cr' + if value.lotter and value.lot and value.lot > 0 then + current_string = current_string..' | ' + current_string = (current_string..'\\cs(0,255,255)'..value.lotter..': '..value.lot)..'\\cr' end + else + table.remove(items, key) end - treasure_text:show() - else - remove:add('index' .. i) - remove:add('lotting' .. i) + box:show() end - treasure_text:update(info) - end - for entry in remove:it() do - treasure_text[entry] = nil end -end) + box.current_string = current_string +end + +Update:loop(0.5) + +windower.register_event('logout','zone change', function() + items = T{} +end) \ No newline at end of file From 615227bfa011341539d1da58dae8fe3a03406eea Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Thu, 18 Apr 2019 18:29:40 +0200 Subject: [PATCH 0235/1002] fixed formatting fixed formatting --- addons/TreasurePool/TreasurePool.lua | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/addons/TreasurePool/TreasurePool.lua b/addons/TreasurePool/TreasurePool.lua index 2b5570ed14..af28f98e2e 100644 --- a/addons/TreasurePool/TreasurePool.lua +++ b/addons/TreasurePool/TreasurePool.lua @@ -68,7 +68,7 @@ windower.register_event('load', function() temp = treasure[i].timestamp + 300, lotter = nil, lot = nil}) end end - table.sort(items, function(a,b) return a and b and a.position < b.position end) + table.sort(items, function(a,b) return a and b and a.position < b.position end) end) windower.register_event('incoming chunk', function(id, data) @@ -83,16 +83,16 @@ windower.register_event('incoming chunk', function(id, data) if value and value.index == packet.Index then if value.timestamp == packet.Timestamp then return - else - table.remove(items, key) + else + table.remove(items, key) end end end - -- Ignore item 0 packets - if packet.Item == 0 then - return - end - -- Create table + -- Ignore item 0 packets + if packet.Item == 0 then + return + end + -- Create table local time_check = packet.Timestamp + 300 local diff = os.difftime(time_check, os.time()) local item = res.items[packet.Item] and res.items[packet.Item].en or packet.Item @@ -104,8 +104,8 @@ windower.register_event('incoming chunk', function(id, data) table.insert(items, {position = pos, index = packet.Index, name = item, timestamp = packet.Timestamp, temp = os.time() + 300, lotter = nil, lot = nil}) end - -- Sort table - table.sort(items, function(a,b) return a and b and a.position < b.position end) + -- Sort table + table.sort(items, function(a,b) return a and b and a.position < b.position end) end if id == 0x0D3 then local packet = packets.parse('incoming', data) @@ -113,7 +113,7 @@ windower.register_event('incoming chunk', function(id, data) if value.index == packet.Index then if packet.Drop ~= 0 then table.remove(items, key) - table.sort(items, function(a,b) return a and b and a.position < b.position end) + table.sort(items, function(a,b) return a and b and a.position < b.position end) else value.lotter = packet['Highest Lotter Name'] value.lot = packet['Highest Lot'] @@ -121,7 +121,7 @@ windower.register_event('incoming chunk', function(id, data) end end end - if id == 0xB then + if id == 0xB then items = T{} end end) From 770808d3b5533fa7e29b4f6fc7af9d797d70df93 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Mon, 22 Apr 2019 19:02:57 +0200 Subject: [PATCH 0236/1002] Update TreasurePool.lua --- addons/TreasurePool/TreasurePool.lua | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/addons/TreasurePool/TreasurePool.lua b/addons/TreasurePool/TreasurePool.lua index af28f98e2e..65529ad101 100644 --- a/addons/TreasurePool/TreasurePool.lua +++ b/addons/TreasurePool/TreasurePool.lua @@ -126,13 +126,12 @@ windower.register_event('incoming chunk', function(id, data) end end) -function Update() - local current_string = '' +windower.register_event('prerender', function() if items:empty() then box:hide() return end - current_string = 'Treasure Pool:' + local current_string = 'Treasure Pool:' for key, value in pairs(items) do if value and value.temp then local diff = os.difftime(value.temp, os.time()) @@ -141,11 +140,11 @@ function Update() current_string = current_string..'\n['..key..']' current_string = ( diff < 60 and - current_string..'\\cs(255,0,0)['..value.index..'] '..value.name..' → '..timer + current_string..'\\cs(255,0,0) '..value.name..' → '..timer or diff > 180 and - current_string..'\\cs(0,255,0)['..value.index..'] '..value.name..' → '..timer + current_string..'\\cs(0,255,0) '..value.name..' → '..timer or - current_string..'\\cs(255,128,0)['..value.index..'] '..value.name..' → '..timer)..'\\cr' + current_string..'\\cs(255,128,0) '..value.name..' → '..timer)..'\\cr' if value.lotter and value.lot and value.lot > 0 then current_string = current_string..' | ' current_string = (current_string..'\\cs(0,255,255)'..value.lotter..': '..value.lot)..'\\cr' @@ -157,10 +156,8 @@ function Update() end end box.current_string = current_string -end - -Update:loop(0.5) +end) -windower.register_event('logout','zone change', function() +windower.register_event('logout', function() items = T{} -end) \ No newline at end of file +end) From b623a5f35f7670fffe965923245ea785b7f08666 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Sun, 12 May 2019 18:39:48 -0400 Subject: [PATCH 0237/1002] Umbra and Rad SC / Fixes Scoreboard --- addons/libs/actions.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/actions.lua b/addons/libs/actions.lua index 344434400d..1dbffddc90 100644 --- a/addons/libs/actions.lua +++ b/addons/libs/actions.lua @@ -385,13 +385,13 @@ expandable[{1, 2, 67, 77, 110,157, 292,293,294,295,296,297, 298,299,300,301,302,317, 352,353,379,419,522,576, - 577,648,650,732}] = {subject="target", verb="loses", objects={"HP"} } + 577,648,650,732,767,768}] = {subject="target", verb="loses", objects={"HP"} } expandable[{122,167,383}] = {subject="actor", verb="gains", objects={"HP"} } expandable[{7, 24, 102,103,238,263, 306,318,357,367,373,382,384, 385,386,387,388,389,390,391, 392,393,394,395,396,397,398, - 539,587,606,651}] = {subject="target", verb="gains", objects={"HP"} } + 539,587,606,651,769,770}] = {subject="target", verb="gains", objects={"HP"} } expandable[{25, 224,276,358,451,588}] = {subject="target", verb="gains", objects={"MP"} } expandable[{161,187,227,274,281}] = {subject="actor", verb="steals", objects={"HP"} } expandable[{165,226,454,652}] = {subject="actor", verb="steals", objects={"TP"} } From 4865d26e6787952123dcb8fa9e7335fb7efe8cee Mon Sep 17 00:00:00 2001 From: Chiaia Date: Sun, 12 May 2019 18:40:47 -0400 Subject: [PATCH 0238/1002] Umbra and Rad SC / Fixes Scoreboard --- addons/libs/actions.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/actions.lua b/addons/libs/actions.lua index 344434400d..1dbffddc90 100644 --- a/addons/libs/actions.lua +++ b/addons/libs/actions.lua @@ -385,13 +385,13 @@ expandable[{1, 2, 67, 77, 110,157, 292,293,294,295,296,297, 298,299,300,301,302,317, 352,353,379,419,522,576, - 577,648,650,732}] = {subject="target", verb="loses", objects={"HP"} } + 577,648,650,732,767,768}] = {subject="target", verb="loses", objects={"HP"} } expandable[{122,167,383}] = {subject="actor", verb="gains", objects={"HP"} } expandable[{7, 24, 102,103,238,263, 306,318,357,367,373,382,384, 385,386,387,388,389,390,391, 392,393,394,395,396,397,398, - 539,587,606,651}] = {subject="target", verb="gains", objects={"HP"} } + 539,587,606,651,769,770}] = {subject="target", verb="gains", objects={"HP"} } expandable[{25, 224,276,358,451,588}] = {subject="target", verb="gains", objects={"MP"} } expandable[{161,187,227,274,281}] = {subject="actor", verb="steals", objects={"HP"} } expandable[{165,226,454,652}] = {subject="actor", verb="steals", objects={"TP"} } From d5ed299746818f047be37fb220e05cb41aeb38e8 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Tue, 14 May 2019 04:02:58 -0400 Subject: [PATCH 0239/1002] Slips 28 and Missing other tiems All of Slip 28 Added Missing stuff on Slip 22 from Sep 2018 to May 2019 Updated added. (August stuff was added already.) Missing stuff on Slip 23 from Aug 2018 to May 2019 added. --- addons/libs/slips.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 841aa5247e..67ab6956d5 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -11,7 +11,7 @@ _libs.slips = slips slips.default_storages = {'inventory', 'safe', 'storage', 'locker', 'satchel', 'sack', 'case', 'wardrobe', 'safe2'} -slips.storages = L{29312, 29313, 29314, 29315, 29316, 29317, 29318, 29319, 29320, 29321, 29322, 29323, 29324, 29325, 29326, 29327, 29328, 29329, 29330, 29331, 29332, 29333, 29334, 29335, 29336, 29337, 29338,} +slips.storages = L{29312, 29313, 29314, 29315, 29316, 29317, 29318, 29319, 29320, 29321, 29322, 29323, 29324, 29325, 29326, 29327, 29328, 29329, 29330, 29331, 29332, 29333, 29334, 29335, 29336, 29337, 29338, 29339} slips.items = { [slips.storages[1]] = L{16084, 14546, 14961, 15625, 15711, 16085, 14547, 14962, 15626, 15712, 16086, 14548, 14963, 15627, 15713, 16087, 14549, 14964, 15628, 15714, 16088, 14550, 14965, 15629, 15715, 16089, 14551, 14966, 15630, 15716, 16090, 14552, 14967, 15631, 15717, 16091, 14553, 14968, 15632, 15718, 16092, 14554, 14969, 15633, 15719, 16093, 14555, 14970, 15634, 15720, 16094, 14556, 14971, 15635, 15721, 16095, 14557, 14972, 15636, 15722, 16096, 14558, 14973, 15637, 15723, 16097, 14559, 14974, 15638, 15724, 16098, 14560, 14975, 15639, 15725, 16099, 14561, 14976, 15640, 15726, 16100, 14562, 14977, 15641, 15727, 16101, 14563, 14978, 15642, 15728, 16102, 14564, 14979, 15643, 15729, 16103, 14565, 14980, 15644, 15730, 16106, 14568, 14983, 15647, 15733, 16107, 14569, 14984, 15648, 15734, 16108, 14570, 14985, 15649, 15735, 16602, 17741, 18425, 18491, 18588, 18717, 18718, 18850, 18943, 16069, 14530, 14940, 15609, 15695, 16062, 14525, 14933, 15604, 15688, 16064, 14527, 14935, 15606, 15690, 18685, 18065, 17851, 18686, 18025, 18435, 18113, 17951, 17715, 18485, 18408, 18365, 18583, 18417, 18388, 16267, 16268, 16269, 16228, 16229, 15911, 15799, 15800, 15990, 17745, 18121, 16117, 14577, 17857}, -- 168 [slips.storages[2]] = L{12421, 12549, 12677, 12805, 12933, 13911, 14370, 14061, 14283, 14163, 12429, 12557, 12685, 12813, 12941, 13924, 14371, 14816, 14296, 14175, 13934, 14387, 14821, 14303, 14184, 13935, 14388, 14822, 14304, 14185, 13876, 13787, 14006, 14247, 14123, 13877, 13788, 14007, 14248, 14124, 13908, 14367, 14058, 14280, 14160, 13909, 14368, 14059, 14281, 14161, 16113, 14573, 14995, 15655, 15740, 16115, 14575, 14997, 15657, 15742, 16114, 14574, 14996, 15656, 15741, 16116, 14576, 14998, 15658, 15743, 12818, 18198, 12946, 18043, 12690, 17659, 12296, 12434, 15471, 15472, 15473, 15508, 15509, 15510, 15511, 15512, 15513, 15514, 17710, 17595, 18397, 18360, 18222, 17948, 18100, 15475, 15476, 15477, 15488, 15961, 14815, 14812, 14813, 15244, 15240, 14488, 14905, 15576, 15661, 15241, 14489, 14906, 15577, 15662, 13927, 14378, 14076, 14308, 14180, 13928, 14379, 14077, 14309, 14181, 10438, 10276, 10320, 10326, 10367, 10439, 10277, 10321, 10327, 10368, 10440, 10278, 10322, 10328, 10369, 10441, 10279, 10323, 10329, 10370}, -- 144 @@ -34,12 +34,13 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757}, -- 191 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453,}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454,}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839,}, -- 76 : Fancy Shorts is the last - [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25589, 25762, 25763, 25810, 25811, 25869, 25870, 25935, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, }, --160 + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 26518, 27623, 3719, 20573, 20674, 21742, 21860, 22065, 23731, 26517, 3724, 3721, 21682, 22072, 21820, 21821, 22124, 22132, 3738, 22039, 23730,}, -- 97 + [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25589, 25762, 25763, 25810, 25811, 25869, 25870, 25935, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21761, 20576, 21272, 21744, 22004, 26409,}, --165 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330,}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665,}, --115 [slips.storages[26]] = L{23063, 23130, 23197, 23264, 23331, 23064, 23131, 23198, 23265, 23332, 23065, 23132, 23199, 23266, 23333, 23066, 23133, 23200, 23267, 23334, 23067, 23134, 23201, 23268, 23335, 23068, 23135, 23202, 23269, 23336, 23069, 23136, 23203, 23270, 23337, 23070, 23137, 23204, 23271, 23338, 23071, 23138, 23205, 23272, 23339, 23072, 23139, 23206, 23273, 23340, 23073, 23140, 23207, 23274, 23341, 23074, 23141, 23208, 23274, 23342, 23075, 23142, 23209, 23276, 23343, 23076, 23143, 23210, 23277, 23344, 23077, 23144, 23211, 23278, 23345, 23078, 23145, 23212, 23279, 23346, 23079, 23146, 23213, 23280, 23347, 23080, 23147, 23214, 23281, 23348, 23081, 23148, 23215, 23282, 23349, 23082, 23149, 23216, 23283, 23350, 23083, 23150, 23217, 23284, 23351, 23084, 23151, 23218, 23285, 23352,}, --110 [slips.storages[27]] = L{23398, 23465, 23532, 23599, 23666, 23399, 23466, 23533, 23600, 23667, 23400, 23467, 23534, 23601, 23668, 23401, 23468, 23535, 23602, 23669, 23402, 23469, 23536, 23603, 23670, 23403, 23470, 23537, 23604, 23671, 23404, 23471, 23538, 23605, 23672, 23405, 23472, 23539, 23606, 23673, 23406, 23473, 23540, 23607, 23674, 23407, 23474, 23541, 23608, 23675, 23408, 23475, 23542, 23609, 23676, 23409, 23476, 23543, 23610, 23677, 23410, 23477, 23544, 23611, 23678, 23411, 23478, 23545, 23612, 23679, 23412, 23479, 23546, 23613, 23680, 23413, 23480, 23547, 23614, 23681, 23414, 23481, 23548, 23615, 23682, 23415, 23482, 23549, 23616, 23683, 23416, 23483, 23550, 23617, 23684, 23417, 23484, 23551, 23618, 23685, 23418, 23485, 23552, 23619, 23686, 23419, 23486, 23553, 23620, 23687,}, --110 + [slips.storages[28]] = L{21515, 21561, 21617, 21670, 21718, 21775, 21826, 21879, 21918, 21971, 22027, 22082, 22108, 22214, 21516, 21562, 21618, 21671, 21719, 21776, 21827, 21880, 21919, 21972, 22028, 22083, 22109, 22215, 21517, 21563, 21619, 21672, 21720, 21777, 21828, 21881, 21920, 21973, 22029, 22084, 22110, 22216, 21518, 21564, 21620, 21673, 21721, 21778, 21829, 21882, 21921, 21974, 22030, 22085, 22111, 22217, 21519, 21565, 21621, 21674, 21722, 21779, 21830, 21883, 21922, 21975, 22031, 22086, 22107, 22218}, --70 } function slips.get_slip_id(n) From 746d35580267e48fb84527647341e30751ef1da0 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Tue, 14 May 2019 04:04:47 -0400 Subject: [PATCH 0240/1002] Slip 28 --- addons/findAll/findAll.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/findAll/findAll.lua b/addons/findAll/findAll.lua index e10f6a281e..9e3e293ee7 100644 --- a/addons/findAll/findAll.lua +++ b/addons/findAll/findAll.lua @@ -189,7 +189,7 @@ storages_order = S(res.bags:map(string.gsub-{' ', ''} .. string.lower .. return index1 < index2 end) -storage_slips_order = L{'slip 01', 'slip 02', 'slip 03', 'slip 04', 'slip 05', 'slip 06', 'slip 07', 'slip 08', 'slip 09', 'slip 10', 'slip 11', 'slip 12', 'slip 13', 'slip 14', 'slip 15', 'slip 16', 'slip 17', 'slip 18', 'slip 19', 'slip 20', 'slip 21', 'slip 22', 'slip 23', 'slip 24', 'slip 25', 'slip 26', 'slip 27'} +storage_slips_order = L{'slip 01', 'slip 02', 'slip 03', 'slip 04', 'slip 05', 'slip 06', 'slip 07', 'slip 08', 'slip 09', 'slip 10', 'slip 11', 'slip 12', 'slip 13', 'slip 14', 'slip 15', 'slip 16', 'slip 17', 'slip 18', 'slip 19', 'slip 20', 'slip 21', 'slip 22', 'slip 23', 'slip 24', 'slip 25', 'slip 26', 'slip 27', 'slip 28'} merged_storages_orders = storages_order + storage_slips_order + L{'key items'} function search(query, export) From 309439c836ce67608ae37575e525c99ee586c7e5 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Tue, 14 May 2019 04:06:38 -0400 Subject: [PATCH 0241/1002] version bump --- addons/findAll/findAll.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/findAll/findAll.lua b/addons/findAll/findAll.lua index 9e3e293ee7..83ff8d1a19 100644 --- a/addons/findAll/findAll.lua +++ b/addons/findAll/findAll.lua @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'findAll' _addon.author = 'Zohno' -_addon.version = '1.20180607' +_addon.version = '1.20190514' _addon.commands = {'findall'} require('chat') From 47e821498fee93ae7738146e227e89991da593ec Mon Sep 17 00:00:00 2001 From: Chiaia Date: Tue, 14 May 2019 04:12:49 -0400 Subject: [PATCH 0242/1002] Slip 28 --- addons/organizer/organizer.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/organizer/organizer.lua b/addons/organizer/organizer.lua index 27e2a46536..88f485854a 100644 --- a/addons/organizer/organizer.lua +++ b/addons/organizer/organizer.lua @@ -201,7 +201,7 @@ function options_load( ) if(settings.retain.slips == true) then org_verbose("Slips set to retain") - slips = {29312,29313,29314,29315,29316,29317,29318,29319,29320,29321,29322,29323,29324,29325,29326,29327,29328,29329,29330,29331,29332,29333,29334,29335,29336,29337,29338} + slips = {29312,29313,29314,29315,29316,29317,29318,29319,29320,29321,29322,29323,29324,29325,29326,29327,29328,29329,29330,29331,29332,29333,29334,29335,29336,29337,29338,29339} for _,slips_id in pairs(slips) do _retain[slips_id] = "slips" org_debug("settings", "Adding ("..res.items[slips_id].english..') to slip retain list') From 87765f78526c62ee4907d4e24e63b71ae470adff Mon Sep 17 00:00:00 2001 From: David Kolb Date: Wed, 15 May 2019 12:57:25 -0400 Subject: [PATCH 0243/1002] Add /boomhelix commands; fix lua error Now supports SCH Helix Commands. Also, the conditionals checking the length of the spell_tables entry were out of order, so you could try to get the length of nil instead. Now the or conditional short circuits when the spell_table entry is nil. General cleanup of code to reuse current_spell_table instead of indexing into spell_tables repeatedly. Cleaned up repitition in spell casting commands. --- addons/EasyNuke/EasyNuke.lua | 79 +++++++++++++++--------------------- addons/EasyNuke/readme.md | 9 +++- 2 files changed, 41 insertions(+), 47 deletions(-) diff --git a/addons/EasyNuke/EasyNuke.lua b/addons/EasyNuke/EasyNuke.lua index 30e37b419b..1ad6c0fe22 100644 --- a/addons/EasyNuke/EasyNuke.lua +++ b/addons/EasyNuke/EasyNuke.lua @@ -58,25 +58,33 @@ spell_tables = {} spell_tables["fire"] = {"Fire","Fire II","Fire III","Fire IV","Fire V","Fire VI",} spell_tables["fire"]["ga"] = {"Firaga","Firaga II","Firaga III","Firaja",} spell_tables["fire"]["ra"] = {"Fira","Fira II","Fira III"} +spell_tables["fire"]["helix"] = {"Pyrohelix","Pyrohelix II"} spell_tables["earth"] = {"Stone","Stone II","Stone III","Stone IV","Stone V","Stone VI",} spell_tables["earth"]["ga"] = {"Stonega","Stonega II","Stonega III","Stoneja",} spell_tables["earth"]["ra"] = {"Stonera","Stonera II","Stonera III"} +spell_tables["earth"]["helix"] = {"Geohelix","Geohelix II"} spell_tables["wind"] = {"Aero","Aero II","Aero III","Aero IV","Aero V","Aero VI",} spell_tables["wind"]["ga"] = {"Aeroga","Aeroga II","Aeroga III","Aeroja",} spell_tables["wind"]["ra"] = {"Aerora","Aerora II","Aerora III"} +spell_tables["wind"]["helix"] = {"Anemohelix","Anemohelix II"} spell_tables["water"] = {"Water","Water II","Water III","Water IV","Water V","Water VI",} spell_tables["water"]["ga"] = {"Waterga","Waterga II","Waterga III","Waterja",} spell_tables["water"]["ra"] = {"Watera","Watera II","Watera III"} +spell_tables["water"]["helix"] = {"Hydrohelix","Hydrohelix II"} spell_tables["ice"] = {"Blizzard","Blizzard II","Blizzard III","Blizzard IV","Blizzard V","Blizzard VI",} spell_tables["ice"]["ga"] = {"Blizzaga","Blizzaga II","Blizzaga III","Blizzaja",} spell_tables["ice"]["ra"] = {"Blizzara","Blizzara II","Blizzara III"} +spell_tables["ice"]["helix"] = {"Cryohelix","Cryohelix II"} spell_tables["thunder"] = {"Thunder","Thunder II","Thunder III","Thunder IV","Thunder V","Thunder VI",} spell_tables["thunder"]["ga"] = {"Thundaga","Thundaga II","Thundaga III","Thundaja",} spell_tables["thunder"]["ra"] = {"Thundara","Thundara II","Thundara III"} +spell_tables["thunder"]["helix"] = {"Ionohelix","Ionohelix II"} spell_tables["light"] = {"Banish","Banish II","Holy","Banish III",} spell_tables["light"]["ga"] = {"Banishga","Banishga II"} +spell_tables["light"]["helix"] = {"Luminohelix","Luminohelix II"} spell_tables["dark"] = {"Impact"} spell_tables["dark"]["ga"] = {"Comet"} +spell_tables["dark"]["helix"] = {"Noctohelix", "Noctohelix II"} spell_tables["cure"] = {"Cure","Cure II","Cure III","Cure IV","Cure V","Cure VI"} spell_tables["cure"]["ga"] = {"Curaga","Curaga II","Curaga III","Curaga IV","Curaga V",} spell_tables["cure"]["ra"] = {"Cura","Cura II","Cura III"} @@ -101,64 +109,43 @@ local indices = { dark = 8, } +function execute_spell_cast(spell_type, arg) + local current_spell_table = nil + if spell_type == nil then + current_spell_table = spell_tables[current_element] + else + current_spell_table = spell_tables[current_element][spell_type] + end + if arg == nil then arg = 1 end + arg = tonumber(arg) + if current_spell_table == nil or arg > #current_spell_table then + windower.add_to_chat(206,"Invalid Spell.") return + end + windower.chat.input("/ma \""..current_spell_table[arg].."\" <"..target_mode..">") +end + windower.register_event("unhandled command", function (command, arg) if command == "boom" or command == "nuke" then - local current_spell_table = spell_tables[current_element] - if arg == nil then arg = 1 end - arg = tonumber(arg) - if arg > #spell_tables[current_element] then - windower.add_to_chat(206,"Invalid Spell.") return - end - windower.chat.input("/ma \""..current_spell_table[arg].."\" <"..target_mode..">") - + execute_spell_cast(nil, arg) elseif command == "boomga" or command == "bga" then - local current_spell_table = spell_tables[current_element]["ga"] - if arg == nil then arg = 1 end - arg = tonumber(arg) - if arg > #spell_tables[current_element]["ga"] or spell_tables[current_element]["ga"] == nil then - windower.add_to_chat(206,"Invalid Spell.") return - end - windower.chat.input("/ma \""..current_spell_table[arg].."\" <"..target_mode..">") - + execute_spell_cast("ga", arg) elseif command == "boomra" or command == "bra" then - local current_spell_table = spell_tables[current_element]["ra"] - if arg == nil then arg = 1 end - arg = tonumber(arg) - if arg > #spell_tables[current_element]["ra"] or spell_tables[current_element]["ra"] == nil then - windower.add_to_chat(206,"Invalid Spell.") return - end - windower.chat.input("/ma \""..current_spell_table[arg].."\" <"..target_mode..">") + execute_spell_cast("ra", arg) + elseif command == "boomhelix" or command == "bhelix" then + execute_spell_cast("helix", arg) end end) windower.register_event('addon command', function (command, arg) if command == "boom" or command == "nuke" then - local current_spell_table = spell_tables[current_element] - if arg == nil then arg = 1 end - arg = tonumber(arg) - if arg > #spell_tables[current_element] then - windower.add_to_chat(206,"Invalid Spell.") return - end - windower.chat.input("/ma \""..current_spell_table[arg].."\" <"..target_mode..">") - + execute_spell_cast(nil, arg) elseif command == "boomga" or command == "bga" then - local current_spell_table = spell_tables[current_element]["ga"] - if arg == nil then arg = 1 end - arg = tonumber(arg) - if arg > #spell_tables[current_element]["ga"] or spell_tables[current_element]["ga"] == nil then - windower.add_to_chat(206,"Invalid Spell.") return - end - windower.chat.input("/ma \""..current_spell_table[arg].."\" <"..target_mode..">") - + execute_spell_cast("ga", arg) elseif command == "boomra" or command == "bra" then - local current_spell_table = spell_tables[current_element]["ra"] - if arg == nil then arg = 1 end - arg = tonumber(arg) - if arg > #spell_tables[current_element]["ra"] or spell_tables[current_element]["ra"] == nil then - windower.add_to_chat(206,"Invalid Spell.") return - end - windower.chat.input("/ma \""..current_spell_table[arg].."\" <"..target_mode..">") + execute_spell_cast("ra", arg) + elseif command == "boomhelix" or command == "bhelix" then + execute_spell_cast("helix", arg) elseif command == "target" then if arg then diff --git a/addons/EasyNuke/readme.md b/addons/EasyNuke/readme.md index ebdcd0444e..1d92b7bff5 100644 --- a/addons/EasyNuke/readme.md +++ b/addons/EasyNuke/readme.md @@ -71,4 +71,11 @@ Commands: * Casts an area of effect nuke of tier XXX. GEO's -ra AOE nukes and WHM's Cura line * EX: //ez boomra 3 <<<< If Element Mode is Ice, and mode is "bt", will cast Blizzara III on your current battle target. * EX2: //boomra 2 <<<< If Element Mode is Cure, and mode is "me", you will cast Cura II on yourself. - * Macro usage: /con ez boomra # /OR/ /con boomra # \ No newline at end of file + * Macro usage: /con ez boomra # /OR/ /con boomra # + +#### boomhelix +* Casts the appropriate SCH Helix spell of tier XXX. + * EX: //ez boomhelix 2 <<<< If Element Mode is Ice, and target mode is "t", will cast Cryohelix II on your current target. + * EX2: //boomhelix <<<< If Element Mode is Fire, and target mode is "bt", will cast Pyrohelix on your current battle target. + * Macro usage: /con ez boomhelix # /OR/ /con boomhelix # +* Also supports a short version //bhelix # or //ez bhelix \ No newline at end of file From fb01324c96227b01046f7bbc5ceaa53c41ce3614 Mon Sep 17 00:00:00 2001 From: David Kolb Date: Wed, 15 May 2019 14:31:21 -0400 Subject: [PATCH 0244/1002] Style Fixes Replace tabs witth 4 spaces. --- addons/EasyNuke/EasyNuke.lua | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/addons/EasyNuke/EasyNuke.lua b/addons/EasyNuke/EasyNuke.lua index 1ad6c0fe22..68b1ec010c 100644 --- a/addons/EasyNuke/EasyNuke.lua +++ b/addons/EasyNuke/EasyNuke.lua @@ -110,18 +110,18 @@ local indices = { } function execute_spell_cast(spell_type, arg) - local current_spell_table = nil - if spell_type == nil then - current_spell_table = spell_tables[current_element] - else - current_spell_table = spell_tables[current_element][spell_type] - end - if arg == nil then arg = 1 end - arg = tonumber(arg) - if current_spell_table == nil or arg > #current_spell_table then - windower.add_to_chat(206,"Invalid Spell.") return - end - windower.chat.input("/ma \""..current_spell_table[arg].."\" <"..target_mode..">") + local current_spell_table = nil + if spell_type == nil then + current_spell_table = spell_tables[current_element] + else + current_spell_table = spell_tables[current_element][spell_type] + end + if arg == nil then arg = 1 end + arg = tonumber(arg) + if current_spell_table == nil or arg > #current_spell_table then + windower.add_to_chat(206,"Invalid Spell.") return + end + windower.chat.input("/ma \""..current_spell_table[arg].."\" <"..target_mode..">") end windower.register_event("unhandled command", function (command, arg) @@ -131,8 +131,8 @@ windower.register_event("unhandled command", function (command, arg) execute_spell_cast("ga", arg) elseif command == "boomra" or command == "bra" then execute_spell_cast("ra", arg) - elseif command == "boomhelix" or command == "bhelix" then - execute_spell_cast("helix", arg) + elseif command == "boomhelix" or command == "bhelix" then + execute_spell_cast("helix", arg) end end) @@ -144,8 +144,8 @@ windower.register_event('addon command', function (command, arg) execute_spell_cast("ga", arg) elseif command == "boomra" or command == "bra" then execute_spell_cast("ra", arg) - elseif command == "boomhelix" or command == "bhelix" then - execute_spell_cast("helix", arg) + elseif command == "boomhelix" or command == "bhelix" then + execute_spell_cast("helix", arg) elseif command == "target" then if arg then From c21e691be4b2274fce74f6096ed8fb16035abe83 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Wed, 22 May 2019 23:53:43 +0200 Subject: [PATCH 0245/1002] fix to allow on screen dmg fix to allow on screen dmg --- addons/battlemod/battlemod.lua | 23 +++++++++++++++++++++-- addons/battlemod/generic_helpers.lua | 2 +- addons/battlemod/parse_action_packet.lua | 12 +++++++++--- addons/battlemod/statics.lua | 3 ++- 4 files changed, 33 insertions(+), 7 deletions(-) diff --git a/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index c33a506071..00ef74a354 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -12,7 +12,7 @@ require 'generic_helpers' require 'parse_action_packet' require 'statics' -_addon.version = '3.24' +_addon.version = '3.25' _addon.name = 'BattleMod' _addon.author = 'Byrth, maintainer: SnickySnacks' _addon.commands = {'bm','battlemod'} @@ -107,7 +107,7 @@ windower.register_event('addon command', function(command, ...) end end) -windower.register_event('incoming text',function (original, modified, color) +windower.register_event('incoming text',function (original, modified, color, color_m, blocked) if debugging then windower.debug('incoming text') end local redcol = color%256 @@ -132,10 +132,29 @@ windower.register_event('incoming text',function (original, modified, color) modified = true end end + if filter_messages(original) then + blocked = true + return blocked + end return modified,color end) +function filter_messages(original) + for i, v in pairs(res.action_messages) do + if non_block_messages:contains(res.action_messages[i].id) then + local msg = res.action_messages[i].en + msg = msg:gsub("${actor}", "%.-" ) + msg = msg:gsub("${target}", "%.-" ) + msg = msg:gsub("${number}", "%%d+" ) + original = original:gsub("point ", "points ") + if original:match(msg) then + return true + end + end + end +end + function flip_block_equip() block_equip = not block_equip end diff --git a/addons/battlemod/generic_helpers.lua b/addons/battlemod/generic_helpers.lua index 0bf277009f..71cf637183 100644 --- a/addons/battlemod/generic_helpers.lua +++ b/addons/battlemod/generic_helpers.lua @@ -1,4 +1,4 @@ ---Copyright (c) 2013, Byrthnoth +--Copyright (c) 2019, Byrthnoth --All rights reserved. --Redistribution and use in source and binary forms, with or without diff --git a/addons/battlemod/parse_action_packet.lua b/addons/battlemod/parse_action_packet.lua index ee3756d49a..09ec7bac1c 100644 --- a/addons/battlemod/parse_action_packet.lua +++ b/addons/battlemod/parse_action_packet.lua @@ -247,7 +247,9 @@ function parse_action_packet(act) :gsub('${number}',act.action.number or m.param) :gsub('${status}',m.status or 'ERROR 120') :gsub('${gil}',m.param..' gil'))) - m.message = 0 + 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) @@ -276,7 +278,9 @@ function parse_action_packet(act) :gsub('${lb}','\7') :gsub('${number}',m.add_effect_param) :gsub('${status}',m.add_effect_status or 'ERROR 178'))) - m.add_effect_message = 0 + 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 @@ -311,7 +315,9 @@ function parse_action_packet(act) :gsub('${lb}','\7') :gsub('${number}',m.spike_effect_param) :gsub('${status}',m.spike_effect_status or 'ERROR 150'))) - m.spike_effect_message = 0 + if not non_block_messages:contains(m.spike_effect_message) then + m.spike_effect_message = 0 + end end end end diff --git a/addons/battlemod/statics.lua b/addons/battlemod/statics.lua index ffe54e6ca6..b9db2b7300 100644 --- a/addons/battlemod/statics.lua +++ b/addons/battlemod/statics.lua @@ -1,4 +1,4 @@ - --Copyright (c) 2013, Byrthnoth + --Copyright (c) 2019, Byrthnoth --All rights reserved. --Redistribution and use in source and binary forms, with or without @@ -29,6 +29,7 @@ ratings_arr = {'TW','EEP','EP','DC','EM','T','VT','IT'} current_job = 'NONE' default_filt = false 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,608,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,40,47,48,49,64,78,87,88,89,90,112,116,154,170,171,172,173,174,175,176,177,178,191,192,198,204,215,217,218,219,234,246,249,307,315,328,350,336,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,62,94,251,308,313,372,8,105,253,679,97,62,94,251,313,308,206,72,38,53} 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. From a55fbea0ab090a2c5dd2c319b0f25460cd8aa11e Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Thu, 23 May 2019 16:55:34 +0200 Subject: [PATCH 0246/1002] Update battlemod.lua --- addons/battlemod/battlemod.lua | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index 00ef74a354..2b513bf553 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -144,10 +144,19 @@ function filter_messages(original) for i, v in pairs(res.action_messages) do if non_block_messages:contains(res.action_messages[i].id) then local msg = res.action_messages[i].en - msg = msg:gsub("${actor}", "%.-" ) - msg = msg:gsub("${target}", "%.-" ) - msg = msg:gsub("${number}", "%%d+" ) + msg = msg:gsub("${actor}", "%%w+") + msg = msg:gsub("${target}", "%%w+") + msg = msg:gsub("${lb}", "") + msg = msg:gsub("${number}", "%%d+") + msg = msg:gsub(" ", "") + msg = msg:gsub("'", "") + msg = msg:gsub("-", "") original = original:gsub("point ", "points ") + original = original:gsub("absorb ", "absorbs ") + original = original:gsub(" ", "") + original = original:gsub("'", "") + original = original:gsub("-", "") + original = original:gsub("?", "") if original:match(msg) then return true end From d005da5567822beddb4cca6c3c6db9ae62bcf245 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Thu, 23 May 2019 19:22:29 +0200 Subject: [PATCH 0247/1002] copyright --- addons/battlemod/generic_helpers.lua | 2 +- addons/battlemod/statics.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/battlemod/generic_helpers.lua b/addons/battlemod/generic_helpers.lua index 71cf637183..4bb5ef14ca 100644 --- a/addons/battlemod/generic_helpers.lua +++ b/addons/battlemod/generic_helpers.lua @@ -1,4 +1,4 @@ ---Copyright (c) 2019, Byrthnoth +--Copyright © 2013, Byrthnoth --All rights reserved. --Redistribution and use in source and binary forms, with or without diff --git a/addons/battlemod/statics.lua b/addons/battlemod/statics.lua index b9db2b7300..e089cac282 100644 --- a/addons/battlemod/statics.lua +++ b/addons/battlemod/statics.lua @@ -1,4 +1,4 @@ - --Copyright (c) 2019, Byrthnoth + --Copyright © 2013, Byrthnoth --All rights reserved. --Redistribution and use in source and binary forms, with or without From 7a4ec1439b83c3809e543ac685c22754ca88664d Mon Sep 17 00:00:00 2001 From: Unknown Date: Wed, 29 May 2019 20:21:15 -0400 Subject: [PATCH 0248/1002] Added Delete function to AzureSets --- addons/azureSets/azuresets.lua | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/addons/azureSets/azuresets.lua b/addons/azureSets/azuresets.lua index 898a49b8ae..f25097099a 100644 --- a/addons/azureSets/azuresets.lua +++ b/addons/azureSets/azuresets.lua @@ -210,6 +210,16 @@ function save_set(setname) notice('Set '..setname..' saved.') end +function delete_set(setname) + if settings.spellsets[setname] == nil then + error('Please choose an existing spellset.') + return + end + settings.spellsets[setname] = nil + settings:save('all') + notice('Deleted '..setname..'.') +end + function get_spellset_list() log("Listing sets:") for key,_ in pairs(settings.spellsets) do @@ -248,7 +258,10 @@ windower.register_event('addon command', function(...) if args[1] ~= nil then save_set(args[1]) end - + elseif comm == 'delete' then + if args[1] ~= nil then + delete_set(args[1]) + end elseif comm == 'spellset' or comm == 'set' then if args[1] ~= nil then set_spells(args[1], args[2] or settings.setmode) @@ -272,10 +285,11 @@ windower.register_event('addon command', function(...) 3. set (clearfirst|preservetraits) -- Same as spellset 4. add -- Set (spell) to slot (slot (number)). 5. save -- Saves current spellset as (setname). - 6. currentlist -- Lists currently set spells. - 7. setlist -- Lists all spellsets. - 8. spelllist -- List spells in (setname) - 9. help --Shows this menu.]] + 6. delete -- Delete (setname) spellset. + 7. currentlist -- Lists currently set spells. + 8. setlist -- Lists all spellsets. + 9. spelllist -- List spells in (setname) + 10. help --Shows this menu.]] for _, line in ipairs(helptext:split('\n')) do windower.add_to_chat(207, line..chat.controls.reset) end From 1d9eb5b4d27657a2a36d99b783ef931e5f71fd2a Mon Sep 17 00:00:00 2001 From: DYDR Date: Wed, 29 May 2019 21:44:39 -0400 Subject: [PATCH 0249/1002] Tabs -> Spaces --- addons/azureSets/azuresets.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/azureSets/azuresets.lua b/addons/azureSets/azuresets.lua index f25097099a..2bdbfb1f8d 100644 --- a/addons/azureSets/azuresets.lua +++ b/addons/azureSets/azuresets.lua @@ -211,7 +211,7 @@ function save_set(setname) end function delete_set(setname) - if settings.spellsets[setname] == nil then + if settings.spellsets[setname] == nil then error('Please choose an existing spellset.') return end @@ -258,7 +258,7 @@ windower.register_event('addon command', function(...) if args[1] ~= nil then save_set(args[1]) end - elseif comm == 'delete' then + elseif comm == 'delete' then if args[1] ~= nil then delete_set(args[1]) end From 984cffcee5251b7716698f824180d827cdcc4d90 Mon Sep 17 00:00:00 2001 From: DYDR Date: Thu, 30 May 2019 18:00:16 -0400 Subject: [PATCH 0250/1002] Version 1.23 --- .vs/ProjectSettings.json | 3 +++ .vs/VSWorkspaceState.json | 9 +++++++++ .vs/slnx.sqlite | Bin 0 -> 323584 bytes addons/azureSets/azuresets.lua | 2 +- 4 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 .vs/ProjectSettings.json create mode 100644 .vs/VSWorkspaceState.json create mode 100644 .vs/slnx.sqlite diff --git a/.vs/ProjectSettings.json b/.vs/ProjectSettings.json new file mode 100644 index 0000000000..f8b4888565 --- /dev/null +++ b/.vs/ProjectSettings.json @@ -0,0 +1,3 @@ +{ + "CurrentProjectSetting": null +} \ No newline at end of file diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json new file mode 100644 index 0000000000..ce5d6c0216 --- /dev/null +++ b/.vs/VSWorkspaceState.json @@ -0,0 +1,9 @@ +{ + "ExpandedNodes": [ + "", + "\\addons", + "\\addons\\azureSets" + ], + "SelectedNode": "\\addons\\azureSets\\azuresets.lua", + "PreviewInSolutionExplorer": false +} \ No newline at end of file diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..4a430bd6bcf4b6f68570a59b8ac16138c321d35b GIT binary patch literal 323584 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�AZLM`1#%Y1Ss-VDoCW?f7Qo;CHwvAc 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 literal 0 HcmV?d00001 diff --git a/addons/azureSets/azuresets.lua b/addons/azureSets/azuresets.lua index 2bdbfb1f8d..41bab2951d 100644 --- a/addons/azureSets/azuresets.lua +++ b/addons/azureSets/azuresets.lua @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'AzureSets' -_addon.version = '1.22' +_addon.version = '1.23' _addon.author = 'Nitrous (Shiva)' _addon.commands = {'aset','azuresets','asets'} From e833bf6fc18e535d1ea925c027835a5488d406cf Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 30 May 2019 18:04:39 -0400 Subject: [PATCH 0251/1002] Damn you MSVS --- .vs/ProjectSettings.json | 3 --- .vs/VSWorkspaceState.json | 9 --------- .vs/slnx.sqlite | Bin 323584 -> 0 bytes 3 files changed, 12 deletions(-) delete mode 100644 .vs/ProjectSettings.json delete mode 100644 .vs/VSWorkspaceState.json delete mode 100644 .vs/slnx.sqlite diff --git a/.vs/ProjectSettings.json b/.vs/ProjectSettings.json deleted file mode 100644 index f8b4888565..0000000000 --- a/.vs/ProjectSettings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "CurrentProjectSetting": null -} \ No newline at end of file diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json deleted file mode 100644 index ce5d6c0216..0000000000 --- a/.vs/VSWorkspaceState.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "ExpandedNodes": [ - "", - "\\addons", - "\\addons\\azureSets" - ], - "SelectedNode": "\\addons\\azureSets\\azuresets.lua", - "PreviewInSolutionExplorer": false -} \ No newline at end of file diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite deleted file mode 100644 index 4a430bd6bcf4b6f68570a59b8ac16138c321d35b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 323584 zcmeFa2Y4LSwKzVzGdsIGTSi)S%VpiLWqW1y0vIgIvMrEgS;Ylo+iG9%(>^B zd+xdQ%-(x$@3M|iLU9M9v0-n*UCZTh1_L+W?dCYH9R4qb|LQ*(9t8CTph5S%ug7xE z^WBjqB$mHLntb_N`=~7@J!<*XvfO-;$s)w~XSnydH}@sre}EUABH=!M&|xmAtu>sS zOn7}^Wl<=s^p3?7%5aYoRANfRzc-Y#wWqD6ug%@pvY?~Qy?QT9YaG%{hvbHTdrNJL zBtnU?_P`o3<&E&Y8<+q)o(&bF>Tch^$*-`~+O$Iaw* z$D*U5fD+TQt3>Xewnc3{ZC$Nxz3$a2AgObr2?6;v21xU|c?u&tvFiqqQC+uE|Q zZ4S$5p)#UG0^Udh%l9vHOB+GUFB^sVvQn^&`@0vS9a+XdLZ^&c$FNW=(y41*zhF zFtkP^31#C?;piJ1QPOP-TaQDkNKLVuOICOcsm@R&pls|N8}>!R3zc9f5=w-kkpcP` z8AL0!2L{^rM&w`(zrAZ=+e-K9A0-320%>G>P_J>%T%DQenu=6`&0Nw7O1AD@$u94( zvUk<&|3bAi=RZ{l$<}05M8)xWlDWj=F`U#(28rxqXTRGrhllKB-Pn+wq;JtbVn|>e zRqg0{?*GV$K#h~taM}2jWixdUS(FTi$Cf3%;ZQK71okFi@4e(usDE7(RtG^=;ugPO ziN`~}P#DJ1eUoLiE^V~kt8ubNhyTog(Gm4~vAgv|H|$$)m8dluP7X)*q{H6aWHpzx zc??@^q@!djKhW)k$ty8{2G35DSo7@fYG2mh21X%$Ih#r^LF+NuMA(J*)??_ZgD zX22mgRbbKg@oW;JGwtKqN!H9ho}H}Y{K*FJ(GmgLk5*&V@@X@~4&oh7o9{+kxr+a&g{OtG)Q zFg+#V5}(a(?Qzs}je9}6Zu!sBI=u13QeRw&jVdrdrW?Cj6${%Iwe)xNx&6r)nE(=M z&tSqAE$wM*U))6;4QQ4)f<)4yBgd&5walMyf z1XkzjI&=>@t%EX#eN9vq-A1uw_H4r{($wNd!g@j(h$}}X(eulCyH*6gwGMNGl7&Bz7R<%oeiwyI>*EE-V!%1js>Ap$55pa(4BnSL8S!y|X zxBP&7t>u1r%>Bz*AZLM`1#%Y1Ss-VDoCUHikg}LeTx)6#EdJLi{serx42A}iG4jo$ z7gntyzj72VWv4KL1<6o2kUuXTzYW<$-#^&Za#oy#<@KpyWk=I}AMVUZU-_-04Hh8Li-o~1Sh9*yARU@#VByV#~ zQzlVOeN{t4z+a=2)EubyWf3*h)K~keGqMW?vWY<9<^bfI)(LgYlvJxI{;Gx=P^Ye; z)>GHmRORv3`U4)Np}tzFYOZf=Pyp?#t?@TBHF|2As{Niie?!3It?^cSY6D;wU(j0< zs0(=Nef2d}&B)&vsQ1(<)m5IR`lcFBwYSdS1O{jdDD|F(X0NxZxw_HgYxMb;2^y6e zrjx(Pr+_^gyiJXb_02&~u(7TIBsGEU8=IOu%?dsf?g_c?8hkwoWHBiC+y5{PdDleEo0Xxtx<%e3%=y(2xnx+O~ zr$#Sm-|TOIeh2oe@hL&jEzsl(HhTQNU|myv9n^zQfkx*CJ2XM7_xP)80>Rq)fTA=v zdjhroI;8;$4qb|6*W`!Rk&#`Xxu&`XO5tgS%7g4coVT&Q)>9L#Z))%beZi{6Mo+-k zR8``C$;NtM^nl)CX#O{$N9}q1vNVRrwlf z(3qN}W*<~_h9sq`QSsN+!XV~rgl=9}+Xy`n$`SB3*ZHfJ2E_{%p)`Og>#AU^QEIAy z2pV#819XI@hPps~O`9a%bH5F7mSf%%pml?V9*C;u7cqMvI}}(s)6h> zbP7UuuZOWFT`j(*rrHci#k|1HmB|zbGbR2q(i%-h616jo0_Ul1jVa!Q5?C7R9|_gHmDz|AP>h0ol>UiP)Fy0W&ij`;ubg`E5s`7QZz`9k^D z?CC!Dp0hyC0yzuhEReH6&H_0L4`H`CIub`E&VW`F;5y zd6M&c=X=iIIB#~I=RDf!ceXogo#UJa$H$JR9k)9!bZm31bM!e5aJU^N`{(vo><`$l zv7ccdwXd?b*r(bh+n2W2Y!BORw4G(!Wb@jV*gUoZ>09Y->DSVY(pl0*=`g8Hs+3A3 z&br(Bl=T+t+18`2inY_)Xq{rUSU$77Zh6pho#iA;#InM2uw|A-Hvi51uK98EE#`~O zTg-#zE_1DUqS-9|NqkAXQ@l*vDh`RAVv{&gG@5psUN+rry3%yIDPcOy)M~0Q*@eFd zZwZeH*9kj?&BCD2DbxxR1%dyFf0Vz0Kb~L5xAV1pk@4@wH;unC?lNvQ4jKIifm`8Xau_To*auXnNI2w&qjzk8vl(JNw$W10v zV*|m#tTZ{D=F3bQpMu~ARGU~Z6b>t~j0{Ut4w0J#VtW*CU|6Xf4#=u5<5PCZ>D`o! zDRCu1RMnD8Q#Qug*0Qj(4LF@DXIV<3`m`hy(ViB}P)jRKSt%RrRG}FMTwIXycRuiQ8s=C-Qr zr70mxC7YU5p5m!W!`_IJ9Hqw7QVUYXbp31Ci7A7~&1Ty8qme``8b)dtdf}L1pR+WA7(IQt3>@AT9Yzp!#H2eT& zu91{)rUlZQVw1{WdQ_HVi<(lfDP2+xSvp3^y^4P*in*jyHe!lJ+!T!{cq%O>5J5-3 zKU%PX3R;zn4{6AvQIRVH@{OTUpI1klq_m?OhQb)Vy5toPHOgIGb@Qy~)97S;| zC`qw{wir*w##q9=q4E)$2TM@8qfu3XdqbsBTDC+C zYAFo6tTeWw2+IbJ+9lG`N{1PPdOS~KC=IieArR(YubJuIP{Ddy^gaj%p^+D^6S)%5 z7b2F7sHM0!R2IU{23QhnA`}Tm8N)d~*O15+U;({84Ocoy^XyIfX!Fog#szU;vWUH) zOk#-=9?|qU$5*OQu6QCkvca41t95sduOL7*jVB^rO;nkm>eM@;gu|^vihsS9RO(~- zW72|XG@VlJrB(+fB|w;T3KXvuxpGtv_Ju>sX5u2N#tl%V<3rJ8rqYpBrAIKOhoZ5B zKdIF`q^w~|D2WUsL{=3YPU{f*hi`CL%cfv8D6 z^|ti2w8EZr#l@ zn9zZPxkVfaCkI230T_9~PHGp2j1Hw4jfB1N;b` zRGFwR%s?0ku-+*plcls{}xgYoTqT6SsJFCO2&gr_;*j zQww%ReXY^q5pSH?eDjNy`2UXjXl(vb2fX z`w%DxQB}*jq>;8*n9hfF6>;N?vIbgonCdfn%H|tq6xY+zg(9%L>gZ*%Zk$nGM@`ZW z!()#EZO5;v08F)%2@@Bn^A89st)Z$7g$9Sh@SpW!NGYqP8VrUq`zj=rR8g%LE8bY| z2Cr&KNSI3#2I259&WTL7<4TGvY4#AEC(sgR6V2x1N=iJGAsCGMqhWQHgM^|v)cA{F zU};s$cw9-rY-)UE)SDJkI*XP8EU&~M`j1-SAijc%S0c*rm^STVzB6e;n>Rkzm0X`z zbo>ljk%2Kd03C`C>86OyYYK|@qs3SVBTu|vE%%y&^6Av{3qw#PFm!i^)zJ!=N~Y1g z0xXdkWlcfRR9ePBNZ0OwehQ^usQ8k>puz@R5L7ss_CtTn8&vCQO+l%fmL3ir#iLHRE@e4;M-*u95DqNOQNlRTuxh0@ zh~>r9)^&bY2%ZeCM|@$ZJ&n8+To_#YY3>hAfr+COTo{_dT#a9?m~NL>jHT>@?k>ZG~~T0$8(Ew~!O1nLTCN#np_!SxL$v30qYHVHfy52j@; zyfuOe;I`nbl)1Flk_*9gK~s>Wu!b!Imj!(`Zy*2-5WNm9sR&$_a?T>g{jtzUB2Jda z8%sVf0Z(NT2kw~aRH+N_Lhw<_fS!s{vH9Sh6acnzluAG&gHJLUBvcMUsIS2YtV~qm z@!+zKKW+m29k;Cs{+4a+fxm^R!{KkiM%@1|I`8M?-^gdlYvh^EzraiGU(NzK3*;=2 zvp~)QISb@0kh4I}0yzuhEReH6&I13ZEKn;7T>sP`6LF)uvbwUV3gS;xR@a)4>BmF@ z&@&0h^kd>f=$YWue*aXAwm-l$Nm3C znYjF&^55mZ%2&!~%3I`!e7Jmw+$8TO7s^KG7tXhxPdV>$UhUlJ+~SNl4|g8oY;x}B zEO2s;&m3<#o^agZxYDu1aWtF>Sm9XcsCG{|{oVEl+l#jQZ8zA?wQaRUY=_wv*=lSPZIbl0^q%yrbdPimoDn!iS|=@+7QiWi zagu2Lv-NH3lh!+|S6ENCZn6fgJ=TM)v#iBdBb*g@!}4p(ZI(+dCtF4>K1-Knf6IOr zm-&11C+1hp51Vf`UuZtT95WwbKE&K$o?>>2e;5BCz9`-=-XNX}=LRC;VPczDC63s^H}R#(%&+ z$KS(W&F|ok;)DD${y=^P?=pU8+--cxc)#&_Yz5#)4+e53siR|Yt5#(fsyye+vTq)QiN04rYykgn+t`zKzBgjb% zdFk^dt`uyHBglyixikL<*R`mwz(0c%#en2 z?sTPKj~hWcDRRT#*S+pa!QM84bTH%>hgG>!u&<3E?F{+hx0_rk*wsdmR)%~d5O$?t zM;k#}M55=0r@z_lO2LLUf;3a*H#~J{%$0(@Yy>GX_J=R5aHU`?8$rV17Bt9)+m^iV zO2H;Jg5(+dZIfSerC|FSK^htRt$C-pQm}Q6AUQ^P^RgFRDcHG&NbUzldDC0ByHc=g zjUc~g$Q!=?!j*zOYXtcnV<$-1twxalP$^R&6ZWbR zGIoN5U1tRO2}2(D-CtcP*l9+PyBTuZr5CwUu)mBTKV~us61JBSqg&;qm$k8u4-*VxB7lM4BAs;b9ZNi>1f_#r5@8QpM z;V~D2{5@4^G&T837anaP$afhfB9CRbcNk&vz++s;Fx=aWF7er*>u831OU3ofcWq|4 zHyJK^zQJ`A!@a@eh5mA)YZJr$meGY)tZ|Jo+-nRM;J$WkWVqK&q*sjk=RM}yz;Lfp zd5OxOceq9w?iEUxnEk|wt|Y^~Oywoqt4?qw816-eb1i$#6=%4Ym^|04CtWdydx6o( zJIh>0GTifw&UUfOHNtSuF*>Q}XRav2J$@{-HXa1SuLm&+0^AH&_p=w3Ry z-Q{Jtdl~M9>t1rLWw>84-WO6&xCR*R9!B@b^L~yNTh>PW{T&%WywqxE;6N@9JT= z8yW75T}jt6hP#2`PFw!AtDE7jXSh=*p5$7}aMv;1$q&qOburwv47Yhl!qv%eS25iB zE537eFx-_47uphb9m;UKSlI@a-0wPs;VxrzM>KA9wKLqMjBd?-9@i3vyM)oL=6AUk zGu*|jt@XZspKB4rUBqz9e%Ih?W4H?$uKTKwTnicQd?v5!`n9fBhC7etyZGu8T?-iQ zTt?USO_8gG;m%<=&$?Z%`3$#{;pSW$aUINXXEEI5pPk}5h~Z9WxU%~qc%nqcb0Q zt&1%ixf2;3fB97|wrb=~V06YEt6gl-$Q@7Z7yEu%gNv;hx#K8r?7Ou;xY&}B+eUd~ z|5$pbi>(;B6vO>FINrq;jNBH+`^UnXd{{3UV1;okBisGurTMU0MAR{i>iy1X`LI?* zl$j~=`#(LN4=Y7P9nBcu`SXH&SSKQCGoyNIq(2{4iHI^WSx^6}Dj(K}h&qa)o}7Ao zKCBQCHO6E;6gw~<*N0YvXdEz-?bNp)Eal_s5K(i}C|nx?%J6L(g)2j(8plv2-{s@F z5UIXNqi|J-s4vqfToWSd8H)Pl7hmL0W~k@WC|nOB)kA3%t_BhHAVWRzhdf*hTCJcx zQT~^J!G$1T4Bx7ld|U-0+i4nGemO&(p`r3{1&EU7s(g94{6ow*4TEbxl>H6GT=7mG zF8mPlrG~*(A7Y+YG5NUU!~DxxX26CEJ|ucZBf`}l64hx$`MB0Y)QmI=S9*w=rJ?e0 zorj_xqN0v^H4hhgh&e;U;0g~hr)d~m-XZ2e4TEbt#LUnzxUfS^ImPrnk%y}~#LUt# zxTHf&orb~n9AG%A&uv>eWLV4@0JDsc03r_;a!5imM+~mwPz*ISVDfPZhb3jL>$aLE zJQ9E?j#WRP@?iO90Ms&S4kUtfAOgSBv$X*J&Ph3q#Q%R2UC{~hXY!li|6gEz!*soT zg7qT#NNYm&TD#>Q%MWs!rbk!6x;w(zELe`hoA6aLFt$+tQu^99a4<7ZC6_@Lv@#;J}E4PQ83cRcBM zNVv^$hw(PY_2zrc*P72VAMLmVzCUcUh>nEuO5-`kqZ~oUVUBjkJV&KtvZKIstixa& zhA$F-vcG44&Hj}A9GJ*7N35qotb*y5FD%blZn2zhe#1OqK1e*!w8k`Ecv{#h zc!h(6a{fF1H~d+AFE1G1F&<$ow7trwY){)B5I?m2!gj6gGTRyO?IURm%D36p*m`UW zP0w0yvla-uj7D37Z9m&MK4Gr0S*35q6T}heQ}IdTLd${XC#3hKSER?JJEfmXyQFia z)1+hhkEJ7}pm?}=kF-)+EbTAN6@O5qykB@{$Tyux*MyP{>$g58`TqDcy^on z95MQ1;oN6Vev(l;iNgJd{jrR%H`1^M1Ebzp$P4GQNzef9 z6Cz1Hug-n!;3pWv${cy1H02|t8v-_x(H~F<91#rA#1Anss3-}N z_(2{&)yR&X5ybnL?287*$lH6!tA!lkeqRIuG4%)12+_NlMDL(M)Pre+;B6aU#tg#! z4pZSK;y9d6r3$?z^OJ!d&#MvYH%Xz@gFM_D$e^BEBLu&-^X0~Pcx0qf zHGd(K>v?=72jd9Gb0k$O$FnFPeL#+oJd;WCG$m0F$`O*MGV^#6t)U*6BLq)m%6J@K z;qYpVs`wkE&uE>$#%7~zgo~iVc#SK$J(fmxcq~)Wqgn%f1cj)_?ntH&(@F^|2?ata zz$s_$AvBo}4v4PDQ*8wGV5aI1X!7pI8mFiAh_w4k_-Z4Zz6=H0;mj)D9ZZ$KH&dZs zVHU&QjV;N+PVWfeyayZPx~Q)&+6t%qRP5cvj@q$5LU~sqKilXHhk?1u`dC;_a@BsZa?IK}|*B@+p?!~YB^DORJr5v7l4z3c{*uIITP%MRxv zLo`4McO9xtWMC`=qQJFgKHr!Oao1S*0_bCL?rO|u7>>^>F;dG|+^f(4>fuMicI5E#o=UjAkJN$X@OlRNN57#h-I9(}~+ z*@5^-LsuMtDq*;a{qy-5hKvvu&8WK;mZAwQtcId!L>1EECmJwE7ILB<)zOEUsKZ1S zTA~(3YT+bmP)a(4L^bB1hK;Dg7d2GGTol2=LsVjd8WO^T1)*Ue=3qfE^uuh-LkssX z3(3_G4;A>LF8XI;fisr#GcX&rhTad0pT4y1ZtrK%vd58K0ri`G*8V08iA8ns?Ik0 zXA-H+a1x-3GMy`<{4B@Ix1n=5Nxn_~qx`yjhUGJ%M&4w(R`y#q%gZc%@_h3*a<%y- zd7AkaxzK#FxyL+T7R&+XU(FW&Sm$oB-uYWG&-tY3Ugy2SZs+yF1ExOb#X`ID6k)vc z82&bAlwa=j8^3n;!S{hy;|g^WdE)Gar@o& z>jlAnj{Ri&(e@F$-`;OuAlx8CEp?`A_|JuN?bYTg`y{)|F4(@dePVmZ_MB;f_^|D2 z+XLW@p9h}!k+y(sx$RJ4yL`9hCChp6jbp0$BiKD~nR!gSRh(w}L3oXSn?HwdHhyS) z(0G9{X6!Z=8h&fr-|%Z&rEQYwB3r(Vm;NSwB)u*@A>AeaOu7j?^c})#h-2vF&C(Vr zBCR!jDRoNoOtVccX^!bA^91oyX|j|LKKkd@53Mg-AGh9Ty~()0^%Cn2;ak&?b&GY_ zdW3bE=}gn})`k3|)@tj1)-tQp@;z3U{+~;jYS4R;leyROgh__97eASMwN#jE*wd4o z%)LS=HD7Wv_cCQw*CB51r9xqbA=969b1xPN6^1O2auWAKChsKfd4kZq%1PXFltT3@ zCvwjcLFusp7daETXEMnqa8ENbb<9Ar3EWee`HknEED)xHt}G-A5{>7c$dpyiJx&ms zms!sJrcjt}%v|(6!u@)@P;cD3tN94`SfGmPL7=-tlyxd$@~RmMG_$u8sW&le^`J(5^4D7lQguS}>m?8W~q&IzxofRLz5$%pLhc$#D8Nn~FXXN!HIeDK7IIe+ zE2$G27QB$V(k;w0?%R32oV$V;n)A+QP_D`0&gL#4wWf=hn$Mk|sZ2h1-bCR5 z!@fM*eD2(FLakwMzHL5tj@GO4xwA>@(k6Z^cs{o?JNrEDELoTUUy{`@t=yTU*{8kS zJZ^`EVIf($Gnj0hr<=!}PRpVCx-xefp~~=fW$x6>(mJ_Qh;+K_KqZ~r$%I7nc^%wI zqzcvL2ogEC?U{1y+=-+`rI#s4X6H`Wa~Ryp9iN$jjXRF^PJL)pZkuLH8@H8?5a~4! z3b%2oOdTX{%Q&Ilu*X^miKSy@n7z`ju=SWy7~-;4NJwZs+6BXXhC94zb0)9lCgVQbb}oRB<30mqXbXlktRuodiPjJ5K`(O3vu$oB96wK z&{|Z#cuY8w@ao-UVT5R)Im$wmvJ+QXh|omUSr&%ryXr0rVWJj^6}sLglo+VXEUe3e z8A9hY3n43vBnFHIIz%LBjnsEbh2}g93dw^+`3w-b;3KQCJ^fUg>Ou=X zQa&KioM^%85XvC~7QJ&V$xi1;3j;Je)s+^GpdwXgT3AEuLEUNLaH!^o>QhJcKAgoNl3= zm`iiJg(c)&bG(JcL?;rtauH#p@haPhKs8F`Lh`1@rfenJvWS!mh~0EfxX?oMPrKp5 zd{XIpM_f3V2vj3Y9z+DP_>%M33yJP`AbDZ2Bo82}k_eLf7r=Tm(l30ziNuHX^4!?-vXrVgoLIrtM-F9InF-nHxF3cd= zs*xA>BZbsE@4|EY4hUN7h)0`lYexK>|3s#~gizY}#Q^y~iy<)a#(mm2&4s`1$NRx2= zN_;~wcDX_Qp>ZHnEZfzxBLtFCizBw7fw+QeJO6-KN-DZBwQ1q}QZNq}9?y>mMPO|54VJ)~S}=mIo|n zfggRKCExso`F7ZY-*292c8Gr#pAjz>Lt>q1HN9uL({#D%MAM+D%~TFC`kxTa5~9L^ zf|Y-mzkpBho%}fCM-Y+!Y~!%;U}J&dE5i$hs|}kCore9muSk(l^S%5lUoCNl5{S)c zG=jGjj>Z-8$I4x4;H9~TLE`M$G!dqw4FmD@5F{TQLKrYIUx9)9hctZ^FieI3lPHZ) zj6jIpc=`#+zLGpEfvf`JMQUWpL?{da8R7S06sx@<`DfCM6+k`}VpD45^!F@6OCOQ& zBWc!hAe;fgbd3fB{0J5b2L>QCY;rgf&v*f1zci&EXeU8bO{68=bO3%})EX7 zG-VK96KUweh5m)qMbfNZU2cOg>#!e;LV=7ID|cC&G^Yn>Nr^!cj(-Et0|$sxllcbJ zb<*@@K&_fF8d(|)c0;s#_!&@rvT~PjpGecYb!2FaUie)rNlZwekn9y{)>56GBtRxu zWf*>#31qwg@u5<67tnej)F){U5FlHLz%OC+hXq(gWWHOubBzy3)t!4|p|(h~uyLwMiul5X-izIgoP?Az%pTnTd10h!Hp#)IuFHM{e6y*@fo@f^hgNRWe zL;&eCq|$>Sy$CK9!SrA_G=l#jWvWzo5TxYi)09Xs5(I3yR51^*q_kki;bb@wV!!9= zpRL?Z!@1J*1A$cSbkq#ts5g*)0y6GHsp0^g#OMgwjWd9R`e!8lxm3G9kj|Y8DnaI` zD0F%Vr#yhS*G3b2Adu-ssk#}M)b^#LQI1T~(lR0B9a*lG<~9L~I!sf2wbqsOiVSB+ zQyYOn?O4On!2!4(02;FTVCBv-G)QF)KtxOp+T-Yg|1qgjDy!Ee4M8wu{EtcdNwe!9 zi44KmaHDY;)T5Ds1pHW;@q)xtq`9>~tSYXhhp;z7bbiK5Uy)&)i@Q!~TJY zvSDCDD3BP+d_!`V)C^&J4E6Q20w7R+cx;n0Kzxcg^jPS(d&2=M_l-2E3Rp=)gmNew zM+S!DgA5?Sr&7gSAW&NttQ>K?A$tP!&q(@#^VTDS{fT5vGM>c{W4yV_y%dlY#>%gNs>;@s(VDjv!&)) zK&YBb8*0I^ggFCZq(>5a!&$jgx%Z^n3Sd>6dj=V9BH06hOs`0jX9ANt(8ax@WUrD6 zk>p9Kc7{$a_?S^3f*n3|Hi++mK&Ho}=KZqD;ZMe5pg!YLh(6gkWW7hKo(`;P55$tk zp{8&X6*}4RY9jA9fJP?9;ery23!7F5z&qgBi1=9Sfz&vjr9l3~n zlF>jg79G|y-4`B21f`}aYGGki48=930WwI8D9|ML!~v&Inl>3YNm~QXbROv^plX+< zxph?Oc9?zws)MA7lYmMcyJN$o*bG>??JFhsL`YXhe^`1D0u=&9yEJ10P^hhxRV=!$ zx<@N_0(Yk59-k!&sZbO`AURf=Rt^+u!4k1CSQFsIN9iY^3Q5z)sZ`L*@%z>QnFZ5N zR&JYNn>4vh%?`gd zWW0i|>7)ku+pzsW_*;J>a@CxG@~cjm2!H1u-v@tZACJEMtmEdu-~G1r!r$pzkAlBb zw$6aRlT(MlU-xRGJe9LKZ^tlz9dHN0ozB@r;C8*A3*VTgTEDVAVVNRcZjMNw+wL`{q&K9; zY&Y_&jf;&@>(i#2tTWBGi<12%@nG=~akl+8##P38+eN}cp_V_?-eUV&+G={(ah>fI zd$E0vG$QBA6?_A~pM0oelk=~p@0}l7|6sja`ra|q(ZZYgvz#xPI^lM|u(;AVTQ=Im zmS-)8n4b}!wN#0}G#_W)DerWe?f=F9NjS;zj#02|Gh6xZV8?)H8*lHoeQ0g5mRRny zIL+<0x21FVd+a7bw#BTI;Meu@v%q(Zfpw0xj*8b#ZWw+gr$In`~){S(yt42 z+d20!ZgL#*#)r7wm=;vvP9L@GTr`_Z-Eha{W1v73HLObB?{AO48GpSxu>uQs_p~y6ax1o+6u}U9-#M( z!1fA?PzIEZFpb1HvWK6Hi%a018;x8-q}qt6Vc7i5J%XE;$(n>Qf}wFYJ@;@qY}SEq z3-G}}LByhHj8Vk7hcrQ$(ux;taSxKC7I;q;khMeOr056mzyZl~A?S`@qx+&nYmS@) zAbq3{@8{v}!wuO`b;!%zi^gRy;uceWMn<}3(Owd8no%#P`h?w|xNGf1LXnY57oAxY{iSE^3^+ z5!+3|8(u#Ezo&yE0vjhF2UcX2=z25*d?^WgN1!3%c7N_V)D%7Q0pB2ZExwQr1uxf- zAqrBstMMt}+gQn6g`5Au>E^D~P*-T3>T(UY3!lPDFu`4>;Vwn<_~62{=rDJQhP@cE zwDEEmY1j)f8*tjW3pCXESmHz!Ml|MQap$4ApfJ%Ge6WJY_=qo2$(@50KLp-iY#J=sUf_6DtElp#HG2=kydKZv_GiGPes?8+bt#2HD+#0QXrx`Y1A z6d%*gn~7eFTSl?#La$&x@Bqr7gY*%Z#B1;siNhfrG7l#^Z1Fdd)dl=)QX9G-Kn^3k zV6p-78^souKHC6f1B`amFtZ%W-2WonGO`hyJw5`;Zhh!R0kfO`$+9 z%Fq0*fNWn+Pi@Ooh3L%IjUuqJw25sg?x}^DHshmyR|b-17w<$-qyv%<^Bt%rF(Q7M zI25<)>OQX@GLdhA9pgarIWcZ2oV3E%^M1lt)r~bq6JTwE% z1wWJ>i0S&zya(Wo;<|6N^uzA{ST-G&e1vJn7Q|LP>V~~0G^_U2wUIP=Xip9JfW5OG zYf$?RitC&@l%iqiC%js07@1!`Yv{?DJ->HWW9ivv%qlF6{$u4_6hwy(_48yU8X&zA z@}NQ)Ul-?~@pT^&XJgJ`&-+z@%%j80HqEB8DH0?VkUe0NH&G^DUEA#rajzfPWFjw z61Fn+Yt}?Gi|(rx*|@KMpBj%s(jTJA@iqO$X&lN?zb%!a9Nj0RQY^FXvk(065FIHY zMCs2$#n?!QTMj-=9Ujud0VHEZLl!-WAs*e?3S2GGmZ=2Tcw_jR+#yiLH<{6wT@b@}If=$?0k(=uH9*$4x^vSmH$kN+tg; zAfN_onI9I4j3lw$p}T>kIEPbG0gv=g#nn9>g-76osQG5VEyBqgJ{1vl#g73){y9-e zxI1>#Y)4&1`7T5s3eo>|%Wuig%a6);$xq6U$oI;(%QwR>|GVT1;C8@Mw zI1BKR<6XyZ9WOebay;s|4s?>W1s3c-f@g$gJZ-Ia`+sp9es{Y$0EnU za5|vcG0QR4G2T(+a5~Hm&i*(1pY4CNe_;Qe{Z;#Oa9ZFY`#ttwKxD$J?U&lmgLD7e z?OWjF|A>9azSh3d-fdrEpKounSJ`LU-S$#@p50>SY~R?vuc-6h>3T?c0b&X;yb+u?k`MrlMElGeg0{%&cBG+%0xs-&5cTPl_EB=|yQ z{l@x*b+`3h>+9C%;iSNW*1KS*#dX$Q*7L19tlQzNz((tcb;!CF_Fi;bmssapo2*sV znO3*8)S73tSUJl#5U*f2e2;kD^1S77IF)c0#4flFzFnMe*>9t zx-CmA^DRx5D$7iZ+fr)Dvsf&g`5V~9vD^Hv`E~R2=Euzsn(s2-V!qD2%Y43hhk3hs zi+Q7Y#5`nPYhG#YHZL*HH#eE9V84gkTx!lUTg;sJjrfJQTYOi1U3^}ATzpWxOT0zA zPTVD)FYXYxi(ABv;)pmTt`%2`-Qp5)zSsmY8E1-au~f_xA#R508`Br2-KKX=Mowb_m;rEy6}&L>Lm*3M++fVTmvwB0N?JGX=L$ zD&z?kf#bj7zuzG z78}^uVCz36WiZKLg26b0F$Rxh5Ih0GA7v060rEb~V3@)6 z48roCq{G2f0*4qJWH88}!eD?wKZCHkCwyK8*D^T3;1LAMhBXWx&fsbSorc30T*cr@ z2I1f+$aNZ)GuY2yAAt@-FM~Y{E@QBp!KDP+4P6X>6c3p$s0vU^{_U!x9D;Gq{Ms zHU<|m*vjAn0!2d$gYy|Yn8AY>oX6mS2)Q2&2Qaulfu9?i3H;R1#9$+X4Gh*3_>rNG z!CD4u7_4Tniov-IRx;=z@Lj_k24@rarePL?6%5W~a0Y|>F*u#UX$(#!@VAC33{Gay z&EO;kCo(vJ!SMvXZYXDP9D`*HmNHnvU@?P53>Gq2z@Ur4dq#o*Tr ze#PKl8T<=_e`fGY2ESnNa|SB3 zGx#op?=bi_gTG_&Ee79Y@C^ok%i!w_zDD4S+^YmW!@a`b%M89m;8Wa-48FkN^9(-6 z;Ijli%ss>4(+obv;FAR2$34N|;{@Kt{f5C`Gx!*Tk23fOgAX(K5Q7gg_yB|VGk70^ z_cHh^2Ja#84(@IOf63j&;GGQK!Qkx#-opKo!Cx?V8-uqpcngC+XYghQZ({Ig1m4Wu z$lwhOUQggn+;t3I%iuK(Ud`ZD3|`6L6%1a^;4TI)WAIW2FJbUv1}|dpLIy8j@O%P) z#+}FDxeT7e;MolBWbiBo&tz~1gJ&>!I)kS%cq)UZFnBV9Co#C4!4nC*kvoCG;~6}T z!EFp~WiZ9y7Lhj^xEqh9;1~*yreHG#M^Uhef-wpSE(szC~Z6ett~DDYF@qrgkSS_%dzID&#T6dX>#m8&T@ zjDl4ZtfXKC1fi_6m(Otlz?-)DCnf1gMvdTID~?B3YJi?n1V$V zv=MO5LJC?bSU^Dw1@kF@4^L2y=Nv@9&Uq9ZNWlRV>`y^61x*B;)kr}D1@#ovQBX@k z4F%N{R8cUOf=UWJ6wIMuHUX#3qM(9;nH0>RU_T0`Q!tH!sT541U@`@60=7@0U?Kr0 zOrT&q1?2>68%IGI1*H^}P*6-k5e0=56j0!zAfJLf0w6Lq+7n_?6W{;JcB&v84?b7;qvfL?qALVISb@0 zkh4I}0yzuhEReH6&H_0L&U|7y+V%9XP~&H_0LXewnc3{ZC$Nxz3$a2Ag zObr2?6;v21xU|c?u&tvFiqqQC+uE|QZ4S$5A;bcJaCwmgmhWHYmNtTxUp5N!Wu;&l z_jfNuJF<*_giaZ?lA#lrD5Lb*nM3)rQU7jz@b0xW?!LB_w8q@6OFKHScwI}OfSOtR zyfHZGv&P-EyrrjgNlVYnn)><*QpNjVXvM>18-EH%-`I$fZd=%T98yJUirrkY!edBv zLZ~KXWAE6oFB)EmF`8(&GWr-9L@Tui2FS7WY$6A1`0ZT_+g7?)XD1KrO$KxY(#ZCp zUgMs*I+I~dMXJDNE@=fNTlcOc-k-O3)$IR5wKV5HRS3z}WK~4P@p+QD1R~{}1cyxF zbb5BNv)^r*!$WqmZfwX-(zoazF(j~#s&;fe_kUzWpvK8+xNLmNvY9%FEJ}vMW6K~0 zKnPB&2KFXk@4e(usDE7(RtG^=;ugOj!UlwV7(aDv-(*>>OB-$XYMkuR;XgBAbVU6m zXhlzS!@l)aiCRe<*FEX5H#b?$C2bzVRvYOk*~$+WUN-sg{G1)}eh4)^l^3C&n~Q9%>Sf4XH2?3 zc|QJM8+x*)w5;)#}KYwrDPyTcLIoRbiAjfPYj3UA36^+BZ}h zjY(@>Y6@HPKzC3vRN<__O-o%4w|YW|gFR-Ntp=011Y(J8n@3uqDvXNHd=oQUU}mDO z{izB12J;izoytzjlOFr4V9oN+hklh)E9;M8hM{fSm_T~siPO_Pku1rn6|y^mDbo(w z$vR79C;c}qvbRa>UzuWGgJF6~!X-YN-P+@*=^FQfcHQ!yrFFmswM%_)1btM2`7zzt z)v8$7wy34QqtC4d4#0Et5SVCqgb81?w5P3oaTjqkpt0^tFP(p&cPX+h`0t$~q3)x+ zxum+>keWo7e>5_dZd~uB7=hKfx(?lgPV1nIVP6wfMYmBbf#8v=NK=a+3F`?A#(HED zJ-@71KBJ*!CC-e%OgjfSD^g1g<`Reqx^7Nid7bky+nd%Q%RTUt`o#yt&9ny;Sz9sM}t+l_Ww|#lro-{4J?9(QG#OsAm zhpm0??1e#lz}?d8Uf_+huc>tD)*hJS-q(@?>04>Ia!QhB!39@Fa$?B6sAp;C9=WD{ z8SrhFcBNmbmg#rYyt{HQ>SdBF>aG0g>h2+esK0r$d&c22+yJ^OwPHd!^rcP=rFm)j zvZ@lPyVEr7U0v|$_z?J5yoV)_a#1gQ+f7qLVfIo>^Yr@QCj-^&IQ>g%?e zTx%E(>7Ob4W0V9{_odsObp#D`34G(;dt-68_Y%i1HCr~9tg0}i;L;xW*qJW)LT|!5 zkbYH5OI*P;8mU~FYs}2VeTmT4otfmg{7hriOxMg=O}wg#<3^ms>pQ7D%i}>k(tP+P zXD%Q!6Zh)tAlH9$IhmHOshoCLRFC6-&p%N8Bh|6gmr8TM^y;XDRQsR)3&>CRdH)-} zAzOfJKO3l}{15(40DU|6yI1aaFPsJ89~j~%fA`Dy9WM8~SLP25^y9TQ6=eU&^Z%dU zy)aT@?)?A%m1TZTkDLW^7RXs3XMvmrau�AZLM`1#%Y1Ss-VDoCW?f7Qo;CHwvAc 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 From 28cfad7fcdb05200b593a41019bf14fd596c864f Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Fri, 31 May 2019 00:53:47 +0200 Subject: [PATCH 0252/1002] Fix to allow on screen numbers without simplify and in jp client Fix to allow on screen numbers when simplify is set to false and in jp client. --- addons/battlemod/battlemod.lua | 35 +++++++++++----------------------- addons/battlemod/statics.lua | 1 + 2 files changed, 12 insertions(+), 24 deletions(-) diff --git a/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index 2b513bf553..e1e46e6f2d 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -132,35 +132,22 @@ windower.register_event('incoming text',function (original, modified, color, col modified = true end end - if filter_messages(original) then - blocked = true - return blocked + if not bm_message(original) and block_modes:contains(color) then + local endline = '[' .. string.char(0x7F, 0x31) .. ']' + if string.find(original, endline) then --allow add_to_chat messages with the modes we blocking + blocked = true + return blocked + end end return modified,color end) -function filter_messages(original) - for i, v in pairs(res.action_messages) do - if non_block_messages:contains(res.action_messages[i].id) then - local msg = res.action_messages[i].en - msg = msg:gsub("${actor}", "%%w+") - msg = msg:gsub("${target}", "%%w+") - msg = msg:gsub("${lb}", "") - msg = msg:gsub("${number}", "%%d+") - msg = msg:gsub(" ", "") - msg = msg:gsub("'", "") - msg = msg:gsub("-", "") - original = original:gsub("point ", "points ") - original = original:gsub("absorb ", "absorbs ") - original = original:gsub(" ", "") - original = original:gsub("'", "") - original = original:gsub("-", "") - original = original:gsub("?", "") - if original:match(msg) then - return true - end - 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 diff --git a/addons/battlemod/statics.lua b/addons/battlemod/statics.lua index e089cac282..b6b5caed77 100644 --- a/addons/battlemod/statics.lua +++ b/addons/battlemod/statics.lua @@ -34,6 +34,7 @@ passed_messages = T{4,5,6,16,17,18,20,34,35,36,40,47,48,49,64,78,87,88,89,90,112 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,185,186,188} black_colors = T{}--352,354,356,388,390,400,402,430,432,442,444,472,474,484,486} domain_buffs = S{ From 79e1cd7727cd6b34d3eda3a1c0ee351f78e08579 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Fri, 31 May 2019 02:42:51 +0200 Subject: [PATCH 0253/1002] Some more fixing Some more fixing --- addons/battlemod/battlemod.lua | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index e1e46e6f2d..11523a7ab1 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -132,9 +132,15 @@ windower.register_event('incoming text',function (original, modified, color, col modified = true end end - if not bm_message(original) and block_modes:contains(color) then - local endline = '[' .. string.char(0x7F, 0x31) .. ']' - if string.find(original, endline) then --allow add_to_chat messages with the modes we blocking + 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 + blocked = true + return blocked + end + elseif original:endswith(endline) and string.find(original, item) then --block items action messages blocked = true return blocked end @@ -144,8 +150,8 @@ windower.register_event('incoming text',function (original, modified, color, col end) function bm_message(original) - local check = '[' .. string.char(0x1E) .. ']' - local check2 = '[' .. string.char(0x1F) .. ']' + local check = string.char(0x1E) + local check2 = string.char(0x1F) if string.find(original, check) or string.find(original, check2) then return true end From f8f0b873719d633b37e8e29fa7e61ec6819f7c68 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Sun, 9 Jun 2019 19:26:06 +0200 Subject: [PATCH 0254/1002] [battlemod] Adding Steal/Despoil messages to simplify Adding Steal/Despoil messages to simplify and added one more blocking chat mode. --- addons/battlemod/parse_action_packet.lua | 19 ++++++++++++++++--- addons/battlemod/statics.lua | 4 +++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/addons/battlemod/parse_action_packet.lua b/addons/battlemod/parse_action_packet.lua index 09ec7bac1c..7a88004536 100644 --- a/addons/battlemod/parse_action_packet.lua +++ b/addons/battlemod/parse_action_packet.lua @@ -171,6 +171,7 @@ function parse_action_packet(act) elseif m.message == 32 then m.simp_name = 'dodged by' elseif m.message == 67 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 == 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' @@ -209,7 +210,7 @@ function parse_action_packet(act) elseif m.message == 85 or m.message == 284 then m.status = color_it('Resists',color_arr['statuscol']) elseif m.message == 351 then - m.status = color_it('status ailments',color_arr['statscol']) + 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 @@ -340,7 +341,7 @@ function simplify_message(msg_ID) local msg = res.action_messages[msg_ID][language] local fields = fieldsearch(msg) - if simplify and not T{23,64,125,129,133,139,140,153,204,210,211,212,213,214,244,350,442,453,516,531,557,565,582,593,594,595,596,597,598,599,674}:contains(msg_ID) then + if simplify and not T{23,64,129,133,139,140,204,210,211,212,213,214,244,350,442,453,516,531,557,565,582,674}: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,659,158,245,324,658}:contains(msg_ID) then fields.status = true end @@ -352,11 +353,17 @@ function simplify_message(msg_ID) fields.ability = true end - if T{152,160,161,162,163,164,165,166,167,168,229,652}:contains(msg_ID) then + if T{125,593,594,595,596,597,598,599}:contains(msg_ID) then + fields.ability = true + fields.item = true + end + + if T{152,153,160,161,162,163,164,165,166,167,168,229,652}:contains(msg_ID) then fields.actor = true fields.target = 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 @@ -367,6 +374,12 @@ function simplify_message(msg_ID) 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 diff --git a/addons/battlemod/statics.lua b/addons/battlemod/statics.lua index b6b5caed77..6f98664ecc 100644 --- a/addons/battlemod/statics.lua +++ b/addons/battlemod/statics.lua @@ -34,7 +34,7 @@ passed_messages = T{4,5,6,16,17,18,20,34,35,36,40,47,48,49,64,78,87,88,89,90,112 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,185,186,188} +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} domain_buffs = S{ @@ -79,6 +79,7 @@ line_aoebuff = '${actor} ${abil} '..string.char(129,168)..' ${target} (${statu 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}' @@ -89,6 +90,7 @@ default_settings_table = {line_aoe = 'AOE ${numb} '..string.char(129,168). 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}', From 2f822f31cbacca8aeb64e96e77c97bc57c8ada5e Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Mon, 10 Jun 2019 09:58:36 +0200 Subject: [PATCH 0255/1002] Added Larceny message Added Larceny message --- addons/battlemod/parse_action_packet.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/battlemod/parse_action_packet.lua b/addons/battlemod/parse_action_packet.lua index 7a88004536..396ef4d507 100644 --- a/addons/battlemod/parse_action_packet.lua +++ b/addons/battlemod/parse_action_packet.lua @@ -341,15 +341,15 @@ function simplify_message(msg_ID) local msg = res.action_messages[msg_ID][language] local fields = fieldsearch(msg) - if simplify and not T{23,64,129,133,139,140,204,210,211,212,213,214,244,350,442,453,516,531,557,565,582,674}: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,659,158,245,324,658}:contains(msg_ID) then + if simplify and not T{23,64,129,133,139,140,204,210,211,212,213,214,244,350,442,516,531,557,565,582,674}: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 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{152,161,162,163,165,229,384,603,652}:contains(msg_ID) then + T{152,161,162,163,165,229,384,453,603,652}:contains(msg_ID) then fields.ability = true end From 3558e87d9083222800800944acdcc2f53de96f95 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Sat, 15 Jun 2019 06:13:35 -0400 Subject: [PATCH 0256/1002] Relic Aug changes for WHM and BLM Doesn't break anyone's GS files with the way GS handles a single copy of an item in inventory. --- addons/libs/extdata.lua | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/addons/libs/extdata.lua b/addons/libs/extdata.lua index 9344fe16f1..4971fa1915 100644 --- a/addons/libs/extdata.lua +++ b/addons/libs/extdata.lua @@ -660,15 +660,15 @@ augment_values = { [0x538] = {{stat='Enhances "Invigorate" effect', offset=0,multiplier=0}}, [0x539] = {{stat='Enhances "Mantra" effect', offset=0,multiplier=0}}, - [0x53C] = {{stat='Enhances "Protectra V" effect', offset=0,multiplier=0}}, + [0x53C] = {{stat='Enhances "Afflatus Solace" effect', offset=0,multiplier=0}}, [0x53D] = {{stat='Enhances "Martyr" effect', offset=0,multiplier=0}}, - [0x53E] = {{stat='Enhances "Shellra V" effect', offset=0,multiplier=0}}, + [0x53E] = {{stat='Enhances "Afflatus Misery" effect', offset=0,multiplier=0}}, [0x53F] = {{stat='Enhances "Devotion" effect', offset=0,multiplier=0}}, - [0x542] = {{stat='Increases Ancient Magic II damage', offset=0,multiplier=0}}, - [0x543] = {{stat='Reduces Ancient Magic II casting time', offset=0,multiplier=0}}, - [0x544] = {{stat='Increases Ancient Magic II accuracy', offset=0,multiplier=0}}, - [0x545] = {{stat='Reduces Ancient Magic II MP cost', offset=0,multiplier=0}}, + [0x542] = {{stat='Increases Ancient Magic damage and magic burst damage', offset=0,multiplier=0}}, + [0x543] = {{stat='Increases Elemental Magic accuracy', offset=0,multiplier=0}}, + [0x544] = {{stat='Increases Elemental Magic debuff time and potency', offset=0,multiplier=0}}, + [0x545] = {{stat='Increases Aspir absorption amount', offset=0,multiplier=0}}, [0x548] = {{stat='Enhances "Dia III" effect', offset=0,multiplier=0}}, [0x549] = {{stat='Enhances "Slow II" effect', offset=0,multiplier=0}}, From e544df527799d515cba9cb5ad853a8d115a54e30 Mon Sep 17 00:00:00 2001 From: John Arnfield Date: Sun, 16 Jun 2019 10:26:30 +0100 Subject: [PATCH 0257/1002] Fix incoming sparks field As sparks are no longer capped at 50,000, use an unsigned int for sparks quantity rather than unsigned short. --- addons/libs/packets/fields.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 6564f46b0b..567688bada 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -3506,8 +3506,7 @@ fields.incoming[0x10B] = L{ -- Sparks update packet fields.incoming[0x110] = L{ - {ctype='unsigned short', label='Sparks Total'}, -- 04 - {ctype='unsigned short', label='_unknown1'}, -- 06 Sparks are currently capped at 50,000 + {ctype='unsigned int', label='Sparks Total'}, -- 04 {ctype='unsigned char', label='Unity (Shared) designator'}, -- 08 Unity (Shared) designator (0=A, 1=B, 2=C, etc.) {ctype='unsigned char', label='Unity (Person) designator '}, -- 09 The game does not distinguish these {ctype='char[6]', label='_unknown2'}, -- 0A Currently all 0xFF'd, never seen it change. From 90073a7dba98253ed23aec721b184b434e78aef6 Mon Sep 17 00:00:00 2001 From: ibm2431 Date: Wed, 26 Jun 2019 14:33:58 -0700 Subject: [PATCH 0258/1002] Update incoming price response packet from using 'Bag' to 'Type' --- addons/libs/packets/data.lua | 2 +- addons/libs/packets/fields.lua | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/addons/libs/packets/data.lua b/addons/libs/packets/data.lua index f5e8a036db..31df30741e 100644 --- a/addons/libs/packets/data.lua +++ b/addons/libs/packets/data.lua @@ -152,7 +152,7 @@ data.incoming[0x038] = {name='Entity Animation', description='Sent when a mod data.incoming[0x039] = {name='Env. Animation', description='Sent to force animations to specific objects.'} data.incoming[0x03A] = {name='Independ. Animation', description='Used for arbitrary battle animations that are unaccompanied by an action packet.'} data.incoming[0x03C] = {name='Shop', description='Displays items in a vendors shop.'} -data.incoming[0x03D] = {name='Value', description='Returns the value of an item.'} +data.incoming[0x03D] = {name='Shop Value/Sale', description='Returns the value of an item or notice it has been sold.'} data.incoming[0x03E] = {name='Open Buy/Sell', description='Opens the buy/sell menu for vendors.'} data.incoming[0x03F] = {name='Shop Buy Response', description='Sent when you buy something from normal vendors.'} data.incoming[0x041] = {name='Blacklist', description='Contains player ID and name for blacklist.'} diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 567688bada..86e0a39970 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2132,12 +2132,13 @@ fields.incoming[0x03C] = L{ {ref=types.shop_item, label='Item', count='*'}, -- 08 - * } --- Price response --- Sent after an outgoing price request for an NPC vendor (0x085) +-- Price/sale response +-- Sent in response to an outgoing price request for an NPC vendor (0x085), and in response to player finalizing a sale. +-- Inventory bag is assumed to be regular Inventory (0) fields.incoming[0x03D] = L{ {ctype='unsigned int', label='Price', fn=gil}, -- 04 {ctype='unsigned char', label='Inventory Index', fn=invp+{0x09}}, -- 08 - {ctype='unsigned char', label='Bag', fn=bag}, -- 09 + {ctype='unsigned char', label='Type'}, -- 09 0 = on apprasial, 1 = when sale is finalized {ctype='unsigned short', label='_junk1'}, -- 0A {ctype='unsigned int', label='_unknown1', const=1}, -- 0C } From 482a7d6317e83473613067ae7189dd7258de3205 Mon Sep 17 00:00:00 2001 From: ibm2431 Date: Wed, 26 Jun 2019 17:10:53 -0700 Subject: [PATCH 0259/1002] Requested comment changes to price response field values --- addons/libs/packets/fields.lua | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 86e0a39970..6b13ff3bf1 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2134,13 +2134,12 @@ fields.incoming[0x03C] = L{ -- Price/sale response -- Sent in response to an outgoing price request for an NPC vendor (0x085), and in response to player finalizing a sale. --- Inventory bag is assumed to be regular Inventory (0) fields.incoming[0x03D] = L{ {ctype='unsigned int', label='Price', fn=gil}, -- 04 {ctype='unsigned char', label='Inventory Index', fn=invp+{0x09}}, -- 08 - {ctype='unsigned char', label='Type'}, -- 09 0 = on apprasial, 1 = when sale is finalized + {ctype='unsigned char', label='Type'}, -- 09 0 = on price check, 1 = when sale is finalized {ctype='unsigned short', label='_junk1'}, -- 0A - {ctype='unsigned int', label='_unknown1', const=1}, -- 0C + {ctype='unsigned int', label='Quantity Sold', const=1}, -- 0C Will be 1 on price check } -- Open Buy/Sell From aa41b02fbe421da3b74318f317634d39e93dbc42 Mon Sep 17 00:00:00 2001 From: ibm2431 Date: Wed, 26 Jun 2019 17:20:38 -0700 Subject: [PATCH 0260/1002] Update inventory index function in price response --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 6b13ff3bf1..8e1b8bba18 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2136,7 +2136,7 @@ fields.incoming[0x03C] = L{ -- Sent in response to an outgoing price request for an NPC vendor (0x085), and in response to player finalizing a sale. fields.incoming[0x03D] = L{ {ctype='unsigned int', label='Price', fn=gil}, -- 04 - {ctype='unsigned char', label='Inventory Index', fn=invp+{0x09}}, -- 08 + {ctype='unsigned char', label='Inventory Index', fn=inv+{0}}, -- 08 {ctype='unsigned char', label='Type'}, -- 09 0 = on price check, 1 = when sale is finalized {ctype='unsigned short', label='_junk1'}, -- 0A {ctype='unsigned int', label='Quantity Sold', const=1}, -- 0C Will be 1 on price check From 85ccb8145705cf739ebd180ca0dbd84b7c4faf44 Mon Sep 17 00:00:00 2001 From: ibm2431 Date: Wed, 26 Jun 2019 17:25:41 -0700 Subject: [PATCH 0261/1002] Change 'Quantity Sold' in NPC price response to 'Count' to be inline with other fields --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 8e1b8bba18..26627c6e73 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2139,7 +2139,7 @@ fields.incoming[0x03D] = L{ {ctype='unsigned char', label='Inventory Index', fn=inv+{0}}, -- 08 {ctype='unsigned char', label='Type'}, -- 09 0 = on price check, 1 = when sale is finalized {ctype='unsigned short', label='_junk1'}, -- 0A - {ctype='unsigned int', label='Quantity Sold', const=1}, -- 0C Will be 1 on price check + {ctype='unsigned int', label='Count', const=1}, -- 0C Will be 1 on price check } -- Open Buy/Sell From 4fe0443f5935358a34179f28cdbcde3c45bf02f6 Mon Sep 17 00:00:00 2001 From: ibm2431 Date: Wed, 26 Jun 2019 17:29:18 -0700 Subject: [PATCH 0262/1002] Remove the const from the NPC price response packet --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 26627c6e73..868d4bb8db 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2139,7 +2139,7 @@ fields.incoming[0x03D] = L{ {ctype='unsigned char', label='Inventory Index', fn=inv+{0}}, -- 08 {ctype='unsigned char', label='Type'}, -- 09 0 = on price check, 1 = when sale is finalized {ctype='unsigned short', label='_junk1'}, -- 0A - {ctype='unsigned int', label='Count', const=1}, -- 0C Will be 1 on price check + {ctype='unsigned int', label='Count'}, -- 0C Will be 1 on price check } -- Open Buy/Sell From b3c48d4b93b78b2d44516ef1104fe4bd56c8b7c0 Mon Sep 17 00:00:00 2001 From: mcooper Date: Thu, 27 Jun 2019 22:16:33 -0700 Subject: [PATCH 0263/1002] Adding chatmodes for ls2. Showing valid chatmodes for //scoreboard help. Making error message a little more helpful for tells. --- addons/scoreboard/scoreboard.lua | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/addons/scoreboard/scoreboard.lua b/addons/scoreboard/scoreboard.lua index 97e1369d70..087f55babc 100644 --- a/addons/scoreboard/scoreboard.lua +++ b/addons/scoreboard/scoreboard.lua @@ -69,7 +69,7 @@ end -- Handle addon args windower.register_event('addon command', function() - local chatmodes = S{'s', 'l', 'p', 't', 'say', 'linkshell', 'party', 'tell'} + local chatmodes = S{'s', 'l', 'l2', 'p', 't', 'say', 'linkshell', 'linkshell2', 'party', 'tell'} return function(command, ...) if command == 'e' then @@ -87,6 +87,7 @@ windower.register_event('addon command', function() sb_output('sb reset : Reset damage') sb_output('sb report [] : Reports damage. Can take standard chatmode target options.') sb_output('sb reportstat [] [] : Reports the given stat. Can take standard chatmode target options. Ex: //sb rs acc p') + sb_output('Valid chatmode targets are: ' .. chatmodes:tostring():stripchars('{}"')) sb_output('sb filter show : Shows current filter settings') sb_output('sb filter add ... : Add mob patterns to the filter (substrings ok)') sb_output('sb filter clear : Clears mob filter') @@ -183,10 +184,14 @@ windower.register_event('addon command', function() if arg then if chatmodes:contains(arg) then - if arg2 and not arg2:match('^[a-zA-Z]+$') then - -- should be a valid player name - error('Invalid argument for report t: ' .. arg2) - return + if (arg == "t" or arg == "tell") then + if not arg2 then + -- should be a valid player name + error('Invalid argument for report t: Please include player target name.') + return + elseif not arg2:match('^[a-zA-Z]+$') then + error('Invalid argument for report t: ' .. arg2) + end end else error('Invalid parameter passed to report: ' .. arg) From 8b29b5fe51743f90743a662d610325d2557ff113 Mon Sep 17 00:00:00 2001 From: mcooper Date: Thu, 27 Jun 2019 22:25:57 -0700 Subject: [PATCH 0264/1002] Using single quotes and removing unnecessary parentheses. --- addons/scoreboard/scoreboard.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/scoreboard/scoreboard.lua b/addons/scoreboard/scoreboard.lua index 087f55babc..6a6c0fe399 100644 --- a/addons/scoreboard/scoreboard.lua +++ b/addons/scoreboard/scoreboard.lua @@ -87,7 +87,7 @@ windower.register_event('addon command', function() sb_output('sb reset : Reset damage') sb_output('sb report [] : Reports damage. Can take standard chatmode target options.') sb_output('sb reportstat [] [] : Reports the given stat. Can take standard chatmode target options. Ex: //sb rs acc p') - sb_output('Valid chatmode targets are: ' .. chatmodes:tostring():stripchars('{}"')) + sb_output('Valid chatmode targets are: ' .. chatmodes:concat(', ')) sb_output('sb filter show : Shows current filter settings') sb_output('sb filter add ... : Add mob patterns to the filter (substrings ok)') sb_output('sb filter clear : Clears mob filter') @@ -184,7 +184,7 @@ windower.register_event('addon command', function() if arg then if chatmodes:contains(arg) then - if (arg == "t" or arg == "tell") then + if arg == 't' or arg == 'tell' then if not arg2 then -- should be a valid player name error('Invalid argument for report t: Please include player target name.') From bf46c813638652ee6e141779d859203bd3320a9f Mon Sep 17 00:00:00 2001 From: mcooper Date: Fri, 5 Jul 2019 14:43:45 -0700 Subject: [PATCH 0265/1002] Allow sending target id of sender to other characters with . --- addons/send/readme.txt | 2 ++ addons/send/send.lua | 31 +++++++++++++++++++------------ 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/addons/send/readme.txt b/addons/send/readme.txt index 438b330bf3..4e83cfe0a8 100644 --- a/addons/send/readme.txt +++ b/addons/send/readme.txt @@ -5,3 +5,5 @@ If you wish to change the color of the text added from aecho. Or any plugin that windower.add_to_chat(55,msg:sub(5)) You may change the 55 to any number from 1 to 255 to get a (not always) different color. + +Can use from the user originating the send and it will replace the with the senders currently targeted mob id. diff --git a/addons/send/send.lua b/addons/send/send.lua index 89b094ddbf..b9aa4ab1a3 100644 --- a/addons/send/send.lua +++ b/addons/send/send.lua @@ -4,10 +4,19 @@ _addon.command = 'send' _addon.author = 'Byrth' windower.register_event('addon command',function (...) - local term = table.concat({...}, ' ') + local term = table.concat({...}, ' ') + + local target = windower.ffxi.get_mob_by_target('t') + if target then + term = term:gsub("", tostring(target.id)) + end + local broken_init = split(term, ' ') local qual = table.remove(broken_init,1) local player = windower.ffxi.get_player() + + + if qual:lower()==player['name']:lower() then if broken_init ~= nil then relevant_msg(table.concat(broken_init,' ')) @@ -80,17 +89,15 @@ end function relevant_msg(msg) local player = windower.ffxi.get_player() - msg:gsub("", tostring(player.name)) - msg:gsub("", tostring(player.vitals.hp)) - msg:gsub("", tostring(player.vitals.mp)) - msg:gsub("", tostring(player.vitals.hpp)) - msg:gsub("", tostring(player.vitals.mpp)) - msg:gsub("", tostring(player.vitals.tp)) - msg:gsub("", tostring(player.main_job_full)..'/'..tostring(player.sub_job_full)) - msg:gsub("", tostring(player.main_job_full)) - msg:gsub("", tostring(player.sub_job_full)) - - + msg = msg:gsub("", tostring(player.name)) + msg = msg:gsub("", tostring(player.vitals.hp)) + msg = msg:gsub("", tostring(player.vitals.mp)) + msg = msg:gsub("", tostring(player.vitals.hpp)) + msg = msg:gsub("", tostring(player.vitals.mpp)) + msg = msg:gsub("", tostring(player.vitals.tp)) + msg = msg:gsub("", tostring(player.main_job_full)..'/'..tostring(player.sub_job_full)) + msg = msg:gsub("", tostring(player.main_job_full)) + msg = msg:gsub("", tostring(player.sub_job_full)) if msg:sub(1,2)=='//' then windower.send_command(msg:sub(3)) From 638d1c8a0721012f21e196a7b15483a834ba4d8e Mon Sep 17 00:00:00 2001 From: mcooper Date: Fri, 5 Jul 2019 14:48:59 -0700 Subject: [PATCH 0266/1002] Deleting pointless code --- addons/send/send.lua | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/addons/send/send.lua b/addons/send/send.lua index b9aa4ab1a3..fcb958069d 100644 --- a/addons/send/send.lua +++ b/addons/send/send.lua @@ -89,16 +89,6 @@ end function relevant_msg(msg) local player = windower.ffxi.get_player() - msg = msg:gsub("", tostring(player.name)) - msg = msg:gsub("", tostring(player.vitals.hp)) - msg = msg:gsub("", tostring(player.vitals.mp)) - msg = msg:gsub("", tostring(player.vitals.hpp)) - msg = msg:gsub("", tostring(player.vitals.mpp)) - msg = msg:gsub("", tostring(player.vitals.tp)) - msg = msg:gsub("", tostring(player.main_job_full)..'/'..tostring(player.sub_job_full)) - msg = msg:gsub("", tostring(player.main_job_full)) - msg = msg:gsub("", tostring(player.sub_job_full)) - if msg:sub(1,2)=='//' then windower.send_command(msg:sub(3)) elseif msg:sub(1,1)=='/' then From d4297faf663fab327d8d207af0c0c69dc7149764 Mon Sep 17 00:00:00 2001 From: mcooper Date: Fri, 5 Jul 2019 14:50:22 -0700 Subject: [PATCH 0267/1002] Replacing quotes with tick marks --- addons/send/send.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/send/send.lua b/addons/send/send.lua index fcb958069d..d4348f0449 100644 --- a/addons/send/send.lua +++ b/addons/send/send.lua @@ -8,7 +8,7 @@ windower.register_event('addon command',function (...) local target = windower.ffxi.get_mob_by_target('t') if target then - term = term:gsub("", tostring(target.id)) + term = term:gsub('', tostring(target.id)) end local broken_init = split(term, ' ') From a4e17c8f93d7a63165f777bedd65551119b8164a Mon Sep 17 00:00:00 2001 From: mcooper Date: Fri, 5 Jul 2019 16:03:57 -0700 Subject: [PATCH 0268/1002] Adding lstid, for sub targetting. --- addons/send/readme.txt | 14 +++++++++++++- addons/send/send.lua | 5 +++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/addons/send/readme.txt b/addons/send/readme.txt index 4e83cfe0a8..549cf42042 100644 --- a/addons/send/readme.txt +++ b/addons/send/readme.txt @@ -6,4 +6,16 @@ windower.add_to_chat(55,msg:sub(5)) You may change the 55 to any number from 1 to 255 to get a (not always) different color. -Can use from the user originating the send and it will replace the with the senders currently targeted mob id. +Can use (stands for target id) from the user originating the send and it will replace the with the senders currently targeted mob id. + +/con send @others /ma "Blizzard IV" + +and another program, e.g. gearswap will resolve the target id to the monster and cast blizzard IV on the mob targeted by the sender. + +Can use (stands for last sub-target id) and works the same as but with the last sub-target. + +/ta +/con send //@others /ma "Blizzard IV" + +This would have all the other characters cast Blizzard IV on the last sub target from the sender. + diff --git a/addons/send/send.lua b/addons/send/send.lua index d4348f0449..9d008635cd 100644 --- a/addons/send/send.lua +++ b/addons/send/send.lua @@ -11,6 +11,11 @@ windower.register_event('addon command',function (...) term = term:gsub('', tostring(target.id)) end + local last_sub_target = windower.ffxi.get_mob_by_target('lastst') + if last_sub_target then + term = term:gsub('', tostring(last_sub_target.id)) + end + local broken_init = split(term, ' ') local qual = table.remove(broken_init,1) local player = windower.ffxi.get_player() From d9cee1c2716cf01f6599936f2c4ba9c4440fdd1e Mon Sep 17 00:00:00 2001 From: mcooper Date: Fri, 5 Jul 2019 20:10:14 -0700 Subject: [PATCH 0269/1002] Turned the readme into markdown and gave more information and examples --- addons/send/readme.md | 59 ++++++++++++++++ addons/send/readme.txt | 21 ------ addons/send/send.lua | 155 ++++++++++++++++++++--------------------- 3 files changed, 133 insertions(+), 102 deletions(-) create mode 100644 addons/send/readme.md delete mode 100644 addons/send/readme.txt diff --git a/addons/send/readme.md b/addons/send/readme.md new file mode 100644 index 0000000000..fc0e031cca --- /dev/null +++ b/addons/send/readme.md @@ -0,0 +1,59 @@ +## Usage +Syntax for the send command is send [playername, @others, @all, @job] [command] + +e.g. +``` +/con send @all /ma "Blizzard" +``` + +If you wish to change the color of the text added from aecho. Or any plugin that includes send atc. Near the end of the send.lua you will find the following: + +``` +windower.add_to_chat(55,msg:sub(5)) +``` + +You may change the 55 to any number from 1 to 255 to get a (not always) different color. + +## Sending mob ids through send + +You can send target ids from the sender to the receiver. Any addon could take advantage of this, but right now +it's especially adventageous to use with gearswap. Gearswap will resolve the mob id to the monster if it is within range. + +``` +/con send @others /ma "Blizzard" +``` + +This is faster than the current alternative of +``` +/con send @others /assist Player1 + +/con send @others /ma "Blizzard" +``` + +and more accurate than + +``` +/con send @others /ma "Blizzard" +``` + +because you may not always know what you are going to get with `` + +You can also use last sub target id for when you are engaged and don't want to switch targets. + +``` +/ta +/con send @others /ma "Blizzard" +``` + +`/ta ` will block execution until you are finished selecting a monster +then it will execute the next line. + +## List of target ids + +* `tid`: the id of the target +* `laststid`: last subtarget (e.g stnpc) +* `meid`: the id of yourself +* `petid`: player's pet id +* `stid`: current sub-target id +* `btid`: Party's enemy, is not guaranteed to return the same mob as +* `htid`: help target id \ No newline at end of file diff --git a/addons/send/readme.txt b/addons/send/readme.txt deleted file mode 100644 index 549cf42042..0000000000 --- a/addons/send/readme.txt +++ /dev/null @@ -1,21 +0,0 @@ -Syntax for the send command is send [playername, @others, @all, @job] [command] - -If you wish to change the color of the text added from aecho. Or any plugin that includes send atc. Near the end of the send.lua you will find the following: - -windower.add_to_chat(55,msg:sub(5)) - -You may change the 55 to any number from 1 to 255 to get a (not always) different color. - -Can use (stands for target id) from the user originating the send and it will replace the with the senders currently targeted mob id. - -/con send @others /ma "Blizzard IV" - -and another program, e.g. gearswap will resolve the target id to the monster and cast blizzard IV on the mob targeted by the sender. - -Can use (stands for last sub-target id) and works the same as but with the last sub-target. - -/ta -/con send //@others /ma "Blizzard IV" - -This would have all the other characters cast Blizzard IV on the last sub target from the sender. - diff --git a/addons/send/send.lua b/addons/send/send.lua index 9d008635cd..8df543b72c 100644 --- a/addons/send/send.lua +++ b/addons/send/send.lua @@ -4,105 +4,98 @@ _addon.command = 'send' _addon.author = 'Byrth' windower.register_event('addon command',function (...) - local term = table.concat({...}, ' ') - - local target = windower.ffxi.get_mob_by_target('t') - if target then - term = term:gsub('', tostring(target.id)) - end + local term = table.concat({...}, ' ') - local last_sub_target = windower.ffxi.get_mob_by_target('lastst') - if last_sub_target then - term = term:gsub('', tostring(last_sub_target.id)) - end + term = term:gsub('<(%a+)id>', function(target_string) + local entity = windower.ffxi.get_mob_by_target(target_string) + return entity and entity.id or '<' .. target_string .. 'id>' + end) - local broken_init = split(term, ' ') - local qual = table.remove(broken_init,1) - local player = windower.ffxi.get_player() + local broken_init = split(term, ' ') + local qual = table.remove(broken_init,1) + local player = windower.ffxi.get_player() - - - if qual:lower()==player['name']:lower() then - if broken_init ~= nil then - relevant_msg(table.concat(broken_init,' ')) - end - elseif qual:lower()=='@all' or qual:lower()=='@'..player.main_job:lower() then - if broken_init ~= nil then - relevant_msg(table.concat(broken_init,' ')) - end - windower.send_ipc_message('send ' .. term) - else - windower.send_ipc_message('send ' .. term) - end + if qual:lower()==player['name']:lower() then + if broken_init ~= nil then + relevant_msg(table.concat(broken_init,' ')) + end + elseif qual:lower()=='@all' or qual:lower()=='@'..player.main_job:lower() then + if broken_init ~= nil then + relevant_msg(table.concat(broken_init,' ')) + end + windower.send_ipc_message('send ' .. term) + else + windower.send_ipc_message('send ' .. term) + end end) windower.register_event('ipc message',function (msg) - local broken = split(msg, ' ') + local broken = split(msg, ' ') local command = table.remove(broken, 1) if command ~= 'send' then return end - if #broken < 2 then return end - - local qual = table.remove(broken,1) - local player = windower.ffxi.get_player() - if qual:lower()==player.name:lower() then - relevant_msg(table.concat(broken,' ')) - end - if string.char(qual:byte(1)) == '@' then - local arg = string.char(qual:byte(2, qual:len())) - if arg:upper() == player.main_job:upper() then - if broken ~= nil then - relevant_msg(table.concat(broken,' ')) - end - elseif arg:upper() == 'ALL' then - if broken ~= nil then - relevant_msg(table.concat(broken,' ')) - end - elseif arg:upper() == 'OTHERS' then - if broken ~= nil then - relevant_msg(table.concat(broken,' ')) - end - end - end + if #broken < 2 then return end + + local qual = table.remove(broken,1) + local player = windower.ffxi.get_player() + if qual:lower()==player.name:lower() then + relevant_msg(table.concat(broken,' ')) + end + if string.char(qual:byte(1)) == '@' then + local arg = string.char(qual:byte(2, qual:len())) + if arg:upper() == player.main_job:upper() then + if broken ~= nil then + relevant_msg(table.concat(broken,' ')) + end + elseif arg:upper() == 'ALL' then + if broken ~= nil then + relevant_msg(table.concat(broken,' ')) + end + elseif arg:upper() == 'OTHERS' then + if broken ~= nil then + relevant_msg(table.concat(broken,' ')) + end + end + end end) function split(msg, match) - if msg == nil then return '' end - local length = msg:len() - local splitarr = {} - local u = 1 - while u <= length do - local nextanch = msg:find(match,u) - if nextanch ~= nil then - splitarr[#splitarr+1] = msg:sub(u,nextanch-match:len()) - if nextanch~=length then - u = nextanch+match:len() - else - u = length - end - else - splitarr[#splitarr+1] = msg:sub(u,length) - u = length+1 - end - end - return splitarr + if msg == nil then return '' end + local length = msg:len() + local splitarr = {} + local u = 1 + while u <= length do + local nextanch = msg:find(match,u) + if nextanch ~= nil then + splitarr[#splitarr+1] = msg:sub(u,nextanch-match:len()) + if nextanch~=length then + u = nextanch+match:len() + else + u = length + end + else + splitarr[#splitarr+1] = msg:sub(u,length) + u = length+1 + end + end + return splitarr end function relevant_msg(msg) - local player = windower.ffxi.get_player() - - if msg:sub(1,2)=='//' then - windower.send_command(msg:sub(3)) - elseif msg:sub(1,1)=='/' then - windower.send_command('input '..msg) - elseif msg:sub(1,3)=='atc' then - windower.add_to_chat(55,msg:sub(5)) - else - windower.send_command(msg) - end + local player = windower.ffxi.get_player() + + if msg:sub(1,2)=='//' then + windower.send_command(msg:sub(3)) + elseif msg:sub(1,1)=='/' then + windower.send_command('input '..msg) + elseif msg:sub(1,3)=='atc' then + windower.add_to_chat(55,msg:sub(5)) + else + windower.send_command(msg) + end end From 27b9965aede98fb990e7a31195da475aa6143a44 Mon Sep 17 00:00:00 2001 From: mcooper Date: Fri, 5 Jul 2019 20:19:04 -0700 Subject: [PATCH 0270/1002] Changing headers in readme --- addons/send/readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/send/readme.md b/addons/send/readme.md index fc0e031cca..4f3abdf0c0 100644 --- a/addons/send/readme.md +++ b/addons/send/readme.md @@ -14,7 +14,7 @@ windower.add_to_chat(55,msg:sub(5)) You may change the 55 to any number from 1 to 255 to get a (not always) different color. -## Sending mob ids through send +### Sending mob ids through send You can send target ids from the sender to the receiver. Any addon could take advantage of this, but right now it's especially adventageous to use with gearswap. Gearswap will resolve the mob id to the monster if it is within range. @@ -48,7 +48,7 @@ You can also use last sub target id for when you are engaged and don't want to s `/ta ` will block execution until you are finished selecting a monster then it will execute the next line. -## List of target ids +#### List of target ids * `tid`: the id of the target * `laststid`: last subtarget (e.g stnpc) From 5cf2345ee46cd40cfd0dabc2b6a02bd8c23aa359 Mon Sep 17 00:00:00 2001 From: mcooper Date: Fri, 5 Jul 2019 20:23:59 -0700 Subject: [PATCH 0271/1002] Fixing small typo --- addons/send/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/send/readme.md b/addons/send/readme.md index 4f3abdf0c0..c637b0116b 100644 --- a/addons/send/readme.md +++ b/addons/send/readme.md @@ -17,7 +17,7 @@ You may change the 55 to any number from 1 to 255 to get a (not always) differen ### Sending mob ids through send You can send target ids from the sender to the receiver. Any addon could take advantage of this, but right now -it's especially adventageous to use with gearswap. Gearswap will resolve the mob id to the monster if it is within range. +it's especially advantageous to use with gearswap. Gearswap will resolve the mob id to the monster if it is within range. ``` /con send @others /ma "Blizzard" From a538789cef5f29d6a0514c5bc3028441b3ce2d5e Mon Sep 17 00:00:00 2001 From: mcooper Date: Fri, 5 Jul 2019 20:40:35 -0700 Subject: [PATCH 0272/1002] Making the readme more terse --- addons/send/readme.md | 41 +++++++++++------------------------------ 1 file changed, 11 insertions(+), 30 deletions(-) diff --git a/addons/send/readme.md b/addons/send/readme.md index c637b0116b..efe860b150 100644 --- a/addons/send/readme.md +++ b/addons/send/readme.md @@ -1,57 +1,38 @@ ## Usage -Syntax for the send command is send [playername, @others, @all, @job] [command] +Syntax for the send command is -e.g. ``` -/con send @all /ma "Blizzard" +send [playername, @others, @all, @job] [command] ``` -If you wish to change the color of the text added from aecho. Or any plugin that includes send atc. Near the end of the send.lua you will find the following: +Available send targets +* playername +* @others +* @all +* @job +e.g. ``` -windower.add_to_chat(55,msg:sub(5)) +/con send @all /ma "Blizzard" ``` -You may change the 55 to any number from 1 to 255 to get a (not always) different color. - ### Sending mob ids through send -You can send target ids from the sender to the receiver. Any addon could take advantage of this, but right now -it's especially advantageous to use with gearswap. Gearswap will resolve the mob id to the monster if it is within range. +The next two examples require gearswap to be loaded to use. These examples pass the mob id from the sender to the receiver. With the receiver having gearswap loaded, it will resolve the id to the correct monster if it is in range. ``` /con send @others /ma "Blizzard" ``` -This is faster than the current alternative of -``` -/con send @others /assist Player1 - -/con send @others /ma "Blizzard" -``` - -and more accurate than - -``` -/con send @others /ma "Blizzard" -``` - -because you may not always know what you are going to get with `` - -You can also use last sub target id for when you are engaged and don't want to switch targets. - ``` /ta /con send @others /ma "Blizzard" ``` -`/ta ` will block execution until you are finished selecting a monster -then it will execute the next line. - #### List of target ids * `tid`: the id of the target -* `laststid`: last subtarget (e.g stnpc) +* `laststid`: last subtarget * `meid`: the id of yourself * `petid`: player's pet id * `stid`: current sub-target id From dc005c88386ffc91dabd068954c7b8e74d9678e8 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Sat, 6 Jul 2019 14:11:00 +0900 Subject: [PATCH 0273/1002] Update readme.md --- addons/send/readme.md | 38 +++++++++++++------------------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/addons/send/readme.md b/addons/send/readme.md index efe860b150..e77c79f387 100644 --- a/addons/send/readme.md +++ b/addons/send/readme.md @@ -1,40 +1,28 @@ ## Usage -Syntax for the send command is ``` -send [playername, @others, @all, @job] [command] +//send ``` -Available send targets -* playername -* @others -* @all -* @job +The target can be the receiver's name, `@all` to send to all instances, `@other` to send to all instances excluding the sender or `@` to send to a specific job. The command can be any valid FFXI or Windower command. -e.g. +Examples: ``` -/con send @all /ma "Blizzard" +//send @all /ma "Blizzard" + +//send @whm /ma "Haste" + +//send Mymule //reload timers ``` -### Sending mob ids through send +## Sending entity IDs -The next two examples require gearswap to be loaded to use. These examples pass the mob id from the sender to the receiver. With the receiver having gearswap loaded, it will resolve the id to the correct monster if it is in range. +Entity IDs can be sent to the receiver by appending `id` to a target specifier, like `` for the target's ID. This works not just for `` but for all common targets mentioned [here](https://github.com/Windower/Lua/wiki/FFXI-Functions#windowerffxiget_mob_by_targettarget), i.e. ``, ` -``` +//send Mymule /ma "Stun" -``` /ta -/con send @others /ma "Blizzard" +//send Mymule /ma "Blizzard" ``` - -#### List of target ids - -* `tid`: the id of the target -* `laststid`: last subtarget -* `meid`: the id of yourself -* `petid`: player's pet id -* `stid`: current sub-target id -* `btid`: Party's enemy, is not guaranteed to return the same mob as -* `htid`: help target id \ No newline at end of file From 02b53eea0ed3cf44517feb3438478db354397fec Mon Sep 17 00:00:00 2001 From: Allonte Date: Sun, 7 Jul 2019 08:48:40 -0700 Subject: [PATCH 0274/1002] Improve Summoner CheckParams There was an issue where Blood Pact Damage would from Pet: and Avatar: did not add up together. My solution is to make all Blood Pact Damage to be Pet: Blood Pact Damage. --- addons/checkparam/checkparam.lua | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua index f923a23b4f..97d3fa1332 100644 --- a/addons/checkparam/checkparam.lua +++ b/addons/checkparam/checkparam.lua @@ -51,7 +51,7 @@ defaults = { SAM = 'store tp|double attack|triple attack|quadruple attack|weapon skill damage', NIN = 'store tp|double attack|triple attack|quadruple attack|subtle blow', DRG = 'store tp|double attack|triple attack|quadruple attack|weapon skill damage', - SMN = 'blood pact delay|blood pact delay ii|blood pact damage|avatar perpetuation cost|pet: magic attack bonus|pet: str|pet: double attack', + SMN = 'blood pact delay|blood pact delay ii|blood pact damage|avatar perpetuation cost|pet: magic attack bonus|pet: attack|pet: double attack|pet: accuracy|pet: magic accuracy|summoning magic skill|pet: blood pact damage|pet: magic damage', BLU = 'store tp|double attack|triple attack|quadruple attack|critical hit rate|critical hit damage|weapon skill damage|fast cast|magic attack bonus|magic accuracy|cure potency', COR = 'store tp|snapshot|rapid shot|fast cast|cure potency|magic accuracy|magic attack bonus|magic damage|weapon skill damage', PUP = 'pet: hp|pet: damage taken|pet: regen|martial arts|store tp|double attack|triple attack|quadruple attack', @@ -122,7 +122,13 @@ function get_text(id,data) local ext = extdata.decode({id=id,extdata=data}) if ext.augments then for i,v in ipairs(ext.augments) do - split_text(id,v) + local stats = windower.regex.split(v,'(Pet|Avatar|Automaton|Wyvern|Luopan): ') + if stats[2] then + local pet_text = windower.regex.replace(stats[2],'\n',' ') + split_text(id,pet_text,'pet: ') + else + split_text(id,v) + end end end if enhanced[id] then @@ -141,6 +147,9 @@ function split_text(id,text,arg) local key = windower.regex.replace(string.lower(key),'(\\"|\\.|\\s$)','') local key = integrate[key] or key local key = arg and arg..key or key + if key == "blood pact damage" then + key = "pet: blood pact damage" + end tbl[key] = tonumber(value)+(tbl[key] or 0) if settings.debugmode then log(id,res.items[id].english,key,value,tbl[key]) @@ -288,7 +297,7 @@ combination={ stats={['pet: accuracy']=15,['pet: magic accuracy']=15,['pet: ranged accuracy']=15},type=-1}, ['adhemar']={item=S{25614,25687,27118,27303,27474},stats={['critical hit rate']=2},type=0}, ['amalric']={item=S{25616,25689,27120,27305,27476},stats={['magic attack bonus']=10},type=0}, - ['apogee']={item=S{26677,26853,27029,27205,27381},stats={['blood pact damage']=2},type=0}, + ['apogee']={item=S{26677,26853,27029,27205,27381},stats={['pet: blood pact damage']=2},type=0}, ['argosy']={item=S{26673,26849,27025,27201,27377},stats={['double attack']=2},type=0}, ['emicho']={item=S{25610,25683,27114,27299,27470},stats={['double attack']=2},type=0}, ['carmine']={item=S{26679,26855,27031,27207,27383},stats={['accuracy']=10},type=0}, From 6d4fe40d8e6905d8fb8197dc71146cd1ac519715 Mon Sep 17 00:00:00 2001 From: Allonte Date: Sun, 7 Jul 2019 08:48:40 -0700 Subject: [PATCH 0275/1002] Improve Summoner CheckParams There was an issue where Blood Pact Damage would from Pet: and Avatar: did not add up together. My solution is to make all Blood Pact Damage to be Pet: Blood Pact Damage. --- addons/checkparam/checkparam.lua | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua index f923a23b4f..97d3fa1332 100644 --- a/addons/checkparam/checkparam.lua +++ b/addons/checkparam/checkparam.lua @@ -51,7 +51,7 @@ defaults = { SAM = 'store tp|double attack|triple attack|quadruple attack|weapon skill damage', NIN = 'store tp|double attack|triple attack|quadruple attack|subtle blow', DRG = 'store tp|double attack|triple attack|quadruple attack|weapon skill damage', - SMN = 'blood pact delay|blood pact delay ii|blood pact damage|avatar perpetuation cost|pet: magic attack bonus|pet: str|pet: double attack', + SMN = 'blood pact delay|blood pact delay ii|blood pact damage|avatar perpetuation cost|pet: magic attack bonus|pet: attack|pet: double attack|pet: accuracy|pet: magic accuracy|summoning magic skill|pet: blood pact damage|pet: magic damage', BLU = 'store tp|double attack|triple attack|quadruple attack|critical hit rate|critical hit damage|weapon skill damage|fast cast|magic attack bonus|magic accuracy|cure potency', COR = 'store tp|snapshot|rapid shot|fast cast|cure potency|magic accuracy|magic attack bonus|magic damage|weapon skill damage', PUP = 'pet: hp|pet: damage taken|pet: regen|martial arts|store tp|double attack|triple attack|quadruple attack', @@ -122,7 +122,13 @@ function get_text(id,data) local ext = extdata.decode({id=id,extdata=data}) if ext.augments then for i,v in ipairs(ext.augments) do - split_text(id,v) + local stats = windower.regex.split(v,'(Pet|Avatar|Automaton|Wyvern|Luopan): ') + if stats[2] then + local pet_text = windower.regex.replace(stats[2],'\n',' ') + split_text(id,pet_text,'pet: ') + else + split_text(id,v) + end end end if enhanced[id] then @@ -141,6 +147,9 @@ function split_text(id,text,arg) local key = windower.regex.replace(string.lower(key),'(\\"|\\.|\\s$)','') local key = integrate[key] or key local key = arg and arg..key or key + if key == "blood pact damage" then + key = "pet: blood pact damage" + end tbl[key] = tonumber(value)+(tbl[key] or 0) if settings.debugmode then log(id,res.items[id].english,key,value,tbl[key]) @@ -288,7 +297,7 @@ combination={ stats={['pet: accuracy']=15,['pet: magic accuracy']=15,['pet: ranged accuracy']=15},type=-1}, ['adhemar']={item=S{25614,25687,27118,27303,27474},stats={['critical hit rate']=2},type=0}, ['amalric']={item=S{25616,25689,27120,27305,27476},stats={['magic attack bonus']=10},type=0}, - ['apogee']={item=S{26677,26853,27029,27205,27381},stats={['blood pact damage']=2},type=0}, + ['apogee']={item=S{26677,26853,27029,27205,27381},stats={['pet: blood pact damage']=2},type=0}, ['argosy']={item=S{26673,26849,27025,27201,27377},stats={['double attack']=2},type=0}, ['emicho']={item=S{25610,25683,27114,27299,27470},stats={['double attack']=2},type=0}, ['carmine']={item=S{26679,26855,27031,27207,27383},stats={['accuracy']=10},type=0}, From 44b8323d615f1a03b8fedeed93c55c4833b57b5b Mon Sep 17 00:00:00 2001 From: Allonte Date: Sun, 7 Jul 2019 16:44:47 -0700 Subject: [PATCH 0276/1002] Update checkparam.lua --- addons/checkparam/checkparam.lua | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua index 97d3fa1332..71d8719ba0 100644 --- a/addons/checkparam/checkparam.lua +++ b/addons/checkparam/checkparam.lua @@ -116,19 +116,19 @@ function get_text(id,data) split_text(id,v) end if stats[2] then - local pet_text = windower.regex.replace(stats[2],'\n',' ') - split_text(id,pet_text,'pet: ') + stats[2] = stats[2]:gsub('\n', ''):trim() + split_text(id,stats[2],'pet: ') end local ext = extdata.decode({id=id,extdata=data}) if ext.augments then for i,v in ipairs(ext.augments) do - local stats = windower.regex.split(v,'(Pet|Avatar|Automaton|Wyvern|Luopan): ') - if stats[2] then - local pet_text = windower.regex.replace(stats[2],'\n',' ') - split_text(id,pet_text,'pet: ') - else - split_text(id,v) - end + local stats = windower.regex.split(v,'(Pet|Avatar|Automaton|Wyvern|Luopan): ') + if stats[2] then + stats[2] = stats[2]:gsub('\n', ''):trim() + split_text(id,stats[2],'pet: ') + else + split_text(id,v) + end end end if enhanced[id] then @@ -147,9 +147,9 @@ function split_text(id,text,arg) local key = windower.regex.replace(string.lower(key),'(\\"|\\.|\\s$)','') local key = integrate[key] or key local key = arg and arg..key or key - if key == "blood pact damage" then - key = "pet: blood pact damage" - end + if key == "blood pact damage" then + key = "pet: blood pact damage" + end tbl[key] = tonumber(value)+(tbl[key] or 0) if settings.debugmode then log(id,res.items[id].english,key,value,tbl[key]) From a8a22bd8bf207ee5af3a9e7b6375f15981ed732b Mon Sep 17 00:00:00 2001 From: Allonte Date: Sun, 7 Jul 2019 16:44:47 -0700 Subject: [PATCH 0277/1002] Update checkparam.lua --- addons/checkparam/checkparam.lua | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua index 97d3fa1332..71d8719ba0 100644 --- a/addons/checkparam/checkparam.lua +++ b/addons/checkparam/checkparam.lua @@ -116,19 +116,19 @@ function get_text(id,data) split_text(id,v) end if stats[2] then - local pet_text = windower.regex.replace(stats[2],'\n',' ') - split_text(id,pet_text,'pet: ') + stats[2] = stats[2]:gsub('\n', ''):trim() + split_text(id,stats[2],'pet: ') end local ext = extdata.decode({id=id,extdata=data}) if ext.augments then for i,v in ipairs(ext.augments) do - local stats = windower.regex.split(v,'(Pet|Avatar|Automaton|Wyvern|Luopan): ') - if stats[2] then - local pet_text = windower.regex.replace(stats[2],'\n',' ') - split_text(id,pet_text,'pet: ') - else - split_text(id,v) - end + local stats = windower.regex.split(v,'(Pet|Avatar|Automaton|Wyvern|Luopan): ') + if stats[2] then + stats[2] = stats[2]:gsub('\n', ''):trim() + split_text(id,stats[2],'pet: ') + else + split_text(id,v) + end end end if enhanced[id] then @@ -147,9 +147,9 @@ function split_text(id,text,arg) local key = windower.regex.replace(string.lower(key),'(\\"|\\.|\\s$)','') local key = integrate[key] or key local key = arg and arg..key or key - if key == "blood pact damage" then - key = "pet: blood pact damage" - end + if key == "blood pact damage" then + key = "pet: blood pact damage" + end tbl[key] = tonumber(value)+(tbl[key] or 0) if settings.debugmode then log(id,res.items[id].english,key,value,tbl[key]) From b99ec7cfaa9d2a3e3635782c30f803c5c2ee053d Mon Sep 17 00:00:00 2001 From: Allonte Date: Sun, 7 Jul 2019 18:49:54 -0700 Subject: [PATCH 0278/1002] Update checkparam.lua --- addons/checkparam/checkparam.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua index 71d8719ba0..587c28d306 100644 --- a/addons/checkparam/checkparam.lua +++ b/addons/checkparam/checkparam.lua @@ -116,7 +116,7 @@ function get_text(id,data) split_text(id,v) end if stats[2] then - stats[2] = stats[2]:gsub('\n', ''):trim() + stats[2] = stats[2]:trim() split_text(id,stats[2],'pet: ') end local ext = extdata.decode({id=id,extdata=data}) @@ -124,7 +124,7 @@ function get_text(id,data) for i,v in ipairs(ext.augments) do local stats = windower.regex.split(v,'(Pet|Avatar|Automaton|Wyvern|Luopan): ') if stats[2] then - stats[2] = stats[2]:gsub('\n', ''):trim() + stats[2] = stats[2]:trim() split_text(id,stats[2],'pet: ') else split_text(id,v) From a7033dd91738b84948aacff0081cd9371023531b Mon Sep 17 00:00:00 2001 From: Chiaia Date: Wed, 10 Jul 2019 09:43:32 -0400 Subject: [PATCH 0279/1002] Fandom changes --- addons/linker/linker.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/linker/linker.lua b/addons/linker/linker.lua index e274cc2311..e1832eb866 100644 --- a/addons/linker/linker.lua +++ b/addons/linker/linker.lua @@ -39,7 +39,7 @@ defaults.search.db = 'http://ffxidb.com/search?q=${query}' defaults.search.ah = 'http://ffxiah.com/search/item?q=${query}' defaults.search.bg = 'http://wiki.bluegartr.com/index.php?title=Special:Search&search=${query}' defaults.search.ge = 'http://ffxi.gamerescape.com/wiki/Special:Search?search=${query}' -defaults.search.wikia = 'http://wiki.ffxiclopedia.org/wiki/index.php?search=${query}&fulltext=Search' +defaults.search.wikia = 'https://ffxiclopedia.fandom.com/wiki/Special:Search?query=${query}' -- Miscallenous sites defaults.search.g = 'http://google.com/?q=${query}' From 468694b286f01e38697227567ed92cd7d0b45b97 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Wed, 10 Jul 2019 09:50:45 -0400 Subject: [PATCH 0280/1002] Fandom changes --- addons/Lookup/Lookup.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/Lookup/Lookup.lua b/addons/Lookup/Lookup.lua index 652c66273b..499f2a6016 100644 --- a/addons/Lookup/Lookup.lua +++ b/addons/Lookup/Lookup.lua @@ -42,7 +42,7 @@ function load_settings() default = 'ffxiclopedia'; sites = { ffxiclopedia = { - search = 'http://ffxiclopedia.wikia.com/wiki/Special:Search?go=Go&search=${term}'; + search = 'https://ffxiclopedia.fandom.com/wiki/Special:Search?query=${term}'; }; ['bg-wiki'] = { search = 'https://www.bg-wiki.com/bg/Special:Search?go=Go&search=${term}'; From 2cf6b39b9889c2d321a7ee1e7e9a809212ec4034 Mon Sep 17 00:00:00 2001 From: Rubenator Date: Wed, 10 Jul 2019 17:02:50 -0600 Subject: [PATCH 0281/1002] Use Correct URL Encoding --- addons/linker/linker.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/linker/linker.lua b/addons/linker/linker.lua index e274cc2311..0f37349e1f 100644 --- a/addons/linker/linker.lua +++ b/addons/linker/linker.lua @@ -1,4 +1,5 @@ require('luau') +url = require("socket.url") _addon.name = 'Linker' _addon.author = 'Arcon' @@ -53,7 +54,7 @@ windower.register_event('addon command', function(command, ...) if not ... or not settings.search[command] and settings.raw[command] then windower.open_url(settings.raw[command]) elseif settings.search[command] then - windower.open_url((settings.search[command]:gsub('${query}', L{...}:concat(' ')))) + windower.open_url((settings.search[command]:gsub('${query}', url.escape(L{...}:concat(' ')):gsub('%%','%%%%')))) else error('Command "' .. command .. '" not found.') end From b1cf0a845fef3cd859adaf10adf2d814d15e7f18 Mon Sep 17 00:00:00 2001 From: Rubenator Date: Wed, 10 Jul 2019 17:32:01 -0600 Subject: [PATCH 0282/1002] Correct styling and scope --- addons/linker/linker.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/linker/linker.lua b/addons/linker/linker.lua index 0f37349e1f..0cd9ae170b 100644 --- a/addons/linker/linker.lua +++ b/addons/linker/linker.lua @@ -1,5 +1,5 @@ require('luau') -url = require("socket.url") +local url = require('socket.url') _addon.name = 'Linker' _addon.author = 'Arcon' From 703d11b252658e6687534a57a0754495e5d52809 Mon Sep 17 00:00:00 2001 From: Rubenator Date: Wed, 10 Jul 2019 21:57:45 -0600 Subject: [PATCH 0283/1002] Currencies and Currencies 2 updates --- addons/libs/packets/fields.lua | 63 +++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index b8094a4fe7..d749d1d61a 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -3588,7 +3588,7 @@ fields.incoming[0x113] = L{ {ctype='signed int', label='Therion Ichor'}, -- A0 {ctype='signed int', label='Allied Notes'}, -- A4 {ctype='unsigned short', label='A.M.A.N. Vouchers Stored'}, -- A8 - {ctype='unsigned short', label='Unity Accolades'}, -- AA + {ctype='unsigned short', label="Login Points"}, -- AA {ctype='signed int', label='Cruor'}, -- AC {ctype='signed int', label='Resistance Credits'}, -- B0 {ctype='signed int', label='Dominion Notes'}, -- B4 @@ -3604,6 +3604,29 @@ fields.incoming[0x113] = L{ {ctype='signed int', label='Voidstones'}, -- C4 {ctype='signed int', label='Kupofried\'s Corundums'}, -- C8 {ctype='unsigned char', label='Moblin Pheromone Sacks'}, -- CC + {ctype='data[1]', label='_unknown2'}, -- CD + {ctype='unsigned char', label="Rems Tale Chapter 1"}, -- CE + {ctype='unsigned char', label="Rems Tale Chapter 2"}, -- CF + {ctype='unsigned char', label="Rems Tale Chapter 3"}, -- D0 + {ctype='unsigned char', label="Rems Tale Chapter 4"}, -- D1 + {ctype='unsigned char', label="Rems Tale Chapter 5"}, -- D2 + {ctype='unsigned char', label="Rems Tale Chapter 6"}, -- D3 + {ctype='unsigned char', label="Rems Tale Chapter 7"}, -- D4 + {ctype='unsigned char', label="Rems Tale Chapter 8"}, -- D5 + {ctype='unsigned char', label="Rems Tale Chapter 9"}, -- D6 + {ctype='unsigned char', label="Rems Tale Chapter 10"}, -- D7 + {ctype='data[8]', label="_unknown3"}, -- D8 + {ctype='signed int', label="Reclamation Marks"}, -- E0 + {ctype='signed int', label='Unity Accolades'}, -- E4 + {ctype='unsigned short', label="Fire Crystals"}, -- E8 + {ctype='unsigned short', label="Ice Crystals"}, -- EA + {ctype='unsigned short', label="Wind Crystals"}, -- EC + {ctype='unsigned short', label="Earth Crystals"}, -- EE + {ctype='unsigned short', label="Lightning Crystals"}, -- E0 + {ctype='unsigned short', label="Water Crystals"}, -- F2 + {ctype='unsigned short', label="Light Crystals"}, -- F4 + {ctype='unsigned short', label="Dark Crystals"}, -- F6 + {ctype='signed int', label="Deeds"}, -- F8 } -- Fish Bite Info @@ -3646,7 +3669,7 @@ fields.incoming[0x118] = L{ {ctype='signed int', label='Bayld'}, -- 04 {ctype='unsigned short', label='Kinetic Units'}, -- 08 {ctype='unsigned char', label='Coalition Imprimaturs'}, -- 0A - {ctype='unsigned char', label='_unknown1'}, -- 0B Currently holds no value + {ctype='unsigned char', label='Mystical Canteens'}, -- 0B {ctype='signed int', label='Obsidian Fragments'}, -- 0C {ctype='unsigned short', label='Lebondopt Wings Stored'}, -- 10 {ctype='unsigned short', label='Pulchridopt Wings Stored'}, -- 12 @@ -3699,11 +3722,41 @@ fields.incoming[0x118] = L{ {ctype='unsigned char', label='Pellucid Stones Stored'}, -- 45 {ctype='unsigned char', label='Fern Stones Stored'}, -- 46 {ctype='unsigned char', label='Taupe Stones Stored'}, -- 47 - {ctype='unsigned short', label='_unknown2'}, -- 48 + {ctype='unsigned short', label='Mellidopt Wings Stored'}, -- 48 {ctype='unsigned short', label='Escha Beads'}, -- 4A {ctype='signed int', label='Escha Silt'}, -- 4C - {ctype='unsigned short', label='Potpourri'}, -- 50 - {ctype='data[0x0E]', label='_unknown3'}, -- 52 Room for future additions, currently holds no value + {ctype='signed int', label='Potpourri'}, -- 50 + {ctype='signed int', label='Hallmarks'}, -- 54 + {ctype='signed int', label='Total Hallmarks'}, -- 58 + {ctype='signed int', label='Badges of Gallantry'}, -- 5C + {ctype='signed int', label='Crafter Points'}, -- 60 + {ctype='unsigned char', label='Fire Crystals Set'}, -- 64 + {ctype='unsigned char', label='Ice Crystals Set'}, -- 65 + {ctype='unsigned char', label='Wind Crystals Set'}, -- 66 + {ctype='unsigned char', label='Earth Crystals Set'}, -- 67 + {ctype='unsigned char', label='Lightning Crystals Set'}, -- 68 + {ctype='unsigned char', label='Water Crystals Set'}, -- 69 + {ctype='unsigned char', label='Light Crystals Set'}, -- 6A + {ctype='unsigned char', label='Dark Crystals Set'}, -- 6B + {ctype='unsigned char', label='MC-S-SR01s Set'}, -- 6C + {ctype='unsigned char', label='MC-S-SR02s Set'}, -- 6D + {ctype='unsigned char', label='MC-S-SR03s Set'}, -- 6E + {ctype='unsigned char', label='Liquefaction Spheres Set'}, -- 6F + {ctype='unsigned char', label='Induration Spheres Set'}, -- 70 + {ctype='unsigned char', label='Detonation Spheres Set'}, -- 71 + {ctype='unsigned char', label='Scission Spheres Set'}, -- 72 + {ctype='unsigned char', label='Impaction Spheres Set'}, -- 73 + {ctype='unsigned char', label='Reverberation Spheres Set'}, -- 74 + {ctype='unsigned char', label='Transfixion Spheres Set'}, -- 75 + {ctype='unsigned char', label='Compression Spheres Set'}, -- 76 + {ctype='unsigned char', label='Fusion Spheres Set'}, -- 77 + {ctype='unsigned char', label='Distortion Spheres Set'}, -- 78 + {ctype='unsigned char', label='Fragmentation Spheres Set'}, -- 79 + {ctype='unsigned char', label='Gravitation Spheres Set'}, -- 7A + {ctype='unsigned char', label='Light Spheres Set'}, -- 7B + {ctype='unsigned char', label='Darkness Spheres Set'}, -- 7C + {ctype='data[0x03]', label='_unknown1'}, -- 7D Presumably Unused Padding + {ctype='signed int', label='Silver A.M.A.N. Vouchers Stored'}, -- 80 } types.ability_recast = L{ From 78470831913d3dee1615a469731fa54b1771ce68 Mon Sep 17 00:00:00 2001 From: Rubenator Date: Wed, 10 Jul 2019 22:07:07 -0600 Subject: [PATCH 0284/1002] Fix merge --- addons/libs/packets/fields.lua | 3 --- 1 file changed, 3 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index c4e950977e..04116f62ec 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -3633,10 +3633,7 @@ fields.incoming[0x113] = L{ {ctype='unsigned short', label="Water Crystals"}, -- F2 {ctype='unsigned short', label="Light Crystals"}, -- F4 {ctype='unsigned short', label="Dark Crystals"}, -- F6 -<<<<<<< HEAD {ctype='signed int', label="Deeds"}, -- F8 -======= ->>>>>>> e34be6958ee92d50eb588115261e5a96a485e123 } -- Fish Bite Info From 3ff4c514531b3553558726806f77a37f9c0ae759 Mon Sep 17 00:00:00 2001 From: Noah Jorgensen Date: Wed, 10 Jul 2019 23:43:38 -0700 Subject: [PATCH 0285/1002] area.Cities + Chocobo Circuit --- addons/GearSwap/libs/Mote-Mappings.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/GearSwap/libs/Mote-Mappings.lua b/addons/GearSwap/libs/Mote-Mappings.lua index d2831d8c38..47e8b06b81 100644 --- a/addons/GearSwap/libs/Mote-Mappings.lua +++ b/addons/GearSwap/libs/Mote-Mappings.lua @@ -242,7 +242,8 @@ areas.Cities = S{ "Eastern Adoulin", "Western Adoulin", "Kazham", - "Rabao" + "Rabao", + "Chocobo Circuit", } -- Adoulin areas, where Ionis will grant special stat bonuses. areas.Adoulin = S{ From 0250f3961ea1ab908fee2a0a5b165278610e5e0f Mon Sep 17 00:00:00 2001 From: Rubenator Date: Thu, 11 Jul 2019 17:10:34 -0600 Subject: [PATCH 0286/1002] Bugfix for only 1 word searches, had to refactor to account for gsub returning 2 values --- addons/linker/linker.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/addons/linker/linker.lua b/addons/linker/linker.lua index 375df1fd92..01ad1fe0a8 100644 --- a/addons/linker/linker.lua +++ b/addons/linker/linker.lua @@ -54,7 +54,9 @@ windower.register_event('addon command', function(command, ...) if not ... or not settings.search[command] and settings.raw[command] then windower.open_url(settings.raw[command]) elseif settings.search[command] then - windower.open_url((settings.search[command]:gsub('${query}', url.escape(L{...}:concat(' ')):gsub('%%','%%%%')))) + local query_string = url.escape(L{...}:concat(' ')) + local adjusted_query_string = query_string:gsub('%%','%%%%') + windower.open_url((settings.search[command]:gsub('${query}',adjusted_query_string))) else error('Command "' .. command .. '" not found.') end From bb17167202f9b9af1d757e4f58010423bad02c88 Mon Sep 17 00:00:00 2001 From: Rubenator Date: Thu, 11 Jul 2019 18:17:16 -0600 Subject: [PATCH 0287/1002] style compliance --- addons/linker/linker.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/linker/linker.lua b/addons/linker/linker.lua index 01ad1fe0a8..13e6d407e4 100644 --- a/addons/linker/linker.lua +++ b/addons/linker/linker.lua @@ -55,8 +55,8 @@ windower.register_event('addon command', function(command, ...) windower.open_url(settings.raw[command]) elseif settings.search[command] then local query_string = url.escape(L{...}:concat(' ')) - local adjusted_query_string = query_string:gsub('%%','%%%%') - windower.open_url((settings.search[command]:gsub('${query}',adjusted_query_string))) + local adjusted_query_string = query_string:gsub('%%', '%%%%') + windower.open_url((settings.search[command]:gsub('${query}', adjusted_query_string))) else error('Command "' .. command .. '" not found.') end From 66dd0635379b071ead175b92682abc2a29ea3891 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Fri, 12 Jul 2019 02:56:36 -0400 Subject: [PATCH 0288/1002] giltracker and invtracker --- addons/addons.xml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/addons/addons.xml b/addons/addons.xml index ea4208223d..19a6410ac1 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -767,4 +767,18 @@ https://github.com/deadman80/Lua/issues https://www.ffxiah.com/user/Nyarlko + + giltracker + Sylandro + Displays the current gil, similar to the FFXIV Gil HUD widget. + https://github.com/Windower/Lua/issues + https://github.com/azamorapl + + + invtracker + Sylandro + Displays a grid detailing empty and filled inventory slots, similar to the FFXIV Inventory Grid HUD widget. + https://github.com/Windower/Lua/issues + https://github.com/azamorapl + From b0e98bc0e50d26c0502168901097590e060aea42 Mon Sep 17 00:00:00 2001 From: Allonte Date: Wed, 24 Jul 2019 05:39:38 -0700 Subject: [PATCH 0289/1002] Update checkparam.lua - Add Bladeborn/Flashsteel Earring set - Add Heartseeker/Dudgeon Earring set - Add in more relevant paramaters to THF's default --- addons/checkparam/checkparam.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua index 587c28d306..adfe103a0a 100644 --- a/addons/checkparam/checkparam.lua +++ b/addons/checkparam/checkparam.lua @@ -42,7 +42,7 @@ defaults = { WHM = 'cure potency|cure potency ii|fast cast|cure spellcasting time|enmity|healing magic casting time|divine benison|damage taken|physical damage taken|magic damage taken', BLM = 'magic attack bonus|magic burst damage|magic burst damage ii|int|magic accuracy|magic damage|fast cast|elemental magic casting time', RDM = 'magic attack bonus|magic burst damage|magic burst damage ii|magic accuracy|fast cast|enfeebling magic skill|enhancing magic skill|store tp|dual wield', - THF = 'store tp|double attack|triple attack|quadruple attack|dual wield', + THF = 'store tp|double attack|triple attack|quadruple attack|dual wield|critical hit rate|critical hit damage|haste|weapon skill damage', PLD = 'enmity|damage taken|physical damage taken|magic damage taken|spell interruption rate|phalanx|cure potency|fastcast', DRK = 'store tp|double attack|triple attack|quadruple attack|weapon skill damage', BST = 'pet: double attack|pet: magic attack bonus|pet: damage taken', @@ -316,4 +316,6 @@ combination={ ['jhakri']={item=S{25578,25794,25832,25883,25950},stats={['fast cast']=3},type=-1}, ['meghanada']={item=S{25575,25791,25829,25880,25947},stats={['regen']=3},type=-1}, ['Sulevia\'s']={item=S{25574,25790,25828,25879,25946},stats={['subtle blow']=5},type=-1}, + ['BladeFlashEarrings']={item=S{28520,28521},stats={['double attack']=7},type=-1} + ['HeartDudgeonEarrings']={item=S{28522,28523},stats={['dual wield']=7},type=-1} } From 68594225320945595c6661f34d6ca1a006e0eada Mon Sep 17 00:00:00 2001 From: Allonte Date: Wed, 24 Jul 2019 10:02:42 -0700 Subject: [PATCH 0290/1002] tabs to space-tabs --- addons/checkparam/checkparam.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua index adfe103a0a..01fe4d2b03 100644 --- a/addons/checkparam/checkparam.lua +++ b/addons/checkparam/checkparam.lua @@ -316,6 +316,6 @@ combination={ ['jhakri']={item=S{25578,25794,25832,25883,25950},stats={['fast cast']=3},type=-1}, ['meghanada']={item=S{25575,25791,25829,25880,25947},stats={['regen']=3},type=-1}, ['Sulevia\'s']={item=S{25574,25790,25828,25879,25946},stats={['subtle blow']=5},type=-1}, - ['BladeFlashEarrings']={item=S{28520,28521},stats={['double attack']=7},type=-1} - ['HeartDudgeonEarrings']={item=S{28522,28523},stats={['dual wield']=7},type=-1} + ['BladeFlashEarrings']={item=S{28520,28521},stats={['double attack']=7},type=-1} + ['HeartDudgeonEarrings']={item=S{28522,28523},stats={['dual wield']=7},type=-1} } From 8b618ea4088df3dbc1a28327bc3d76ec6c3b4ca5 Mon Sep 17 00:00:00 2001 From: Allonte Date: Wed, 24 Jul 2019 14:44:00 -0700 Subject: [PATCH 0291/1002] Missed a comma --- addons/checkparam/checkparam.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua index 01fe4d2b03..ab6c81f8b3 100644 --- a/addons/checkparam/checkparam.lua +++ b/addons/checkparam/checkparam.lua @@ -316,6 +316,6 @@ combination={ ['jhakri']={item=S{25578,25794,25832,25883,25950},stats={['fast cast']=3},type=-1}, ['meghanada']={item=S{25575,25791,25829,25880,25947},stats={['regen']=3},type=-1}, ['Sulevia\'s']={item=S{25574,25790,25828,25879,25946},stats={['subtle blow']=5},type=-1}, - ['BladeFlashEarrings']={item=S{28520,28521},stats={['double attack']=7},type=-1} + ['BladeFlashEarrings']={item=S{28520,28521},stats={['double attack']=7},type=-1}, ['HeartDudgeonEarrings']={item=S{28522,28523},stats={['dual wield']=7},type=-1} } From 757d59050c4dd12f30a8b4eec20b1b4b7c4b5781 Mon Sep 17 00:00:00 2001 From: Allonte Date: Wed, 24 Jul 2019 17:59:51 -0700 Subject: [PATCH 0292/1002] Add in support to display stat caps - Add in support (display and color code) the params relative to the know (hard) cap - Do not display stat params that are converted to other stats --- addons/checkparam/checkparam.lua | 50 ++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua index ab6c81f8b3..e650d07f18 100644 --- a/addons/checkparam/checkparam.lua +++ b/addons/checkparam/checkparam.lua @@ -26,8 +26,8 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.]] _addon.name = 'Checkparam' -_addon.author = 'from20020516' -_addon.version = '1.2' +_addon.author = 'from20020516 & Kigen' +_addon.version = '1.3' _addon.commands = {'cp','checkparam'} require('logger') @@ -35,6 +35,7 @@ res = require('resources') extdata = require('extdata') config = require('config') packets = require('packets') +require('math') defaults = { WAR = 'store tp|double attack|triple attack|quadruple attack|weapon skill damage', @@ -150,7 +151,12 @@ function split_text(id,text,arg) if key == "blood pact damage" then key = "pet: blood pact damage" end - tbl[key] = tonumber(value)+(tbl[key] or 0) + if key == "damage taken" then + tbl['physical damage taken'] = tonumber(value)+(tbl['physical damage taken'] or 0) + tbl['magic damage taken'] = tonumber(value)+(tbl['magic damage taken'] or 0) + else + tbl[key] = tonumber(value)+(tbl[key] or 0) + end if settings.debugmode then log(id,res.items[id].english,key,value,tbl[key]) end @@ -175,9 +181,25 @@ function show_results(name,mjob,sjob) local head = '<'..mjob..'/'..(sjob or '')..'>' windower.add_to_chat(160,string.color(name,1,160)..': '..string.color(head,160,160)) for index,key in ipairs(windower.regex.split(stats,'[|]')) do - local value = tbl[string.lower(key)] - local color = {value and 1 or 160,value and 166 or 160} - windower.add_to_chat(160,' ['..string.color(key,color[1],160)..'] '..string.color(tostring(value),color[2],160)) + -- WA for blood pact damage showing when it is converted to pet: blood pact damage + -- WA for damage taken showing when it is converted to physical/magic damage taken + key = string.lower(key) + if key ~= 'blood pact damage' and key ~= 'damage taken' then + local value = tbl[key] + local color = {value and 1 or 160,value and 166 or 160, 106, 205, 61} + local stat_cap = caps[key] + local output_string = ' ['..string.color(key,color[1],160)..']' + if stat_cap == nil or value == nil then + output_string = output_string..' '..string.color(tostring(value),color[2],160) + elseif value == stat_cap then + output_string = output_string..' '..string.color(tostring(value),color[3],160)..'/'..string.color(tostring(stat_cap),155,160) + elseif math.abs(value) > math.abs(stat_cap) then + output_string = output_string..' '..string.color(tostring(value),color[4],160)..'/'..string.color(tostring(stat_cap),155,160) + else + output_string = output_string..' '..string.color(tostring(value),color[5],160)..'/'..string.color(tostring(stat_cap),155,160) + end + windower.add_to_chat(160,output_string) + end end tbl = {} end @@ -319,3 +341,19 @@ combination={ ['BladeFlashEarrings']={item=S{28520,28521},stats={['double attack']=7},type=-1}, ['HeartDudgeonEarrings']={item=S{28522,28523},stats={['dual wield']=7},type=-1} } + +caps={ + ['haste']=25, + ['subtle blow']=50, + ['cure potency']=50, + ['potency of cure effects received']=30, + ['physical damage taken']=25, + ['magic damage taken']=25, + ['pet: haste']=80, + ['magic burst damage']=40, + ['blood pact delay']=-15, + ['blood pact delay ii']=-15, + ['save tp']=500, + ['fast cast']=80, + ['reward']=50 +} \ No newline at end of file From 0229bf1034fee5acdad11755db504442f2ae66e4 Mon Sep 17 00:00:00 2001 From: Allonte Date: Wed, 24 Jul 2019 18:06:16 -0700 Subject: [PATCH 0293/1002] PDT/MDT should be negative --- addons/checkparam/checkparam.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua index e650d07f18..1255f6909b 100644 --- a/addons/checkparam/checkparam.lua +++ b/addons/checkparam/checkparam.lua @@ -347,8 +347,8 @@ caps={ ['subtle blow']=50, ['cure potency']=50, ['potency of cure effects received']=30, - ['physical damage taken']=25, - ['magic damage taken']=25, + ['physical damage taken']=-25, + ['magic damage taken']=-25, ['pet: haste']=80, ['magic burst damage']=40, ['blood pact delay']=-15, From f7814518ae371eb31660d2b52a5e0efb024de71d Mon Sep 17 00:00:00 2001 From: Allonte Date: Sat, 3 Aug 2019 11:57:02 -0700 Subject: [PATCH 0294/1002] Add support for the alias "Quick Cast" Quick Cast is the alias for 'occassionally quickens spellcasting' that caps out at 10% --- addons/checkparam/checkparam.lua | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua index 1255f6909b..2814269025 100644 --- a/addons/checkparam/checkparam.lua +++ b/addons/checkparam/checkparam.lua @@ -40,9 +40,9 @@ require('math') defaults = { WAR = 'store tp|double attack|triple attack|quadruple attack|weapon skill damage', MNK = 'store tp|double attack|triple attack|quadruple attack|martial arts|subtle blow', - WHM = 'cure potency|cure potency ii|fast cast|cure spellcasting time|enmity|healing magic casting time|divine benison|damage taken|physical damage taken|magic damage taken', + WHM = 'cure potency|cure potency ii|fast cast|quick cast|cure spellcasting time|enmity|healing magic casting time|divine benison|damage taken|physical damage taken|magic damage taken', BLM = 'magic attack bonus|magic burst damage|magic burst damage ii|int|magic accuracy|magic damage|fast cast|elemental magic casting time', - RDM = 'magic attack bonus|magic burst damage|magic burst damage ii|magic accuracy|fast cast|enfeebling magic skill|enhancing magic skill|store tp|dual wield', + RDM = 'magic attack bonus|magic burst damage|magic burst damage ii|magic accuracy|fast cast|quick cast|enfeebling magic skill|enhancing magic skill|store tp|dual wield', THF = 'store tp|double attack|triple attack|quadruple attack|dual wield|critical hit rate|critical hit damage|haste|weapon skill damage', PLD = 'enmity|damage taken|physical damage taken|magic damage taken|spell interruption rate|phalanx|cure potency|fastcast', DRK = 'store tp|double attack|triple attack|quadruple attack|weapon skill damage', @@ -230,6 +230,8 @@ integrate = { ['mag dmg'] = 'magic damage', ['crithit rate'] = 'critical hit rate', ['phys dmg taken'] = 'physical damage taken', + ['occ. quickens spellcasting']="quick cast", + ['occassionally quickens spellcasting']="quick cast" } enhanced = { [10392] = 'cursna+10', --Malison Medallion @@ -347,6 +349,7 @@ caps={ ['subtle blow']=50, ['cure potency']=50, ['potency of cure effects received']=30, + ['quick cast']=10, ['physical damage taken']=-25, ['magic damage taken']=-25, ['pet: haste']=80, From 9f53ad65e40c424eb1cf231013960718f12e374d Mon Sep 17 00:00:00 2001 From: funkworkz Date: Fri, 9 Aug 2019 09:57:51 -0500 Subject: [PATCH 0295/1002] Update setbgm.lua Song names released with the soundtrack FINAL FANTASY XI Gifts from Vana'diel: Songs of Rebirth OST. --- addons/setbgm/setbgm.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/setbgm/setbgm.lua b/addons/setbgm/setbgm.lua index 383a9f73d1..045b65d79b 100644 --- a/addons/setbgm/setbgm.lua +++ b/addons/setbgm/setbgm.lua @@ -54,7 +54,7 @@ songs = { [50]='Feast of the Ladies', [51]='Abyssea - Scarlet Skies, Shadowed Plains', [52]='Melodies Errant', [53]='Shinryu', [54]='Everlasting Bonds', [55]='Provenance Watcher', [56]='Where it All Begins', [57]='Steel Sings, Blades Dance', [58]='A New Direction', [59]='The Pioneers', [60]='Into Lands Primeval - Ulbuka', [61]="Water's Umbral Knell", [62]='Keepers of the Wild', [63]='The Sacred City of Adoulin', [64]='Breaking Ground', [65]='Hades', [66]='Arciela', [67]='Mog Resort', [68]='Worlds Away', [69]="Distant Worlds (Nanaa Mihgo's version)", [70]='Monstrosity', [71]="The Pioneers (Nanaa Mihgo's version)", [72]='The Serpentine Labyrinth', [73]='The Divine', [74]='Clouds Over Ulbuka', [75]='The Price', [76]='Forever Today', [77]='Distant Worlds (Instrumental)', [78]='Forever Today (Instrumental)', [79]='Iroha', - [80]='The Boundless Black', [81]='Isle of the Gods', [82]='Wail of the Void', [83]="Rhapsodies of Vana'diel", [84]="Mount", [85]="Ambuscade", [86]="FFRK Shadow Lord", [87]="Omen", [88]="Dynamis - Divergence", [89]="Dynamis - Divergence (Wave 3)", [90]="Iroha's Theme (BCNM)", + [80]='The Boundless Black', [81]='Isle of the Gods', [82]='Wail of the Void', [83]="Rhapsodies of Vana'diel", [84]="Full Speed Ahead!", [85]="Times Grow Tense", [86]="Shadow Lord (Record Keeper Remix)", [87]="For a Friend", [88]="Between Dreams and Reality", [89]="Disjoined One", [90]="Winds of Change", [101]='Battle Theme', [102]='Battle in the Dungeon #2', [103]='Battle Theme #2', [104]='A Road Once Traveled', [105]='Mhaura', [106]='Voyager', [107]="The Kingdom of San d'Oria", [108]="Vana'diel March", [109]='Ronfaure', [110]='The Grand Duchy of Jeuno', [111]='Blackout', [112]='Selbina', [113]='Sarutabaruta', [114]='Batallia Downs', [115]='Battle in the Dungeon', [116]='Gustaberg', [117]="Ru'Lude Gardens", [118]='Rolanberry Fields', [119]='Awakening', [120]="Vana'diel March #2", [121]='Shadow Lord', [122]='One Last Time', [123]='Hopelessness', [124]='Recollection', [125]='Tough Battle', [126]='Mog House', [127]='Anxiety', [128]='Airship', [129]='Hook, Line and Sinker', From f28e6c6b229a72fbe28e92fd5a29334901dd8608 Mon Sep 17 00:00:00 2001 From: Allonte Date: Wed, 21 Aug 2019 08:16:43 -0700 Subject: [PATCH 0296/1002] Update checkparam.lua - Add "Sneak Attack" to default THF - Add "Trick Attack" to default THF - Allow "Song Duration" to be bundled with "Song Effect Duration". --- addons/checkparam/checkparam.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua index 2814269025..02809a7143 100644 --- a/addons/checkparam/checkparam.lua +++ b/addons/checkparam/checkparam.lua @@ -43,7 +43,7 @@ defaults = { WHM = 'cure potency|cure potency ii|fast cast|quick cast|cure spellcasting time|enmity|healing magic casting time|divine benison|damage taken|physical damage taken|magic damage taken', BLM = 'magic attack bonus|magic burst damage|magic burst damage ii|int|magic accuracy|magic damage|fast cast|elemental magic casting time', RDM = 'magic attack bonus|magic burst damage|magic burst damage ii|magic accuracy|fast cast|quick cast|enfeebling magic skill|enhancing magic skill|store tp|dual wield', - THF = 'store tp|double attack|triple attack|quadruple attack|dual wield|critical hit rate|critical hit damage|haste|weapon skill damage', + THF = 'store tp|double attack|triple attack|quadruple attack|dual wield|critical hit rate|critical hit damage|haste|weapon skill damage|steal|sneak attack|trick attack', PLD = 'enmity|damage taken|physical damage taken|magic damage taken|spell interruption rate|phalanx|cure potency|fastcast', DRK = 'store tp|double attack|triple attack|quadruple attack|weapon skill damage', BST = 'pet: double attack|pet: magic attack bonus|pet: damage taken', @@ -231,7 +231,8 @@ integrate = { ['crithit rate'] = 'critical hit rate', ['phys dmg taken'] = 'physical damage taken', ['occ. quickens spellcasting']="quick cast", - ['occassionally quickens spellcasting']="quick cast" + ['occassionally quickens spellcasting']="quick cast", + ['song duration']="song effect duration", } enhanced = { [10392] = 'cursna+10', --Malison Medallion From fd9fedfa3af1ffbd362190f232d41de1bd8e2aa8 Mon Sep 17 00:00:00 2001 From: Allonte Date: Wed, 21 Aug 2019 19:59:03 -0700 Subject: [PATCH 0297/1002] Update checkparam.lua - Add Singing, Wind, and String skill by default to BRD - Add in Aoido's Matinee and Legato Dagget values to Song Effect Duration --- addons/checkparam/checkparam.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua index 02809a7143..dd7f80a4a2 100644 --- a/addons/checkparam/checkparam.lua +++ b/addons/checkparam/checkparam.lua @@ -47,7 +47,7 @@ defaults = { PLD = 'enmity|damage taken|physical damage taken|magic damage taken|spell interruption rate|phalanx|cure potency|fastcast', DRK = 'store tp|double attack|triple attack|quadruple attack|weapon skill damage', BST = 'pet: double attack|pet: magic attack bonus|pet: damage taken', - BRD = 'all songs|song effect duration|fast cast|song spellcasting time', + BRD = 'all songs|song effect duration|fast cast|song spellcasting time|singing skill|wind skill|string skill', RNG = 'store tp|snapshot|rapid shot|weapon skill damage', SAM = 'store tp|double attack|triple attack|quadruple attack|weapon skill damage', NIN = 'store tp|double attack|triple attack|quadruple attack|subtle blow', @@ -304,6 +304,8 @@ enhanced = { [28619] = 'cursna+15', --Mending Cape [28631] = 'elemental siphon+30', --Conveyance Cape [28637] = 'fast cast+7', --Lifestream Cape + [11618] = 'song effect duration+10', -- Aoidos' Matinee + [20629] = 'song effect duration+5', -- Legato Dagger } combination={ ['af']={item=S{ From c98ae188b05c00f8e63c5077386b77c78ab5c9a4 Mon Sep 17 00:00:00 2001 From: Allonte Date: Mon, 26 Aug 2019 18:01:38 -0700 Subject: [PATCH 0298/1002] Bugfix in Integrate Key - Resolve issue where 'blood pact ab. del. ii' could never be found (on such items as Conveyance Cape) due to the period being stripped from the string. --- addons/checkparam/checkparam.lua | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua index dd7f80a4a2..725580ca0d 100644 --- a/addons/checkparam/checkparam.lua +++ b/addons/checkparam/checkparam.lua @@ -150,8 +150,7 @@ function split_text(id,text,arg) local key = arg and arg..key or key if key == "blood pact damage" then key = "pet: blood pact damage" - end - if key == "damage taken" then + elseif key == "damage taken" then tbl['physical damage taken'] = tonumber(value)+(tbl['physical damage taken'] or 0) tbl['magic damage taken'] = tonumber(value)+(tbl['magic damage taken'] or 0) else @@ -213,7 +212,7 @@ integrate = { ['dblatk'] = 'double attack', ['blood pact ability delay'] = 'blood pact delay', ['blood pact ability delay ii'] = 'blood pact delay ii', - ['blood pact ab. del. ii'] = 'blood pact delay ii', + ['blood pact ab del ii'] = 'blood pact delay ii', ['blood pact recast time ii'] = 'blood pact delay ii', ['blood pact dmg'] = 'blood pact damage', ['enhancing magic duration'] = 'enhancing magic effect duration', From 936695af59c85761d0c84edda8e4acfa2dd82b7d Mon Sep 17 00:00:00 2001 From: Allonte Date: Mon, 26 Aug 2019 18:02:28 -0700 Subject: [PATCH 0299/1002] Tab to Space --- addons/checkparam/checkparam.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua index 725580ca0d..4f16d2230b 100644 --- a/addons/checkparam/checkparam.lua +++ b/addons/checkparam/checkparam.lua @@ -212,7 +212,7 @@ integrate = { ['dblatk'] = 'double attack', ['blood pact ability delay'] = 'blood pact delay', ['blood pact ability delay ii'] = 'blood pact delay ii', - ['blood pact ab del ii'] = 'blood pact delay ii', + ['blood pact ab del ii'] = 'blood pact delay ii', ['blood pact recast time ii'] = 'blood pact delay ii', ['blood pact dmg'] = 'blood pact damage', ['enhancing magic duration'] = 'enhancing magic effect duration', From 0a6d47fb78fb4579d109335f96d7cdf528fa6ab9 Mon Sep 17 00:00:00 2001 From: Allonte Date: Mon, 26 Aug 2019 18:38:57 -0700 Subject: [PATCH 0300/1002] Bugfix Pet: Haste I could not confirm that gear "Pet: Haste" could go beyond 25%. Setting cap to 25%. --- addons/checkparam/checkparam.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua index 4f16d2230b..8731d32bb3 100644 --- a/addons/checkparam/checkparam.lua +++ b/addons/checkparam/checkparam.lua @@ -354,7 +354,7 @@ caps={ ['quick cast']=10, ['physical damage taken']=-25, ['magic damage taken']=-25, - ['pet: haste']=80, + ['pet: haste']=25, ['magic burst damage']=40, ['blood pact delay']=-15, ['blood pact delay ii']=-15, From 8c22dc8b19e6ed1dc7755aa56bf51885f9b92379 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Wed, 11 Sep 2019 00:40:49 -0400 Subject: [PATCH 0301/1002] Slip 22 Wind Knife NQ/HQ --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 845fdfff21..adb7feb802 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757}, -- 191 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453,}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454,}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 26518, 27623, 3719, 20573, 20674, 21742, 21860, 22065, 23731, 26517, 3724, 3721, 21682, 22072, 21820, 21821, 22124, 22132, 3738, 22039, 23730,}, -- 97 + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 26518, 27623, 3719, 20573, 20674, 21742, 21860, 22065, 23731, 26517, 3724, 3721, 21682, 22072, 21820, 21821, 22124, 22132, 3738, 22039, 23730, 20578, 20568}, -- 99 [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25589, 25762, 25763, 25810, 25811, 25869, 25870, 25935, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409,}, --167 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330,}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665,}, --115 From 1844f9e4dc70fc9c7f3ff765f3798d56d8ee1186 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Wed, 11 Sep 2019 00:42:10 -0400 Subject: [PATCH 0302/1002] Slip 22 Wind Knife NQ/HQ --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 845fdfff21..adb7feb802 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757}, -- 191 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453,}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454,}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 26518, 27623, 3719, 20573, 20674, 21742, 21860, 22065, 23731, 26517, 3724, 3721, 21682, 22072, 21820, 21821, 22124, 22132, 3738, 22039, 23730,}, -- 97 + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 26518, 27623, 3719, 20573, 20674, 21742, 21860, 22065, 23731, 26517, 3724, 3721, 21682, 22072, 21820, 21821, 22124, 22132, 3738, 22039, 23730, 20578, 20568}, -- 99 [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25589, 25762, 25763, 25810, 25811, 25869, 25870, 25935, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409,}, --167 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330,}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665,}, --115 From b2345145e3b0696e815c1c6be5034bde7c715b4f Mon Sep 17 00:00:00 2001 From: Benjamin Johnson Date: Wed, 18 Sep 2019 19:46:19 +0100 Subject: [PATCH 0303/1002] Update Gearswap to allow for Dispelga Include Dispelga in the check_spell, similar to Impact, as it's a gear-attained spell. --- addons/GearSwap/helper_functions.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/GearSwap/helper_functions.lua b/addons/GearSwap/helper_functions.lua index 2058b23b17..88de35e8c5 100644 --- a/addons/GearSwap/helper_functions.lua +++ b/addons/GearSwap/helper_functions.lua @@ -701,9 +701,9 @@ end ---- false if the spell is not currently accessible ----------------------------------------------------------------------------------- function check_spell(available_spells,spell) - -- Filter for spells that you do not know. Exclude Impact. + -- Filter for spells that you do not know. Exclude Impact / Dispelga. local spell_jobs = copy_entry(res.spells[spell.id].levels) - if not available_spells[spell.id] and not (spell.id == 503 or spell.id == 417) then + if not available_spells[spell.id] and not (spell.id == 503 or spell.id == 417 or spell.id == 360) then return false,"Unable to execute command. You do not know that spell ("..(res.spells[spell.id][language] or spell.id)..")" -- Filter for spells that you know, but do not currently have access to elseif (not spell_jobs[player.main_job_id] or not (spell_jobs[player.main_job_id] <= player.main_job_level or From 0d5e2a7126e278f6de4e23cd2c9d8deccde308cd Mon Sep 17 00:00:00 2001 From: posimagi Date: Fri, 20 Sep 2019 12:35:52 -0700 Subject: [PATCH 0304/1002] Fix parry pronoun --- addons/battlemod/parse_action_packet.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/battlemod/parse_action_packet.lua b/addons/battlemod/parse_action_packet.lua index 396ef4d507..a94786ee33 100644 --- a/addons/battlemod/parse_action_packet.lua +++ b/addons/battlemod/parse_action_packet.lua @@ -227,9 +227,9 @@ function parse_action_packet(act) if m.fields.status then numb = m.status else numb = pref_suf((m.cparam or m.param),m.message) end if msg and m.message == 70 and not simplify then -- fix pronoun on parry - if act.actor.race == 0 then + if v.target[1].race == 0 then msg = msg:gsub(' his ',' its ') - elseif female_races:contains(act.actor.race) then + elseif female_races:contains(v.target[1].race) then msg = msg:gsub(' his ',' her ') end end From b9acf69f15e14bb8d8423fd3cea444dff4e20da6 Mon Sep 17 00:00:00 2001 From: posimagi Date: Fri, 20 Sep 2019 15:25:07 -0700 Subject: [PATCH 0305/1002] battlemod: handle debuff application messages --- addons/battlemod/parse_action_packet.lua | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/addons/battlemod/parse_action_packet.lua b/addons/battlemod/parse_action_packet.lua index 396ef4d507..9d4f6d0d23 100644 --- a/addons/battlemod/parse_action_packet.lua +++ b/addons/battlemod/parse_action_packet.lua @@ -193,6 +193,26 @@ function parse_action_packet(act) else m.simp_name = act.action.name or '' end + -- Debuff Application Messages + if 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 + -- if m.message == 93 or m.message == 273 then m.status=color_it('Vanish',color_arr['statuscol']) end -- Special Message Handling From 161b0385fbc796de6a4b8a807650d6cb60405d41 Mon Sep 17 00:00:00 2001 From: Ivaar <7287342+Ivaar@users.noreply.github.com> Date: Wed, 2 Oct 2019 00:27:40 -0700 Subject: [PATCH 0306/1002] Slips.lua: correct item order for ayanmo/add wardrobes --- addons/libs/slips.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index adb7feb802..f73746fd59 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -10,7 +10,7 @@ local slips = {} _libs.slips = slips -slips.default_storages = {'inventory', 'safe', 'storage', 'locker', 'satchel', 'sack', 'case', 'wardrobe', 'safe2'} +slips.default_storages = {'inventory', 'safe', 'storage', 'locker', 'satchel', 'sack', 'case', 'wardrobe', 'safe2', 'wardrobe2', 'wardrobe3', 'wardrobe4'} slips.storages = L{29312, 29313, 29314, 29315, 29316, 29317, 29318, 29319, 29320, 29321, 29322, 29323, 29324, 29325, 29326, 29327, 29328, 29329, 29330, 29331, 29332, 29333, 29334, 29335, 29336, 29337, 29338, 29339} slips.items = { [slips.storages[1]] = L{16084, 14546, 14961, 15625, 15711, 16085, 14547, 14962, 15626, 15712, 16086, 14548, 14963, 15627, 15713, 16087, 14549, 14964, 15628, 15714, 16088, 14550, 14965, 15629, 15715, 16089, 14551, 14966, 15630, 15716, 16090, 14552, 14967, 15631, 15717, 16091, 14553, 14968, 15632, 15718, 16092, 14554, 14969, 15633, 15719, 16093, 14555, 14970, 15634, 15720, 16094, 14556, 14971, 15635, 15721, 16095, 14557, 14972, 15636, 15722, 16096, 14558, 14973, 15637, 15723, 16097, 14559, 14974, 15638, 15724, 16098, 14560, 14975, 15639, 15725, 16099, 14561, 14976, 15640, 15726, 16100, 14562, 14977, 15641, 15727, 16101, 14563, 14978, 15642, 15728, 16102, 14564, 14979, 15643, 15729, 16103, 14565, 14980, 15644, 15730, 16106, 14568, 14983, 15647, 15733, 16107, 14569, 14984, 15648, 15734, 16108, 14570, 14985, 15649, 15735, 16602, 17741, 18425, 18491, 18588, 18717, 18718, 18850, 18943, 16069, 14530, 14940, 15609, 15695, 16062, 14525, 14933, 15604, 15688, 16064, 14527, 14935, 15606, 15690, 18685, 18065, 17851, 18686, 18025, 18435, 18113, 17951, 17715, 18485, 18408, 18365, 18583, 18417, 18388, 16267, 16268, 16269, 16228, 16229, 15911, 15799, 15800, 15990, 17745, 18121, 16117, 14577, 17857}, -- 168 @@ -35,7 +35,7 @@ slips.items = { [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453,}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454,}, -- 110 [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 26518, 27623, 3719, 20573, 20674, 21742, 21860, 22065, 23731, 26517, 3724, 3721, 21682, 22072, 21820, 21821, 22124, 22132, 3738, 22039, 23730, 20578, 20568}, -- 99 - [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25589, 25762, 25763, 25810, 25811, 25869, 25870, 25935, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409,}, --167 + [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409,}, --167 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330,}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665,}, --115 [slips.storages[26]] = L{23063, 23130, 23197, 23264, 23331, 23064, 23131, 23198, 23265, 23332, 23065, 23132, 23199, 23266, 23333, 23066, 23133, 23200, 23267, 23334, 23067, 23134, 23201, 23268, 23335, 23068, 23135, 23202, 23269, 23336, 23069, 23136, 23203, 23270, 23337, 23070, 23137, 23204, 23271, 23338, 23071, 23138, 23205, 23272, 23339, 23072, 23139, 23206, 23273, 23340, 23073, 23140, 23207, 23274, 23341, 23074, 23141, 23208, 23274, 23342, 23075, 23142, 23209, 23276, 23343, 23076, 23143, 23210, 23277, 23344, 23077, 23144, 23211, 23278, 23345, 23078, 23145, 23212, 23279, 23346, 23079, 23146, 23213, 23280, 23347, 23080, 23147, 23214, 23281, 23348, 23081, 23148, 23215, 23282, 23349, 23082, 23149, 23216, 23283, 23350, 23083, 23150, 23217, 23284, 23351, 23084, 23151, 23218, 23285, 23352,}, --110 From ebe4dadd042895a18b3807308505d774997de975 Mon Sep 17 00:00:00 2001 From: Ivaar <7287342+Ivaar@users.noreply.github.com> Date: Fri, 4 Oct 2019 18:44:58 -0700 Subject: [PATCH 0307/1002] Slips.lua: added items/verified slip 22 --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index a949fe2f9a..b73c32d054 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757}, -- 191 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453,}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454,}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 26518, 27623, 3719, 20573, 20674, 21742, 21860, 22065, 23731, 26517, 3724, 3721, 21682, 22072, 21820, 21821, 22124, 22132, 3738, 22039, 23730, 20578, 20568}, -- 99 + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568}, -- 104 [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25589, 25762, 25763, 25810, 25811, 25869, 25935, 25936, 25870, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409,}, --167 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330,}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665,}, --115 From b0024b955b9db12c5d38ca56a5c9a6fa0480b9fb Mon Sep 17 00:00:00 2001 From: Ivaar <7287342+Ivaar@users.noreply.github.com> Date: Sun, 6 Oct 2019 12:22:49 -0700 Subject: [PATCH 0308/1002] Slips.lua: Add ranine staff to Slip 23 --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index b73c32d054..51aebf9418 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -35,7 +35,7 @@ slips.items = { [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453,}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454,}, -- 110 [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568}, -- 104 - [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25589, 25762, 25763, 25810, 25811, 25869, 25935, 25936, 25870, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409,}, --167 + [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070}, --168 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330,}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665,}, --115 [slips.storages[26]] = L{23063, 23130, 23197, 23264, 23331, 23064, 23131, 23198, 23265, 23332, 23065, 23132, 23199, 23266, 23333, 23066, 23133, 23200, 23267, 23334, 23067, 23134, 23201, 23268, 23335, 23068, 23135, 23202, 23269, 23336, 23069, 23136, 23203, 23270, 23337, 23070, 23137, 23204, 23271, 23338, 23071, 23138, 23205, 23272, 23339, 23072, 23139, 23206, 23273, 23340, 23073, 23140, 23207, 23274, 23341, 23074, 23141, 23208, 23274, 23342, 23075, 23142, 23209, 23276, 23343, 23076, 23143, 23210, 23277, 23344, 23077, 23144, 23211, 23278, 23345, 23078, 23145, 23212, 23279, 23346, 23079, 23146, 23213, 23280, 23347, 23080, 23147, 23214, 23281, 23348, 23081, 23148, 23215, 23282, 23349, 23082, 23149, 23216, 23283, 23350, 23083, 23150, 23217, 23284, 23351, 23084, 23151, 23218, 23285, 23352,}, --110 From f31c2dc585734526e4ff637a219be3864c33951c Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Tue, 8 Oct 2019 23:46:50 +0200 Subject: [PATCH 0309/1002] Adding Mug messages Adding mug messages for simplify --- addons/battlemod/parse_action_packet.lua | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/addons/battlemod/parse_action_packet.lua b/addons/battlemod/parse_action_packet.lua index 553e38f270..2b0ac8c4bb 100644 --- a/addons/battlemod/parse_action_packet.lua +++ b/addons/battlemod/parse_action_packet.lua @@ -172,6 +172,7 @@ function parse_action_packet(act) elseif m.message == 67 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' @@ -192,7 +193,7 @@ function parse_action_packet(act) act.action = {} else m.simp_name = act.action.name or '' end - + -- Debuff Application Messages if message_map[82]:contains(m.message) then if m.status == 'Evasion Down' then @@ -361,7 +362,7 @@ function simplify_message(msg_ID) local msg = res.action_messages[msg_ID][language] local fields = fieldsearch(msg) - if simplify and not T{23,64,129,133,139,140,204,210,211,212,213,214,244,350,442,516,531,557,565,582,674}:contains(msg_ID) then + if simplify and not T{23,64,133,139,140,204,210,211,212,213,214,350,442,516,531,557,565,582,674}: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 @@ -369,7 +370,7 @@ function simplify_message(msg_ID) 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{152,161,162,163,165,229,384,453,603,652}:contains(msg_ID) then + T{129,152,161,162,163,165,229,384,453,603,652}:contains(msg_ID) then fields.ability = true end @@ -378,7 +379,7 @@ function simplify_message(msg_ID) fields.item = true end - if T{152,153,160,161,162,163,164,165,166,167,168,229,652}:contains(msg_ID) then + 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 From f80bbcf77c5e66a7b87066f99b2657cfc20eb00f Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Wed, 9 Oct 2019 00:00:50 +0200 Subject: [PATCH 0310/1002] Update parse_action_packet.lua --- addons/battlemod/parse_action_packet.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/battlemod/parse_action_packet.lua b/addons/battlemod/parse_action_packet.lua index 2b0ac8c4bb..b02a15402d 100644 --- a/addons/battlemod/parse_action_packet.lua +++ b/addons/battlemod/parse_action_packet.lua @@ -193,7 +193,7 @@ function parse_action_packet(act) act.action = {} else m.simp_name = act.action.name or '' end - + -- Debuff Application Messages if message_map[82]:contains(m.message) then if m.status == 'Evasion Down' then From 45d06da0a56e50629b4c50d919c76cf8d9578ea9 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Thu, 10 Oct 2019 00:50:30 +0200 Subject: [PATCH 0311/1002] Adding Chainbound AE message to battlemod Adding the chainbound additional effect message from odin in the master trial fight. --- addons/battlemod/parse_action_packet.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/battlemod/parse_action_packet.lua b/addons/battlemod/parse_action_packet.lua index b02a15402d..c2f18d8043 100644 --- a/addons/battlemod/parse_action_packet.lua +++ b/addons/battlemod/parse_action_packet.lua @@ -281,6 +281,7 @@ function parse_action_packet(act) 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 = 'TH' + 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) From d7c6390493c5c09062a83ab1d445e7c31a0292d8 Mon Sep 17 00:00:00 2001 From: Allonte Date: Wed, 9 Oct 2019 19:42:37 -0700 Subject: [PATCH 0312/1002] Update 'indicolure effect duration' Make sure "indi eff dur" equates properly to indicolure effect duration --- addons/checkparam/checkparam.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua index 8731d32bb3..6a72dd5e1a 100644 --- a/addons/checkparam/checkparam.lua +++ b/addons/checkparam/checkparam.lua @@ -58,7 +58,7 @@ defaults = { PUP = 'pet: hp|pet: damage taken|pet: regen|martial arts|store tp|double attack|triple attack|quadruple attack', DNC = 'store tp|double attack|triple attack|quadruple attack', SCH = 'magic attack bonus|magic burst damage|magic burst damage ii|magic accuracy|magic damage|fast cast|elemental magic casting time|cure potency|enh mag eff dur|enhancing magic effect duration', - GEO = 'pet: regen|pet: damage taken|indicolure effect duration|indi eff dur|fast cast|magic evasion', + GEO = 'pet: regen|pet: damage taken|indicolure effect duration|fast cast|magic evasion|handbell skill|geomancy skill|geomancy', RUN = 'enmity|damage taken|physical damage taken|magic damage taken|spell interruption rate|phalanx|inquartata|fastcast', levelfilter = 99, } @@ -218,6 +218,7 @@ integrate = { ['enhancing magic duration'] = 'enhancing magic effect duration', ['eva'] = 'evasion', ['indicolure spell duration'] = 'indicolure effect duration', + ['indi eff dur'] = 'indicolure effect duration', ['mag eva'] = 'magic evasion', ['magic atk bonus'] = 'magic attack bonus', ['magatkbns'] = 'magic attack bonus', From e56715e91114b2596087d5b31fe49778a692ec14 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Thu, 10 Oct 2019 21:27:23 -0600 Subject: [PATCH 0313/1002] EasyNuke.lua add command for AncientMagic (//ez boomam) I'll be honest, haven't tested it yet but, thought I'd toss it in here in case someone wanted to try it out. --- addons/EasyNuke/EasyNuke.lua | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/addons/EasyNuke/EasyNuke.lua b/addons/EasyNuke/EasyNuke.lua index 68b1ec010c..1b3cbb29e7 100644 --- a/addons/EasyNuke/EasyNuke.lua +++ b/addons/EasyNuke/EasyNuke.lua @@ -59,26 +59,32 @@ spell_tables["fire"] = {"Fire","Fire II","Fire III","Fire IV","Fire V","Fire VI" spell_tables["fire"]["ga"] = {"Firaga","Firaga II","Firaga III","Firaja",} spell_tables["fire"]["ra"] = {"Fira","Fira II","Fira III"} spell_tables["fire"]["helix"] = {"Pyrohelix","Pyrohelix II"} +spell_tables["fire"]["am"] = {"Flare","Flare II"} spell_tables["earth"] = {"Stone","Stone II","Stone III","Stone IV","Stone V","Stone VI",} spell_tables["earth"]["ga"] = {"Stonega","Stonega II","Stonega III","Stoneja",} spell_tables["earth"]["ra"] = {"Stonera","Stonera II","Stonera III"} spell_tables["earth"]["helix"] = {"Geohelix","Geohelix II"} +spell_tables["earth"]["am"] = {"Quake","Quake II"} spell_tables["wind"] = {"Aero","Aero II","Aero III","Aero IV","Aero V","Aero VI",} spell_tables["wind"]["ga"] = {"Aeroga","Aeroga II","Aeroga III","Aeroja",} spell_tables["wind"]["ra"] = {"Aerora","Aerora II","Aerora III"} spell_tables["wind"]["helix"] = {"Anemohelix","Anemohelix II"} +spell_tables["wind"]["am"] = {"Tornado","Tornado II"} spell_tables["water"] = {"Water","Water II","Water III","Water IV","Water V","Water VI",} spell_tables["water"]["ga"] = {"Waterga","Waterga II","Waterga III","Waterja",} spell_tables["water"]["ra"] = {"Watera","Watera II","Watera III"} spell_tables["water"]["helix"] = {"Hydrohelix","Hydrohelix II"} +spell_tables["water"]["am"] = {"Flood","Flood II"} spell_tables["ice"] = {"Blizzard","Blizzard II","Blizzard III","Blizzard IV","Blizzard V","Blizzard VI",} spell_tables["ice"]["ga"] = {"Blizzaga","Blizzaga II","Blizzaga III","Blizzaja",} spell_tables["ice"]["ra"] = {"Blizzara","Blizzara II","Blizzara III"} spell_tables["ice"]["helix"] = {"Cryohelix","Cryohelix II"} +spell_tables["ice"]["am"] = {"Freeze","Freeze II"} spell_tables["thunder"] = {"Thunder","Thunder II","Thunder III","Thunder IV","Thunder V","Thunder VI",} spell_tables["thunder"]["ga"] = {"Thundaga","Thundaga II","Thundaga III","Thundaja",} spell_tables["thunder"]["ra"] = {"Thundara","Thundara II","Thundara III"} spell_tables["thunder"]["helix"] = {"Ionohelix","Ionohelix II"} +spell_tables["thunder"]["am"] = {"Burst","Burst II"} spell_tables["light"] = {"Banish","Banish II","Holy","Banish III",} spell_tables["light"]["ga"] = {"Banishga","Banishga II"} spell_tables["light"]["helix"] = {"Luminohelix","Luminohelix II"} @@ -133,6 +139,8 @@ windower.register_event("unhandled command", function (command, arg) execute_spell_cast("ra", arg) elseif command == "boomhelix" or command == "bhelix" then execute_spell_cast("helix", arg) + elseif command = "boomam" or command == "bam" then + execute_spell_cast("am", arg) end end) @@ -146,6 +154,8 @@ windower.register_event('addon command', function (command, arg) execute_spell_cast("ra", arg) elseif command == "boomhelix" or command == "bhelix" then execute_spell_cast("helix", arg) + elseif command = "boomam" or command == "bam" then + execute_spell_cast("am", arg) elseif command == "target" then if arg then @@ -240,4 +250,4 @@ windower.register_event('addon command', function (command, arg) elseif command == "show" or command == "current" or command == "showcurrent" then windower.add_to_chat(206, "----- Element Mode: "..string.ucfirst(current_element).." --- Target Mode: < "..target_mode.." > -----") end -end) \ No newline at end of file +end) From 9ecd23615bc127b4a11196bb27608637cc716eae Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Fri, 11 Oct 2019 11:02:20 +0200 Subject: [PATCH 0314/1002] Add Spirit Bond message to battlemod Add Spirit Bond message to battlemod --- addons/battlemod/battlemod.lua | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index 11523a7ab1..83e6ddd413 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -259,6 +259,25 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec 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 T{800}:contains(am.message_id) then -- Spirit bond message + local Self = windower.ffxi.get_player() + 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] + :gsub('${status}',status or '') + :gsub('${target}',targ) + :gsub('${number}',number or '') + windower.add_to_chat(color, msg) + end elseif T{206}:contains(am.message_id) and condensetargets then -- Wears off messages -- Condenses across multiple packets local status From 25e997ca03652d7c58826a6d62b948fed7589101 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Fri, 11 Oct 2019 11:37:15 +0200 Subject: [PATCH 0315/1002] Update battlemod.lua --- addons/battlemod/battlemod.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index 83e6ddd413..a96afd436f 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -259,7 +259,7 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec 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 T{800}:contains(am.message_id) then -- Spirit bond message + elseif am.message_id == 800 then -- Spirit bond message local Self = windower.ffxi.get_player() 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]) @@ -278,7 +278,7 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec :gsub('${number}',number or '') windower.add_to_chat(color, msg) end - elseif T{206}:contains(am.message_id) and condensetargets then -- Wears off messages + elseif am.message_id == 206 and condensetargets then -- Wears off messages -- Condenses across multiple packets local status From e9861a516fca1c44746e02a8bbc71350c589884f Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Fri, 11 Oct 2019 19:22:59 +0200 Subject: [PATCH 0316/1002] Update battlemod.lua --- addons/battlemod/battlemod.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index a96afd436f..494ed3fc34 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -260,7 +260,6 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec 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 Self = windower.ffxi.get_player() 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 From b6bc5e4b3488b039c5c4340fa298dc845b8a2e2f Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Sun, 13 Oct 2019 18:41:54 -0600 Subject: [PATCH 0317/1002] EasyNuke fix got pushed with errors --- addons/EasyNuke/EasyNuke.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/EasyNuke/EasyNuke.lua b/addons/EasyNuke/EasyNuke.lua index 1b3cbb29e7..055bcfe9d0 100644 --- a/addons/EasyNuke/EasyNuke.lua +++ b/addons/EasyNuke/EasyNuke.lua @@ -139,7 +139,7 @@ windower.register_event("unhandled command", function (command, arg) execute_spell_cast("ra", arg) elseif command == "boomhelix" or command == "bhelix" then execute_spell_cast("helix", arg) - elseif command = "boomam" or command == "bam" then + elseif command == "boomam" or command == "bam" then execute_spell_cast("am", arg) end end) @@ -154,7 +154,7 @@ windower.register_event('addon command', function (command, arg) execute_spell_cast("ra", arg) elseif command == "boomhelix" or command == "bhelix" then execute_spell_cast("helix", arg) - elseif command = "boomam" or command == "bam" then + elseif command == "boomam" or command == "bam" then execute_spell_cast("am", arg) elseif command == "target" then From 018b0c5b6dfcf2b3ab2b7c78d9872ff78ccd52c4 Mon Sep 17 00:00:00 2001 From: Ivaar <7287342+Ivaar@users.noreply.github.com> Date: Sat, 19 Oct 2019 16:33:21 -0700 Subject: [PATCH 0318/1002] Gearswap: Filter enchanted items with duplicate names. --- addons/GearSwap/gearswap.lua | 2 +- addons/GearSwap/statics.lua | 4 +++- addons/GearSwap/version_history.txt | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/addons/GearSwap/gearswap.lua b/addons/GearSwap/gearswap.lua index b6797d6196..f913db5a95 100644 --- a/addons/GearSwap/gearswap.lua +++ b/addons/GearSwap/gearswap.lua @@ -25,7 +25,7 @@ --SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'GearSwap' -_addon.version = '0.934' +_addon.version = '0.935' _addon.author = 'Byrth' _addon.commands = {'gs','gearswap'} diff --git a/addons/GearSwap/statics.lua b/addons/GearSwap/statics.lua index 837ce993da..9693b89529 100644 --- a/addons/GearSwap/statics.lua +++ b/addons/GearSwap/statics.lua @@ -99,7 +99,9 @@ end for i,v in pairs(res.items) do v.prefix = '/item' - make_entry(v,i) + if not validabils['english'][v.prefix][v.english:lower()] or v.cast_delay then + make_entry(v,i) + end end -- Should transition these slot maps to be based off res.slots, but it's very unlikely to change. diff --git a/addons/GearSwap/version_history.txt b/addons/GearSwap/version_history.txt index 301a001192..3d4e29ef0f 100644 --- a/addons/GearSwap/version_history.txt +++ b/addons/GearSwap/version_history.txt @@ -1,5 +1,6 @@ ------------------------------------------------- - +GearSwap 0.935 - Filter enchanted items with duplicate names. +------------------------------------------------- GearSwap 0.934 - Fixed /item command handling. ------------------------------------------------- GearSwap 0.933 - Adjusted how item use packets are chosen. From 6e57f35d838d739176debb40aff97cb085355591 Mon Sep 17 00:00:00 2001 From: Ivaar <7287342+Ivaar@users.noreply.github.com> Date: Wed, 23 Oct 2019 18:24:06 -0700 Subject: [PATCH 0319/1002] Slips.lua: added Autumn tree and fixed Sakonji Haidate +2 --- addons/libs/slips.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 51aebf9418..3e1911c36f 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,11 +34,11 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757}, -- 191 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453,}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454,}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568}, -- 104 + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739}, -- 105 [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070}, --168 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330,}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665,}, --115 - [slips.storages[26]] = L{23063, 23130, 23197, 23264, 23331, 23064, 23131, 23198, 23265, 23332, 23065, 23132, 23199, 23266, 23333, 23066, 23133, 23200, 23267, 23334, 23067, 23134, 23201, 23268, 23335, 23068, 23135, 23202, 23269, 23336, 23069, 23136, 23203, 23270, 23337, 23070, 23137, 23204, 23271, 23338, 23071, 23138, 23205, 23272, 23339, 23072, 23139, 23206, 23273, 23340, 23073, 23140, 23207, 23274, 23341, 23074, 23141, 23208, 23274, 23342, 23075, 23142, 23209, 23276, 23343, 23076, 23143, 23210, 23277, 23344, 23077, 23144, 23211, 23278, 23345, 23078, 23145, 23212, 23279, 23346, 23079, 23146, 23213, 23280, 23347, 23080, 23147, 23214, 23281, 23348, 23081, 23148, 23215, 23282, 23349, 23082, 23149, 23216, 23283, 23350, 23083, 23150, 23217, 23284, 23351, 23084, 23151, 23218, 23285, 23352,}, --110 + [slips.storages[26]] = L{23063, 23130, 23197, 23264, 23331, 23064, 23131, 23198, 23265, 23332, 23065, 23132, 23199, 23266, 23333, 23066, 23133, 23200, 23267, 23334, 23067, 23134, 23201, 23268, 23335, 23068, 23135, 23202, 23269, 23336, 23069, 23136, 23203, 23270, 23337, 23070, 23137, 23204, 23271, 23338, 23071, 23138, 23205, 23272, 23339, 23072, 23139, 23206, 23273, 23340, 23073, 23140, 23207, 23274, 23341, 23074, 23141, 23208, 23275, 23342, 23075, 23142, 23209, 23276, 23343, 23076, 23143, 23210, 23277, 23344, 23077, 23144, 23211, 23278, 23345, 23078, 23145, 23212, 23279, 23346, 23079, 23146, 23213, 23280, 23347, 23080, 23147, 23214, 23281, 23348, 23081, 23148, 23215, 23282, 23349, 23082, 23149, 23216, 23283, 23350, 23083, 23150, 23217, 23284, 23351, 23084, 23151, 23218, 23285, 23352,}, --110 [slips.storages[27]] = L{23398, 23465, 23532, 23599, 23666, 23399, 23466, 23533, 23600, 23667, 23400, 23467, 23534, 23601, 23668, 23401, 23468, 23535, 23602, 23669, 23402, 23469, 23536, 23603, 23670, 23403, 23470, 23537, 23604, 23671, 23404, 23471, 23538, 23605, 23672, 23405, 23472, 23539, 23606, 23673, 23406, 23473, 23540, 23607, 23674, 23407, 23474, 23541, 23608, 23675, 23408, 23475, 23542, 23609, 23676, 23409, 23476, 23543, 23610, 23677, 23410, 23477, 23544, 23611, 23678, 23411, 23478, 23545, 23612, 23679, 23412, 23479, 23546, 23613, 23680, 23413, 23480, 23547, 23614, 23681, 23414, 23481, 23548, 23615, 23682, 23415, 23482, 23549, 23616, 23683, 23416, 23483, 23550, 23617, 23684, 23417, 23484, 23551, 23618, 23685, 23418, 23485, 23552, 23619, 23686, 23419, 23486, 23553, 23620, 23687,}, --110 [slips.storages[28]] = L{21515, 21561, 21617, 21670, 21718, 21775, 21826, 21879, 21918, 21971, 22027, 22082, 22108, 22214, 21516, 21562, 21618, 21671, 21719, 21776, 21827, 21880, 21919, 21972, 22028, 22083, 22109, 22215, 21517, 21563, 21619, 21672, 21720, 21777, 21828, 21881, 21920, 21973, 22029, 22084, 22110, 22216, 21518, 21564, 21620, 21673, 21721, 21778, 21829, 21882, 21921, 21974, 22030, 22085, 22111, 22217, 21519, 21565, 21621, 21674, 21722, 21779, 21830, 21883, 21922, 21975, 22031, 22086, 22107, 22218}, --70 } From ab37215edb7685c44ac8212d557171e2d1c5bac0 Mon Sep 17 00:00:00 2001 From: Allonte Date: Thu, 31 Oct 2019 06:47:32 -0700 Subject: [PATCH 0320/1002] Add Pet PDT/MDT - Add WA for Pet: DT to be shown as Pet: PDT and Pet: MDT much like regulare DT - Add Pet: PDT/MDT caps --- addons/checkparam/checkparam.lua | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua index 6a72dd5e1a..5b61cfa81f 100644 --- a/addons/checkparam/checkparam.lua +++ b/addons/checkparam/checkparam.lua @@ -52,9 +52,9 @@ defaults = { SAM = 'store tp|double attack|triple attack|quadruple attack|weapon skill damage', NIN = 'store tp|double attack|triple attack|quadruple attack|subtle blow', DRG = 'store tp|double attack|triple attack|quadruple attack|weapon skill damage', - SMN = 'blood pact delay|blood pact delay ii|blood pact damage|avatar perpetuation cost|pet: magic attack bonus|pet: attack|pet: double attack|pet: accuracy|pet: magic accuracy|summoning magic skill|pet: blood pact damage|pet: magic damage', - BLU = 'store tp|double attack|triple attack|quadruple attack|critical hit rate|critical hit damage|weapon skill damage|fast cast|magic attack bonus|magic accuracy|cure potency', - COR = 'store tp|snapshot|rapid shot|fast cast|cure potency|magic accuracy|magic attack bonus|magic damage|weapon skill damage', + SMN = 'physical damage taken|magic damage taken|pet: physical damage taken|pet: magic damage taken|blood pact delay|blood pact delay ii|blood pact damage|avatar perpetuation cost|pet: magic attack bonus|pet: attack|pet: double attack|pet: accuracy|pet: magic accuracy|summoning magic skill|pet: blood pact damage|pet: magic damage', + BLU = 'physical damage taken|magic damage taken|haste|dual wield|store tp|double attack|triple attack|quadruple attack|critical hit rate|critical hit damage|weapon skill damage|fast cast|magic attack bonus|magic accuracy|cure potency', + COR = 'physical damage taken|magic damage taken|haste|dual wield|store tp|snapshot|rapid shot|fast cast|cure potency|magic accuracy|magic attack bonus|magic damage|weapon skill damage', PUP = 'pet: hp|pet: damage taken|pet: regen|martial arts|store tp|double attack|triple attack|quadruple attack', DNC = 'store tp|double attack|triple attack|quadruple attack', SCH = 'magic attack bonus|magic burst damage|magic burst damage ii|magic accuracy|magic damage|fast cast|elemental magic casting time|cure potency|enh mag eff dur|enhancing magic effect duration', @@ -150,6 +150,9 @@ function split_text(id,text,arg) local key = arg and arg..key or key if key == "blood pact damage" then key = "pet: blood pact damage" + elseif key == "pet: damage taken" then + tbl['pet: physical damage taken'] = tonumber(value)+(tbl['pet: physical damage taken'] or 0) + tbl['pet: magic damage taken'] = tonumber(value)+(tbl['pet: magic damage taken'] or 0) elseif key == "damage taken" then tbl['physical damage taken'] = tonumber(value)+(tbl['physical damage taken'] or 0) tbl['magic damage taken'] = tonumber(value)+(tbl['magic damage taken'] or 0) @@ -355,6 +358,8 @@ caps={ ['quick cast']=10, ['physical damage taken']=-25, ['magic damage taken']=-25, + ['pet: physical damage taken']=-87.5, + ['pet: magic damage taken']=-87.5, ['pet: haste']=25, ['magic burst damage']=40, ['blood pact delay']=-15, From 9ffc6b1f13d5d58c7aa2b48da5e37ae840420183 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Wed, 6 Nov 2019 07:14:13 -0500 Subject: [PATCH 0321/1002] Added weather_intensity and real_weather_intensity --- addons/GearSwap/refresh.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/GearSwap/refresh.lua b/addons/GearSwap/refresh.lua index ecff3754f4..a2cfd028a6 100644 --- a/addons/GearSwap/refresh.lua +++ b/addons/GearSwap/refresh.lua @@ -424,6 +424,7 @@ function weather_update(id) world.real_weather_id = id world.real_weather = res.weather[id][language] world.real_weather_element = res.elements[res.weather[id].element][language] + world.real_weather_intensity = res.weather[world.real_weather_id].intensity local buff = false if buffactive[178] then buff = true @@ -471,6 +472,7 @@ function weather_update(id) end world.weather = res.weather[world.weather_id][language] world.weather_element = res.elements[res.weather[world.weather_id].element][language] + world.weather_intensity = res.weather[world.weather_id].intensity end From 92571e78744298575ca07e2fce2a1af42b9ab5bc Mon Sep 17 00:00:00 2001 From: Chiaia Date: Wed, 6 Nov 2019 07:15:38 -0500 Subject: [PATCH 0322/1002] version bump --- addons/GearSwap/gearswap.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/GearSwap/gearswap.lua b/addons/GearSwap/gearswap.lua index f913db5a95..c0ec11c9a4 100644 --- a/addons/GearSwap/gearswap.lua +++ b/addons/GearSwap/gearswap.lua @@ -25,7 +25,7 @@ --SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'GearSwap' -_addon.version = '0.935' +_addon.version = '0.936' _addon.author = 'Byrth' _addon.commands = {'gs','gearswap'} From d4b647c2e066c06991980c2772e51df7f881cc99 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Wed, 6 Nov 2019 07:25:37 -0500 Subject: [PATCH 0323/1002] Added world.weather_intensity and in about world.real_weather --- .../Variables.xlsx | Bin 33390 -> 32911 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/addons/GearSwap/beta_examples_and_information/Variables.xlsx b/addons/GearSwap/beta_examples_and_information/Variables.xlsx index 4fca72acaffb6d51e838e2a670527bcc64109581..ebc19916e99db35d34f923f02822e6eaf387a170 100644 GIT binary patch delta 28862 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%0DF_z~k}k_TS$>AEA#YgkKI0R1BXVNgZ!DC#S~r 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 delta 29239 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

x*NksdDu0# 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 TzW@w@Y1SdsaHYZjb@%@OqsI*y From c3c53cbabb0296171065d4a6421964e9d02ac83c Mon Sep 17 00:00:00 2001 From: Chiaia Date: Fri, 8 Nov 2019 06:43:24 -0500 Subject: [PATCH 0324/1002] Rest of relic changes so far. --- addons/libs/extdata.lua | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/addons/libs/extdata.lua b/addons/libs/extdata.lua index 4971fa1915..1070e03c65 100644 --- a/addons/libs/extdata.lua +++ b/addons/libs/extdata.lua @@ -670,12 +670,13 @@ augment_values = { [0x544] = {{stat='Increases Elemental Magic debuff time and potency', offset=0,multiplier=0}}, [0x545] = {{stat='Increases Aspir absorption amount', offset=0,multiplier=0}}, - [0x548] = {{stat='Enhances "Dia III" effect', offset=0,multiplier=0}}, - [0x549] = {{stat='Enhances "Slow II" effect', offset=0,multiplier=0}}, - [0x54A] = {{stat='Enhances "Phalanx II" effect', offset=0,multiplier=0}}, - [0x54B] = {{stat='Enhances "Bio III" effect', offset=0,multiplier=0}}, - [0x54C] = {{stat='Enhances "Blind II" effect', offset=0,multiplier=0}}, - [0x54D] = {{stat='Enhances "Paralyze II" effect', offset=0,multiplier=0}}, + [0x548] = {{stat='Enfeebling Magic duration', offset=0,multiplier=0}}, + [0x549] = {{stat='Magic Accuracy', offset=0,multiplier=0}}, + [0x54A] = {{stat='Enhancing Magic duration', offset=0,multiplier=0}}, + [0x54B] = {{stat='Enspell Damage', offset=0,multiplier=0}}, + [0x54C] = {{stat='Accuracy', offset=0,multiplier=0}}, + [0x54D] = {{stat='Immunobreak Chance', offset=0,multiplier=0}}, + [0x54E] = {{stat='Enhances "Aura Steal" effect', offset=0,multiplier=0}}, [0x54F] = {{stat='Enhances "Ambush" effect', offset=0,multiplier=0}}, [0x550] = {{stat='Enhances "Feint" effect', offset=0,multiplier=0}}, @@ -696,9 +697,9 @@ augment_values = { [0x562] = {{stat='Enhances "Beast Affinity" effect', offset=0,multiplier=0}}, [0x563] = {{stat='Enhances "Beast Healer" effect', offset=0,multiplier=0}}, - [0x566] = {{stat='Enhances "Foe Sirvente" effect', offset=0,multiplier=0}}, + [0x566] = {{stat='Enhances "Con Anima" effect', offset=0,multiplier=0}}, [0x567] = {{stat='Enhances "Troubadour" effect', offset=0,multiplier=0}}, - [0x568] = {{stat='Enh. "Adventurer\'s Dirge" effect', offset=0,multiplier=0}}, + [0x568] = {{stat='Enhances "Con Brio" effect', offset=0,multiplier=0}}, [0x569] = {{stat='Enhances "Nightingale" effect', offset=0,multiplier=0}}, [0x56C] = {{stat='Enhances "Recycle" effect', offset=0,multiplier=0}}, @@ -711,10 +712,10 @@ augment_values = { [0x574] = {{stat='Enhances "Blade Bash" effect', offset=0,multiplier=0}}, [0x575] = {{stat='Enhances "Ikishoten" effect', offset=0,multiplier=0}}, - [0x578] = {{stat='Increases elem. ninjutsu III damage', offset=0,multiplier=0}}, + [0x578] = {{stat='Enhances "Yonin" and "Innin" effect', offset=0,multiplier=0}}, [0x579] = {{stat='Enhances "Sange" effect', offset=0,multiplier=0}}, [0x57A] = {{stat='Enh. "Ninja Tool Expertise" effect', offset=0,multiplier=0}}, - [0x57B] = {{stat='Reduces elem. ninjutsu III cast time', offset=0,multiplier=0}}, + [0x57B] = {{stat='Enh. Ninj. Mag. Acc/Cast Time Red.', offset=0,multiplier=0}}, [0x57E] = {{stat='Enhances "Deep Breathing" effect', offset=0,multiplier=0}}, [0x57F] = {{stat='Enhances "Angon" effect', offset=0,multiplier=0}}, From f3d4896540cb9f960610c177c565f9e4d8c35f01 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Sun, 17 Nov 2019 16:27:58 -0500 Subject: [PATCH 0325/1002] New Addon autoenterkey hits enter when first starting the game so you don't timeout on the warning message if you tab out --- addons/addons.xml | 7 +++++ addons/autoenterkey/README.md | 9 ++++++ addons/autoenterkey/autoenterkey.lua | 46 ++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+) create mode 100644 addons/autoenterkey/README.md create mode 100644 addons/autoenterkey/autoenterkey.lua diff --git a/addons/addons.xml b/addons/addons.xml index 19a6410ac1..b2780a5435 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -38,6 +38,13 @@ Nitrous (Shiva) https://discord.gg/b275nMv https://github.com/nitrous24/Lua/issues + + + autoenterkey + Chiaia + Automatically hits the enter key twice when first starting so you don't timeout on the warning message. + https://github.com/Windower/Lua/issues + https://discord.gg/b275nMv autoinvite diff --git a/addons/autoenterkey/README.md b/addons/autoenterkey/README.md new file mode 100644 index 0000000000..d8e7f3db3b --- /dev/null +++ b/addons/autoenterkey/README.md @@ -0,0 +1,9 @@ +Author: Chiaia +Version: 1.0 +Automatically hits the enter key twice as you first load up the game so you don't timeout on the warning message if you happen to like to tab out as it launches. +It take about 5 to 10 seconds to start to do this. If you happen to manually do it faster if will just unload itself since it serves no other purpose. + +Abbreviation: //ake, //autoinvite + +Commands: +* There are currently no commands. diff --git a/addons/autoenterkey/autoenterkey.lua b/addons/autoenterkey/autoenterkey.lua new file mode 100644 index 0000000000..fa3cdb245d --- /dev/null +++ b/addons/autoenterkey/autoenterkey.lua @@ -0,0 +1,46 @@ +--Copyright (c) 2019, Chiaia +--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 Auto Enter Key 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 Chiaia 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.name = 'Auto Enter Key' +_addon.version = '1.0' +_addon.author = 'Chiaia (Asura)' +_addon.commands = {'ake',} + +windower.register_event('load', function() + if windower.ffxi.get_info().logged_in then + windower.send_command('lua u autoenterkey') + else + coroutine.sleep(5) + windower.send_command('setkey enter down;') + coroutine.sleep(0.3) + windower.send_command('setkey enter up;') + coroutine.sleep(5) + windower.send_command('setkey enter down;') + coroutine.sleep(0.3) + windower.send_command('setkey enter up;') + windower.send_command('lua u autoenterkey') + end +end) From cec04af08789ce8e5121b9c603e9f4bacb4af2b2 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Tue, 10 Dec 2019 07:27:14 +0100 Subject: [PATCH 0326/1002] [battlemod] Adding puppetmaster messages Adding puppetmaster messages to simplify on battlemod. --- addons/battlemod/parse_action_packet.lua | 14 +++++++++++--- addons/battlemod/statics.lua | 2 ++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/addons/battlemod/parse_action_packet.lua b/addons/battlemod/parse_action_packet.lua index c2f18d8043..a0134df87e 100644 --- a/addons/battlemod/parse_action_packet.lua +++ b/addons/battlemod/parse_action_packet.lua @@ -367,11 +367,11 @@ function simplify_message(msg_ID) 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 then + if msg_ID == 31 or msg_ID == 798 or msg_ID == 799 then fields.actor = true - end + 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}:contains(msg_ID) then + T{129,152,161,162,163,165,229,384,453,603,652,798}:contains(msg_ID) then fields.ability = true end @@ -410,6 +410,14 @@ function simplify_message(msg_ID) 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 diff --git a/addons/battlemod/statics.lua b/addons/battlemod/statics.lua index 6f98664ecc..a6dc6d33b3 100644 --- a/addons/battlemod/statics.lua +++ b/addons/battlemod/statics.lua @@ -83,6 +83,7 @@ line_steal = '[${actor}] ${abil} '..string.char(129,168)..' ${target} (${ite 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}', @@ -94,6 +95,7 @@ default_settings_table = {line_aoe = 'AOE ${numb} '..string.char(129,168). 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,swingnumber=true,sumdamage=true,condensecrits=false} From d9463b5cc5b62793b5f6924786fd1cdfe618a426 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Tue, 10 Dec 2019 02:11:37 -0500 Subject: [PATCH 0327/1002] BD Messages Dec 9th, 2019 Update --- addons/boxdestroyer/messages.lua | 48 ++++++++++++++++---------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/addons/boxdestroyer/messages.lua b/addons/boxdestroyer/messages.lua index 51cf56e9b9..90083cc792 100644 --- a/addons/boxdestroyer/messages.lua +++ b/addons/boxdestroyer/messages.lua @@ -1,31 +1,31 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination" for the associated zone IDs - [100] = 8061, + [100] = 8056, [101] = 7505, - [102] = 7912, - [103] = 8087, - [104] = 8652, - [105] = 7703, - [106] = 8077, - [107] = 7538, - [108] = 7607, - [109] = 8470, - [110] = 7594, - [111] = 8571, - [112] = 8173, + [102] = 7907, + [103] = 8082, + [104] = 8647, + [105] = 7698, + [106] = 8072, + [107] = 7533, + [108] = 7602, + [109] = 8465, + [110] = 7589, + [111] = 8566, + [112] = 8168, [113] = 7928, - [114] = 7772, - [115] = 7868, - [116] = 7564, - [117] = 7571, - [118] = 8113, - [119] = 8350, - [120] = 7510, - [121] = 8090, + [114] = 7767, + [115] = 7863, + [116] = 7559, + [117] = 7566, + [118] = 8108, + [119] = 8345, + [120] = 7505, + [121] = 8085, [122] = 7434, - [123] = 7873, - [124] = 7824, - [125] = 7634, - [126] = 8057, + [123] = 7868, + [124] = 7819, + [125] = 7629, + [126] = 8052, [127] = 7351, [128] = 7506, [130] = 7570, From fc3e3a5f6c6b2cd004a7431c4b3d348bf178c786 Mon Sep 17 00:00:00 2001 From: Sjshovan Date: Sun, 29 Dec 2019 22:14:32 -0500 Subject: [PATCH 0328/1002] Add BattleStations addon --- addons/BattleStations/LICENSE | 25 + addons/BattleStations/README.md | 222 +++++++++ addons/BattleStations/battlestations.lua | 598 +++++++++++++++++++++++ addons/BattleStations/constants.lua | 382 +++++++++++++++ addons/BattleStations/helpers.lua | 121 +++++ addons/addons.xml | 7 + 6 files changed, 1355 insertions(+) create mode 100644 addons/BattleStations/LICENSE create mode 100644 addons/BattleStations/README.md create mode 100644 addons/BattleStations/battlestations.lua create mode 100644 addons/BattleStations/constants.lua create mode 100644 addons/BattleStations/helpers.lua diff --git a/addons/BattleStations/LICENSE b/addons/BattleStations/LICENSE new file mode 100644 index 0000000000..d719b9e710 --- /dev/null +++ b/addons/BattleStations/LICENSE @@ -0,0 +1,25 @@ +Copyright © 2018, Sjshovan (Apogee) +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 Battle Stations 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 Sjshovan (Apogee) 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. \ No newline at end of file diff --git a/addons/BattleStations/README.md b/addons/BattleStations/README.md new file mode 100644 index 0000000000..4587aa808c --- /dev/null +++ b/addons/BattleStations/README.md @@ -0,0 +1,222 @@ +**Author:** [Sjshovan (Apogee)](https://github.com/Ap0gee) +**Version:** v0.9.1 + + +# Battle Stations + +> A Windower 4 addon that allows the user to change or remove the default battle music in Final Fantasy 11 Online. + + +### Table of Contents + +- [Prerequisites](#prerequisites) +- [Installation](#installation) +- [Aliases](#aliases) +- [Usage](#usage) +- [Commands](#commands) +- [Support](#support) +- [Change Log](#change-log) +- [Known Issues](#known-issues) +- [TODOs](#todos) +- [License](#license) + +___ +### Prerequisites +1. [Final Fantasy 11 Online](http://www.playonline.com/ff11us/index.shtml) +2. [Windower 4](http://windower.net/) + +___ +### Installation + +**Windower:** +Not yet available on windower, installation will have to be done manually. + +**Manual:** +1. Navigate to . +2. Click on `Releases`. +3. Click on the `Source code (zip)` link within the latest release to download. +4. Extract the zipped folder to `Windower4/addons/`. +5. Rename the folder to remove the version tag (`-v0.9.0`). The folder should be named `BattleStations`. + +___ +### Aliases +The following aliases are available to Battle Stations commands: + +**battlestations:** stations | bs +**list:** l +**set:** s +**get:** g +**default:** d +**normal:** n +**reload:** r +**about:** a +**help:** h +**stations:** station | s +**radios:** receivers | receiver | radio | r +**all:** all | a | * + +___ +### Usage + +Manually load the addon by using one of the following commands: + + //lua load battlestations + //lua l battlestations + +___ +### Commands + +**help** + +Displays the available Battle Stations commands. Below are the equivalent ways of calling the command: + + //battlestations help + //stations help + //bs help + + //battlestations h + //stations h + //bs h + +**list _[radios|stations] [category#]_** + +Displays the available radios and or stations. Below are some useage examples of this command: + + //bs list + //bs l + + //bs list radios + //bs l radios + //bs l r + + //bs list stations + //bs l stations + //bs l s + + //bs l s 100 + +* _**[radios|stations]:**_ Optional parameter used to filter the list display to show only available radios or stations. If neither filter type is present, all available stations and radios will be listed. +* _**[category#]:**_ Optional parameter used to filter the list of stations by the given category number. The available category numbers are 100-107. + +**set _\ [radio]_** + +Sets the radio(s) to the given station. Below are some useage examples of this command: + + //bs set 100.1 + //bs s 100.1 + + //bs s 100.1 solo + //bs s 100.1 party + +* _**\:**_ Required parameter. +* _**[radio]:**_ Optional parameter used to specify which radio to set the given station to. If no radio type is present both radios will be set to the given station. + +**get _[radio]_** + +Displays the currently set station on the given radio(s). Below are some useage examples of this command: + + //bs get + //bs g + + //bs g solo + //bs g party + +* _**[radio]:**_ Optional parameter used to specify the radio for which you would like to display the currently set station. If no radio type is present, the currently set station for both radios will be displayed. + +**default _[radio]_** + +Sets the given radio(s) to the default station (Current Zone Music). Below are some useage examples of this command: + + //bs default + //bs d + + //bs d solo + //bs d party + +* _**[radio]:**_ Optional parameter used to specify which radio to set the default station to. If no radio type is present, both radios will be set to the default station. + + +**normal _[radio]_** + +Sets the given radio(s) to the original game music. Below are some useage examples of this command: + + //bs normal + //bs n + + //bs n solo + //bs n party + +* _**[radio]:**_ Optional parameter used to specify which radio to set the normal station to. If no radio type is present, both radios will be set to the normal station. + +**reload** + +Reloads the Battle Stations addon. Below are the equivalent ways of calling the command: + + //battlestations reload + //stations reload + //bs reload + + //battlestations r + //stations r + //bs r + +**about** + +Displays information about the Battle Stations addon. Below are the equivalent ways of calling the command: + + /battlestations about + //stations about + //bs about + + //battlestations a + //stations a + //bs a + +___ +### Support +**Having Issues with this addon?** +* Please let me know [here](https://github.com/Ap0gee/BattleStations/issues/new). + +**Have something to say?** +* Send me some feedback here: + +**Want to stay in the loop with my work?** +* You can follow me at: + +**Want to toss a coin to your modder?** +* You can do so here: + +___ +### Change Log + +**v0.9.1** - 12/29/2019 +- **Fix:** Resolved mismatched setting type error within the `bs normal` command. +- **Add:** New command added (about). +- **Update:** Silent song id changed to help prevent future game updates from overriding. +- **Update:** README Commands updated. +- **Update:** README Aliases updated. +- **Update:** README Known Issues updated. +- **Update:** README TODOS updated. + +**v0.9.0** - 6/19/2018 +- Initial release + +___ +### Known Issues + +- **Issue:** During campaign battles in the past, the music switches from the campaign music to the normal zone music while stations are set to `107.3`. + +___ +### TODOS + +- **TODO:** Consider providing aliases to stations to make references easier. +- **TODO:** Consider adding categories as a list type. +- **TODO:** Investigate methods for resolving the campaign battle music issue. +___ + +### License + +Copyright © 2018, [Sjshovan (Apogee)](https://github.com/Ap0gee). +Released under the [BSD License](LICENSE). + +*** \ No newline at end of file diff --git a/addons/BattleStations/battlestations.lua b/addons/BattleStations/battlestations.lua new file mode 100644 index 0000000000..fa8a9b15ee --- /dev/null +++ b/addons/BattleStations/battlestations.lua @@ -0,0 +1,598 @@ +--[[ +Copyright © 2018, Sjshovan (Apogee) +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 Battle Stations 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 Sjshovan (Apogee) 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.name = 'Battle Stations' +_addon.description = 'Change or remove the default battle music.' +_addon.author = 'Sjshovan (Apogee) sjshovan@gmail.com' +_addon.version = '0.9.1' +_addon.commands = {'battlestations', 'stations', 'bs'} + +local _logger = require('logger') +local _config = require('config') +local _packets = require('packets') + +require('functions') +require('constants') +require('helpers') + +local defaults = { + stations = { + solo = 107.3, + party = 107.3 + } +} + +local settings = _config.load(defaults) + +local help = { + commands = { + buildHelpSeperator('=', 28), + buildHelpTitle('Commands'), + buildHelpSeperator('=', 28), + buildHelpCommandEntry('list [radios|stations] [category#]', 'Display the available radios and or stations.'), + buildHelpCommandEntry('set [radio]', 'Set radio(s) to the given station.'), + buildHelpCommandEntry('get [radio]', 'Display currently set station on the given radio(s).'), + buildHelpCommandEntry('default [radio]', 'Set radio(s) to the default station (Current Zone Music).'), + buildHelpCommandEntry('normal [radio]', 'Set radio(s) to the original game music.'), + buildHelpCommandEntry('reload', 'Reload Battle Stations.'), + buildHelpCommandEntry('about', 'Display information about Battle Stations.'), + buildHelpCommandEntry('help', 'Display Battle Stations commands.'), + buildHelpSeperator('=', 28), + }, + + radios = { + buildHelpSeperator('=', 25), + buildHelpTitle('Radios'), + buildHelpSeperator('=', 25), + buildHelpRadioEntry(stations.receivers.solo:ucfirst(), 'Plays Solo Battle Music'), + buildHelpRadioEntry(stations.receivers.party:ucfirst(), 'Plays Party Battle Music'), + buildHelpSeperator('=', 25), + }, + + about = { + buildHelpSeperator('=', 23), + buildHelpTitle('About'), + buildHelpSeperator('=', 23), + buildHelpTypeEntry('Name', _addon.name), + buildHelpTypeEntry('Description', _addon.description), + buildHelpTypeEntry('Author', _addon.author), + buildHelpTypeEntry('Version', _addon.version), + buildHelpSeperator('=', 23), + }, + + aliases = { + list = { + stations = T{ + 's', + 'station', + 'stations', + }, + radios = T{ + 'r', + 'radio', + 'radios', + 'receiver', + 'receivers' + }, + categories = T{ + 'c', + 'cat', + 'category', + 'categories' + }, + all = T{ + '*', + 'a', + 'all', + } + } + } +} + +function displayHelp(table_help) + for index, command in pairs(table_help) do + displayResponse(command) + end +end + +function displayStations(range) + displayResponse(buildHelpSeperator('=', 27)) + displayResponse(buildHelpTitle('Stations')) + displayResponse(buildHelpSeperator('=', 27)) + + if range ~= nil then + if categoryValid(range) then + displayRangeFrequencies(range) + end + else + for i=100, 107, 1 do + range = tostring(i) + displayRangeFrequencies(range) + end + end + displayResponse(buildHelpSeperator('=', 26)) +end + +function displayRangeFrequencies(range, name) + local categories = stations.categories + + if categoryValid(range) then + local name = categories[range] + displayResponse(buildHelpStationCategoryEntry(range, name)) + displayFrequencies(range) + end +end + +function displayFrequencies(range) + for i=1, 9, 1 do + local frequency = range .. '.%s':format(tostring(i)) + if frequencyValid(frequency) then + local frequencyObj = getFrequencyObjByValue(frequency) + local response = buildHelpStationEntry(frequency, frequencyObj.callSign) + displayResponse(response) + end + end +end + +function displayCategories() + displayResponse(buildHelpSeperator('=', 27)) + displayResponse(buildHelpTitle('Categories')) + displayResponse(buildHelpSeperator('=', 27)) + for i=100, 107, 1 do + local range = tostring(i) + if categoryValid(range) then + local name = stations.categories[range] + displayResponse(buildHelpStationCategoryEntry(range, name)) + end + end + displayResponse(buildHelpSeperator('=', 27)) +end + +function getStations() + return settings.stations +end + +function setStation(radio, frequency) + if radio == stations.receivers.solo then + settings.stations.solo = frequency + elseif radio == stations.receivers.party then + settings.stations.party = frequency + else + settings.stations.solo = frequency + settings.stations.party = frequency + end + + settings:save() +end + +function resolveCurrentStations() + local current_stations = getStations() + local radio = 'solo' + local frequency = tostring(defaults.stations.solo) + local message_template = '%s station found in settings was not valid and was set to the default %s (%s).' + + if not frequencyValid(current_stations.solo) then + current_stations.solo = frequency + setStation(radio, frequency) + + displayResponse( + buildWarningMessage( + message_template:format( + radio:ucfirst():color(colors.secondary), + frequency:color(colors.primary), + getFrequencyObjByValue(frequency).callSign + ) + ) + ) + end + + if not frequencyValid(current_stations.party) then + radio = 'party' + frequency = tostring(defaults.stations.party) + current_stations.party = party_default + + setStation(radio, frequency) + + displayResponse( + buildWarningMessage( + message_template:format( + radio:ucfirst():color(colors.secondary), + frequency:color(colors.primary), + getFrequencyObjByValue(frequency).callSign + ) + ) + ) + end + + return current_stations +end + +function injectBattleMusic() + local current_stations = resolveCurrentStations() + local song = getFrequencyObjByValue(current_stations.solo).song + local music_type = music.types.battle_solo + + if playerInParty() then + music_type = music.types.battle_party + song = getFrequencyObjByValue(current_stations.party).song + end + + song = getConditionalSongTranslation(song) + + _packets.inject(_packets.new('incoming', packets.inbound.music_change.id, { + ['BGM Type'] = music_type, + ['Song ID'] = song + })) +end + +function getFrequencyObjByValue(frequency) + return stations.frequencies[tostring(frequency)] +end + +function getCurrentTime(formatted) + local timestamp = tostring(windower.ffxi.get_info().time) + local hours = (timestamp / 60):floor() + local minutes = timestamp % 60 + if formatted then + return "%s:%s":format(hours, minutes) + end + return timestamp +end + +function getZoneBGMTable() + local data = windower.packets.last_incoming(packets.inbound.zone_update.id) + local packet = _packets.parse('incoming', data) + return { + day = packet['Day Music'], + night = packet['Night Music'], + solo = packet['Solo Combat Music'], + party = packet['Party Combat Music'] + } +end + +function getConditionalSongTranslation(song) + local zone_bgm_table = getZoneBGMTable() + if song == music.songs.others.zone then + if timeIsDaytime() then + song = zone_bgm_table.day + else + song = zone_bgm_table.night + end + + if playerInReive() then + song = music.songs.seekers_of_adoulin.breaking_ground + end + + elseif song == music.songs.others.normal then + if playerInParty() then + song = zone_bgm_table.party + else + song = zone_bgm_table.solo + end + end + return song +end + +function getPlayerBuffs() + return T(windower.ffxi.get_player().buffs) +end + +function timeIsDaytime() + local current_time = tonumber(getCurrentTime()) + return current_time >= 6*60 and current_time <= 18*60 +end + +function playerIsFighting() + return windower.ffxi.get_player().status == player.statuses.fighting +end + +function playerInParty() + return windower.ffxi.get_party().alliance_count > 1 +end + +function playerInReive() + return getPlayerBuffs():contains(player.buffs.reiveMark) +end + +function frequencyValid(frequency) + return stations.frequencies[tostring(frequency)] ~= nil +end + +function radioValid(radio) + return stations.receivers[radio] ~= nil or radio == '*' +end + +function categoryValid(category) + return stations.categories[category] ~= nil +end + +function listTypeValid(list_type) + return help.lists[list_type] ~= nil +end + +function handleInjectionNeeds() + if needs_inject then + injectBattleMusic() + needs_inject = false; + end +end + +windower.register_event('load', function () + injectBattleMusic() +end) + +windower.register_event('unload', function() + local music_type = music.types.battle_solo + local zone_bgm_table = getZoneBGMTable() + local song = zone_bgm_table.solo + + if playerInParty() then + music_type = music.types.battle_party + song = zone_bgm_table.solo + end + + _packets.inject(_packets.new('incoming', packets.inbound.music_change.id, { + ['BGM Type'] = music_type, + ['Song ID'] = song, + })) +end) + +windower.register_event('action', function(act) + if act.actor_id == windower.ffxi.get_player().id then + if act.category == 4 and act.recast == 225 and act.targets[1].actions[1].animation == 939 then + if not playerInParty() then + functions.loop(injectBattleMusic, 1, 5) + end + end + end +end) + +windower.register_event('outgoing chunk', function(id, data) + if id == packets.outbound.action.id then + local packet = _packets.parse('outgoing', data) + if packet.Category == packets.outbound.action.categories.engage then + injectBattleMusic() + end + end +end) + +windower.register_event('addon command', function(command, ...) + if command then + command = command:lower() + else + displayHelp(help.commands) + return + end + + local command_args = {...} + + local respond = false + local response_message = '' + local success = true + + if command == 'list' or command == 'l' then + local list_type = tostring(command_args[1] or '*'):lower() + local category = command_args[2] + + if help.aliases.list.stations:contains(list_type) then + if category then + category = tostring(category) + if categoryValid(category) then + displayStations(category) + + else + respond = true + success = false + response_message = 'Category not recognized.' + end + else + displayStations() + end + + elseif help.aliases.list.radios:contains(list_type) then + displayHelp(help.radios) + + elseif help.aliases.list.categories:contains(list_type) then + displayCategories() + + elseif help.aliases.list.all:contains(list_type) then + displayHelp(help.radios) + displayStations() + + else + respond = true + success = false + response_message = 'List type not recognized.' + end + + elseif command == 'set' or command == 's' then + respond = true + + local frequency = tostring(command_args[1]):lower() + + local radio = tostring(command_args[2] or '*'):lower() + + if not frequencyValid(frequency) then + success = false + response_message = 'Frequency not recognized.' + + elseif not radioValid(radio) then + success = false + response_message = 'Radio not recognized.' + else + needs_inject = true + + local context = 'radio' + + setStation(radio, tonumber(frequency)) + + if radio == '*' then + context = 'radios' + radio = 'Solo and Party' + end + + response_message = buildSetResponseMessage( + radio:ucfirst(), + context, + frequency, + getFrequencyObjByValue(frequency).callSign + )..'.' + end + + elseif command == 'get' or command == 'g' then + respond = true + + local current_stations = resolveCurrentStations() + local radio = tostring(command_args[1] or '*'):lower() + local frequency = current_stations[radio] + local frequency2 = current_stations.party + local individual = false + + if not radioValid(radio) then + success = false + response_message = 'Radio not recognized.' + else + local context = 'radio is' + + if radio == '*' then + frequency = current_stations.solo + + if current_stations.party ~= current_stations.solo then + individual = true + else + context = 'radios are' + radio = 'Solo and Party' + end + end + + if not individual then + response_message = buildGetResponseMessage( + radio:ucfirst(), + context, + frequency, + getFrequencyObjByValue(frequency).callSign + )..'.' + + else + local solo_message = buildGetResponseMessage( + stations.receivers.solo:ucfirst(), + context, + frequency, + getFrequencyObjByValue(frequency).callSign + ) + + local party_message = buildGetResponseMessage( + stations.receivers.party:ucfirst(), + context, + frequency2, + getFrequencyObjByValue(frequency2).callSign + ) + + response_message = solo_message..' and '..party_message..'.' + end + end + + elseif command == 'default' or command == 'd' then + respond = true + + local radio = tostring(command_args[1] or '*'):lower() + + if not radioValid(radio) then + success = false + response_message = 'Radio not recognized.' + else + needs_inject = true + + local frequency = defaults.stations.solo + local context = 'radio' + + setStation(radio, tonumber(frequency)) + + if radio == '*' then + context = 'radios' + radio = 'Solo and Party' + end + + response_message = buildSetResponseMessage( + radio:ucfirst(), + context, + frequency, + getFrequencyObjByValue(frequency).callSign + )..'.' + end + + elseif command == 'normal' or command == 'n' then + respond = true + + local radio = tostring(command_args[1] or '*'):lower() + + if not radioValid(radio) then + success = false + response_message = 'Radio not recognized.' + else + needs_inject = true + + local frequency = '107.2' + local context = 'radio' + + setStation(radio, tonumber(frequency)) + + if radio == '*' then + context = 'radios' + radio = 'Solo and Party' + end + + response_message = buildSetResponseMessage( + radio:ucfirst(), + context, + frequency, + getFrequencyObjByValue(frequency).callSign + )..'.' + end + + elseif command == 'reload' or command == 'r' then + windower.send_command('lua r battlestations') + + elseif command == 'about' or command == 'a' then + displayHelp(help.about) + + elseif command == 'help' or command == 'h' then + displayHelp(help.commands) + + else + displayHelp(help.commands) + end + + if respond then + displayResponse( + buildCommandResponse(response_message, success) + ) + end + + handleInjectionNeeds() +end) \ No newline at end of file diff --git a/addons/BattleStations/constants.lua b/addons/BattleStations/constants.lua new file mode 100644 index 0000000000..8087093fde --- /dev/null +++ b/addons/BattleStations/constants.lua @@ -0,0 +1,382 @@ +--[[ +Copyright © 2018, Sjshovan (Apogee) +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 Battle Stations 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 Sjshovan (Apogee) 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. +]] + +packets = { + inbound = { + music_change = { + id = 0x05F + }, + zone_update = { + id = 0x00A + } + }, + outbound = { + action = { + id = 0x1A, + categories = { + engage = 2, + disengage = 4 + + }, + } + }, +} + +player = { + statuses = { + idle = 0x00, + fighting = 0x01, + }, + buffs = { + reiveMark = 511 + } +} + +colors = { + primary = 200, + secondary = 207, + info = 0, + warn = 140, + danger = 167, + success = 158 +} + +music = { + songs = { + final_fantasy_xi = { + battle_theme = 101, + battle_theme_2 = 103, + battle_in_the_dungeon = 115, + battle_in_the_dungeon_2 = 102, + tough_battle = 125, + awakening = 119 + }, + rise_of_the_zilart = { + battle_theme_3 = 191, + battle_in_the_dungeon_3 = 192, + tough_battle_2 = 193, + fighters_of_the_crystal = 196, + ealdnarche = 198, + belief = 195 + }, + chains_of_promathia = { + onslaught = 219, + depths_of_the_soul = 218, + turmoil = 220, + ruler_of_the_skies = 232, + dusk_and_dawn = 224, + a_realm_of_emptiness = 137 + }, + treasures_of_aht_urhgan = { + mercenaries_delight = 138, + delve = 139, + rapid_onslaught_assault = 144, + fated_strife_besieged = 142, + hellriders = 143, + black_coffin = 172, + iron_colossus = 186, + ragnarok = 187 + }, + wings_of_the_goddess = { + clash_of_standards = 215, + on_this_blade = 216, + roar_of_the_battle_drums = 247, + run_maggot_run = 249, + under_a_clouded_moon = 250, + kindred_cry = 217, + provenance_watcher = 55, + goddess_divine = 46 + }, + seekers_of_adoulin = { + steel_sings_blades_dance = 57, + breaking_ground = 64, + buccaneers = 170, + keepers_of_the_wild = 62 + }, + add_ons = { + echoes_of_creation = 47, + luck_of_the_mog = 49, + a_feast_for_ladies = 50, + melodies_errant = 52, + shinryu = 53, + wail_of_the_void = 82 + }, + others = { + silent = 9999, + normal = 09, + zone = 00 + }, + }, + types = { + battle_solo = 2, + battle_party = 3, + idle_day = 0, + idle_night = 1 + } +} + +stations = { + receivers = T{ + solo = 'solo', + party = 'party' + }, + + categories = T{ + ['100'] = 'Final Fantasy XI', + ['101'] = 'Rise of the Zilart', + ['102'] = 'Chains of Promathia', + ['103'] = 'Treasures of Aht Urhgan', + ['104'] = 'Wings of the Goddess', + ['105'] = 'Seekers of Adoulin', + ['106'] = 'Add-Ons', + ['107'] = 'Others' + }, + + frequencies = T{ + + --(100) Final Fantasy XI -- + + ['100.1'] = { + callSign = 'Battle Theme', + song = music.songs.final_fantasy_xi.battle_theme + }, + ['100.2'] = { + callSign = 'Battle Theme 2', + song = music.songs.final_fantasy_xi.battle_theme_2 + }, + ['100.3'] = { + callSign = 'Battle in the Dungeon', + song = music.songs.final_fantasy_xi.battle_in_the_dungeon + }, + ['100.4'] = { + callSign = 'Battle in the Dungeon 2', + song = music.songs.final_fantasy_xi.battle_in_the_dungeon_2 + }, + ['100.5'] = { + callSign = 'Tough Battle', + song = music.songs.final_fantasy_xi.tough_battle + }, + ['100.6'] = { + callSign = 'Awakening', + song = music.songs.final_fantasy_xi.awakening + }, + + --(101) Rise of the Zilart -- + + ['101.1'] = { + callSign = 'Battle Theme 3', + song = music.songs.rise_of_the_zilart.battle_theme_3 + }, + ['101.2'] = { + callSign = 'Battle in the Dungeon 3', + song = music.songs.rise_of_the_zilart.battle_in_the_dungeon_3 + }, + ['101.3'] = { + callSign = 'Tough Battle 2', + song = music.songs.rise_of_the_zilart.tough_battle_2 + }, + ['101.4'] = { + callSign = 'Fighters of the Crystal', + song = music.songs.rise_of_the_zilart.fighters_of_the_crystal + }, + ['101.5'] = { + callSign = "Eald'narche", + song = music.songs.rise_of_the_zilart.ealdnarche + }, + ['101.6'] = { + callSign = 'Belief', + song = music.songs.rise_of_the_zilart.belief + }, + + --(102) Chains of Promathia -- + + ['102.1'] = { + callSign = 'Onslaught', + song = music.songs.chains_of_promathia.onslaught + }, + ['102.2'] = { + callSign = 'Depths of the Soul', + song = music.songs.chains_of_promathia.depths_of_the_soul + }, + ['102.3'] = { + callSign = 'Turmoil', + song = music.songs.chains_of_promathia.turmoil + }, + ['102.4'] = { + callSign = 'Ruler of the Skies', + song = music.songs.chains_of_promathia.ruler_of_the_skies + }, + ['102.5'] = { + callSign = 'Dusk and Dawn', + song = music.songs.chains_of_promathia.dusk_and_dawn + }, + ['102.6'] = { + callSign = 'A Realm of Emptiness', + song = music.songs.chains_of_promathia.a_realm_of_emptiness + }, + + --(103) Treasures of Aht Urhgan -- + + ['103.1'] = { + callSign = "Mercenaries' Delight", + song = music.songs.treasures_of_aht_urhgan.mercenaries_delight + }, + ['103.2'] = { + callSign = 'Delve', + song = music.songs.treasures_of_aht_urhgan.delve + }, + ['103.3'] = { + callSign = 'Rapid Onslaught -Assult-', + song = music.songs.treasures_of_aht_urhgan.rapid_onslaught_assault + }, + ['103.4'] = { + callSign = 'Fated Strife -Besieged-', + song = music.songs.treasures_of_aht_urhgan.fated_strife_besieged + }, + ['103.5'] = { + callSign = 'Hellriders', + song = music.songs.treasures_of_aht_urhgan.hellriders + }, + ['103.6'] = { + callSign = 'Black Coffin', + song = music.songs.treasures_of_aht_urhgan.black_coffin + }, + ['103.7'] = { + callSign = 'Iron Colossus', + song = music.songs.treasures_of_aht_urhgan.iron_colossus + }, + ['103.8'] = { + callSign = 'Ragnarok', + song = music.songs.treasures_of_aht_urhgan.ragnarok + }, + + --(104) Wings of the Goddess -- + + ['104.1'] = { + callSign = 'Clash of Standards', + song = music.songs.wings_of_the_goddess.clash_of_standards + }, + ['104.2'] = { + callSign = 'On this Blade', + song = music.songs.wings_of_the_goddess.on_this_blade + }, + ['104.3'] = { + callSign = 'Roar of the Battle Drums', + song = music.songs.wings_of_the_goddess.roar_of_the_battle_drums + }, + ['104.4'] = { + callSign = 'Run Maggot, Run!', + song = music.songs.wings_of_the_goddess.run_maggot_run + }, + ['104.5'] = { + callSign = 'Under a Clouded Moon', + song = music.songs.wings_of_the_goddess.under_a_clouded_moon + }, + ['104.6'] = { + callSign = 'Kindred Cry', + song = music.songs.wings_of_the_goddess.kindred_cry + }, + ['104.7'] = { + callSign = 'Provenance Watcher', + song = music.songs.wings_of_the_goddess.provenance_watcher + }, + ['104.8'] = { + callSign = 'Goddess Divine', + song = music.songs.wings_of_the_goddess.goddess_divine + }, + + --(105) Seekers of Adoulin -- + + ['105.1'] = { + callSign = 'Steel Sings, Blades Dance', + song = music.songs.seekers_of_adoulin.steel_sings_blades_dance + }, + ['105.2'] = { + callSign = 'Braking Ground', + song = music.songs.seekers_of_adoulin.breaking_ground + }, + ['105.3'] = { + callSign = 'Buccaneers', + song = music.songs.seekers_of_adoulin.buccaneers + }, + ['105.4'] = { + callSign = 'Keepers of the Wild', + song = music.songs.seekers_of_adoulin.keepers_of_the_wild + }, + + --(106) Add-Ons -- + + ['106.1'] = { + callSign = 'Echoes of Creation', + song = music.songs.add_ons.echoes_of_creation + }, + ['106.2'] = { + callSign = 'Luck of the Mog', + song = music.songs.add_ons.luck_of_the_mog + }, + ['106.3'] = { + callSign = 'A Feast for Ladies', + song = music.songs.add_ons.a_feast_for_ladies + }, + ['106.4'] = { + callSign = 'Melodies Errant', + song = music.songs.add_ons.melodies_errant + }, + ['106.5'] = { + callSign = 'Shinryu', + song = music.songs.add_ons.shinryu + }, + ['106.6'] = { + callSign = 'Wail of the Void', + song = music.songs.add_ons.wail_of_the_void + }, + + --(107) Others -- + + ['107.1'] = { + callSign = 'No Music', + song = music.songs.others.silent + }, + ['107.2'] = { + callSign = 'Original Music', + song = music.songs.others.normal + }, + ['107.3'] = { + callSign = 'Current Zone Music (Default)', + song = music.songs.others.zone + } + } +} + +return { + packets = packets, + player = player, + colors = colors, + music = music, + stations = stations +} \ No newline at end of file diff --git a/addons/BattleStations/helpers.lua b/addons/BattleStations/helpers.lua new file mode 100644 index 0000000000..f30e51eec4 --- /dev/null +++ b/addons/BattleStations/helpers.lua @@ -0,0 +1,121 @@ +--[[ +Copyright © 2018, Sjshovan (Apogee) +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 Battle Stations 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 Sjshovan (Apogee) 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. +]] + +local colors = require("constants").colors + +function buildHelpCommandEntry(command, description) + local entry_template = "%s %s %s %s" + local short_name = "bs":color(colors.primary) + local command = command:color(colors.secondary) + local sep = "=>":color(colors.primary) + local description = description:color(colors.info) + return entry_template:format(short_name, command, sep, description) +end + +function buildHelpTypeEntry(name, description) + local entry_template = "%s %s %s" + local name = name:color(colors.secondary) + local sep = "=>":color(colors.primary) + local description = description:color(colors.info) + return entry_template:format(name, sep, description) +end + +function buildHelpRadioEntry(name, description) + local entry_template = "%s %s %s" + local name = name:color(colors.secondary) + local sep = "=>":color(colors.primary) + local description = description:color(colors.info) + return entry_template:format(name, sep, description) +end + +function buildHelpStationEntry(frequency, callSign) + local entry_template = " %s %s %s" + local frequency = frequency:color(colors.secondary) + local sep = "=>":color(colors.primary) + local callSign = callSign:color(colors.info) + return entry_template:format(frequency, sep, callSign) +end + +function buildHelpStationCategoryEntry(range, name) + local entry_template = "(%s) %s" + local range = range:color(colors.primary) + local name = name:color(colors.danger) + return entry_template:format(range, name) +end + +function buildHelpTitle(context) + local title_template = "%s Help: %s" + local context = context:color(colors.danger) + return title_template:color(colors.primary):format(_addon.name, context) +end + +function buildHelpSeperator(character, count) + local sep = '' + for i = 1, count do + sep = sep .. character + end + return sep:color(colors.warn) +end + +function buildCommandResponse(message, success) + local response_template = '%s: %s' + local response_color = colors.success + local response_type = 'Success' + + if not success then + response_type = 'Error' + response_color = colors.danger + end + return response_template:format(response_type:color(response_color), message) +end + +function buildWarningMessage(message) + local message_template = '%s: %s' + local response_type = 'Note' + return message_template:format(response_type:color(colors.warn), message) +end + +function buildGetResponseMessage(radio, context, frequency, callSign) + local message_template = '%s %s currently set to %s (%s)' + radio = radio:color(colors.secondary) + frequency = tostring(frequency):color(colors.primary) + return message_template:format(radio, context, frequency, callSign) +end + +function buildSetResponseMessage(radio, context, frequency, callSign) + local message_template = '%s %s updated to station %s (%s)' + radio = radio:color(colors.secondary) + frequency = tostring(frequency):color(colors.primary) + return message_template:format(radio, context, frequency, callSign) +end + +function displayResponse(response, color) + color = color or colors.info + windower.add_to_chat(color, response) + windower.console.write(response:strip_colors()) +end \ No newline at end of file diff --git a/addons/addons.xml b/addons/addons.xml index b2780a5435..c98bca3cf3 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -86,6 +86,13 @@ Customizes battle chat messages. https://github.com/Byrth/Lua-Byrth/issues https://discord.gg/b275nMv + + + BattleStations + Sjshovan (Apogee) + Change or remove the default battle music. + https://github.com/Windower/Lua/issues + https://discord.gg/b275nMv Blist From 40cf8657e63494235b9bd703379b4d0417c3da9e Mon Sep 17 00:00:00 2001 From: Chiaia Date: Sun, 29 Dec 2019 22:14:59 -0500 Subject: [PATCH 0329/1002] Update fields.lua --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 04116f62ec..e7bf4433da 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -683,7 +683,7 @@ fields.outgoing[0x05C] = L{ {ctype='unsigned short', label='Zone'}, -- 18 {ctype='unsigned short', label='Menu ID'}, -- 1A {ctype='unsigned short', label='Target Index', fn=index}, -- 1C - {ctype='unsigned short', label='_unknown3'}, -- 1E Not zone ID + {ctype='unsigned short', label='Direction'}, -- 1E } -- Outgoing emote From 2d448c2da94bf5dff395f7a4defbb3b774250186 Mon Sep 17 00:00:00 2001 From: Sjshovan Date: Mon, 30 Dec 2019 07:45:27 -0500 Subject: [PATCH 0330/1002] update installation instructions --- addons/BattleStations/README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/addons/BattleStations/README.md b/addons/BattleStations/README.md index 4587aa808c..c378e50bfc 100644 --- a/addons/BattleStations/README.md +++ b/addons/BattleStations/README.md @@ -29,7 +29,10 @@ ___ ### Installation **Windower:** -Not yet available on windower, installation will have to be done manually. +1. Navigate to the `Addons` section at the top of Windower. +2. Locate the `BattleStations` addon. +3. Click the download button. +4. Ensure the addon is switched on. **Manual:** 1. Navigate to . From 60ac22c9f41b9569e9113471ed354327ba4cf870 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Mon, 30 Dec 2019 15:17:33 -0500 Subject: [PATCH 0331/1002] Update fields.lua --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index e7bf4433da..dadda57c7c 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -683,7 +683,7 @@ fields.outgoing[0x05C] = L{ {ctype='unsigned short', label='Zone'}, -- 18 {ctype='unsigned short', label='Menu ID'}, -- 1A {ctype='unsigned short', label='Target Index', fn=index}, -- 1C - {ctype='unsigned short', label='Direction'}, -- 1E + {ctype='unsigned char', label='Rotation'}, -- 1E } -- Outgoing emote From f7588acf72ae2e8e1b72bf52df3c69f0066a6950 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Mon, 30 Dec 2019 16:10:39 -0500 Subject: [PATCH 0332/1002] Kenshi Info --- addons/libs/packets/fields.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index dadda57c7c..c9d325e879 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -683,7 +683,8 @@ fields.outgoing[0x05C] = L{ {ctype='unsigned short', label='Zone'}, -- 18 {ctype='unsigned short', label='Menu ID'}, -- 1A {ctype='unsigned short', label='Target Index', fn=index}, -- 1C - {ctype='unsigned char', label='Rotation'}, -- 1E + {ctype='unsigned char', label='_unknown2', const=1}, -- 1E + {ctype='unsigned char', label='Rotation'}, -- 1F } -- Outgoing emote From f362c9a4ad7dcd3d7edd868f2cc9e8ab1552ad3d Mon Sep 17 00:00:00 2001 From: Sjshovan Date: Tue, 31 Dec 2019 16:26:35 -0500 Subject: [PATCH 0333/1002] replace tabs with spaces remove unnecessary string conversions remove accidental space character in addons.xml --- addons/BattleStations/README.md | 16 +++++----- addons/BattleStations/battlestations.lua | 37 ++++++++++++------------ addons/BattleStations/constants.lua | 4 +-- addons/BattleStations/helpers.lua | 2 +- addons/addons.xml | 2 +- 5 files changed, 30 insertions(+), 31 deletions(-) diff --git a/addons/BattleStations/README.md b/addons/BattleStations/README.md index c378e50bfc..83fd082457 100644 --- a/addons/BattleStations/README.md +++ b/addons/BattleStations/README.md @@ -84,7 +84,7 @@ Displays the available Battle Stations commands. Below are the equivalent ways o **list _[radios|stations] [category#]_** Displays the available radios and or stations. Below are some useage examples of this command: - + //bs list //bs l @@ -92,7 +92,7 @@ Displays the available radios and or stations. Below are some useage examples of //bs l radios //bs l r - //bs list stations + //bs list stations //bs l stations //bs l s @@ -130,9 +130,9 @@ Displays the currently set station on the given radio(s). Below are some useage Sets the given radio(s) to the default station (Current Zone Music). Below are some useage examples of this command: - //bs default + //bs default //bs d - + //bs d solo //bs d party @@ -143,9 +143,9 @@ Sets the given radio(s) to the default station (Current Zone Music). Below are s Sets the given radio(s) to the original game music. Below are some useage examples of this command: - //bs normal + //bs normal //bs n - + //bs n solo //bs n party @@ -154,7 +154,7 @@ Sets the given radio(s) to the original game music. Below are some useage exampl **reload** Reloads the Battle Stations addon. Below are the equivalent ways of calling the command: - + //battlestations reload //stations reload //bs reload @@ -166,7 +166,7 @@ Reloads the Battle Stations addon. Below are the equivalent ways of calling the **about** Displays information about the Battle Stations addon. Below are the equivalent ways of calling the command: - + /battlestations about //stations about //bs about diff --git a/addons/BattleStations/battlestations.lua b/addons/BattleStations/battlestations.lua index fa8a9b15ee..5c2922ad1f 100644 --- a/addons/BattleStations/battlestations.lua +++ b/addons/BattleStations/battlestations.lua @@ -60,7 +60,7 @@ local help = { buildHelpCommandEntry('default [radio]', 'Set radio(s) to the default station (Current Zone Music).'), buildHelpCommandEntry('normal [radio]', 'Set radio(s) to the original game music.'), buildHelpCommandEntry('reload', 'Reload Battle Stations.'), - buildHelpCommandEntry('about', 'Display information about Battle Stations.'), + buildHelpCommandEntry('about', 'Display information about Battle Stations.'), buildHelpCommandEntry('help', 'Display Battle Stations commands.'), buildHelpSeperator('=', 28), }, @@ -73,8 +73,8 @@ local help = { buildHelpRadioEntry(stations.receivers.party:ucfirst(), 'Plays Party Battle Music'), buildHelpSeperator('=', 25), }, - - about = { + + about = { buildHelpSeperator('=', 23), buildHelpTitle('About'), buildHelpSeperator('=', 23), @@ -336,9 +336,9 @@ function listTypeValid(list_type) end function handleInjectionNeeds() - if needs_inject then - injectBattleMusic() - needs_inject = false; + if needs_inject then + injectBattleMusic() + needs_inject = false; end end @@ -373,7 +373,7 @@ windower.register_event('action', function(act) end) windower.register_event('outgoing chunk', function(id, data) - if id == packets.outbound.action.id then + if id == packets.outbound.action.id then local packet = _packets.parse('outgoing', data) if packet.Category == packets.outbound.action.categories.engage then injectBattleMusic() @@ -390,18 +390,17 @@ windower.register_event('addon command', function(command, ...) end local command_args = {...} - + local respond = false local response_message = '' local success = true if command == 'list' or command == 'l' then - local list_type = tostring(command_args[1] or '*'):lower() + local list_type = (command_args[1] or '*'):lower() local category = command_args[2] - + if help.aliases.list.stations:contains(list_type) then if category then - category = tostring(category) if categoryValid(category) then displayStations(category) @@ -433,9 +432,9 @@ windower.register_event('addon command', function(command, ...) elseif command == 'set' or command == 's' then respond = true - local frequency = tostring(command_args[1]):lower() + local frequency = command_args[1]:lower() - local radio = tostring(command_args[2] or '*'):lower() + local radio = (command_args[2] or '*'):lower() if not frequencyValid(frequency) then success = false @@ -468,7 +467,7 @@ windower.register_event('addon command', function(command, ...) respond = true local current_stations = resolveCurrentStations() - local radio = tostring(command_args[1] or '*'):lower() + local radio = (command_args[1] or '*'):lower() local frequency = current_stations[radio] local frequency2 = current_stations.party local individual = false @@ -520,7 +519,7 @@ windower.register_event('addon command', function(command, ...) elseif command == 'default' or command == 'd' then respond = true - local radio = tostring(command_args[1] or '*'):lower() + local radio = (command_args[1] or '*'):lower() if not radioValid(radio) then success = false @@ -549,7 +548,7 @@ windower.register_event('addon command', function(command, ...) elseif command == 'normal' or command == 'n' then respond = true - local radio = tostring(command_args[1] or '*'):lower() + local radio = (command_args[1] or '*'):lower() if not radioValid(radio) then success = false @@ -577,9 +576,9 @@ windower.register_event('addon command', function(command, ...) elseif command == 'reload' or command == 'r' then windower.send_command('lua r battlestations') - - elseif command == 'about' or command == 'a' then - displayHelp(help.about) + + elseif command == 'about' or command == 'a' then + displayHelp(help.about) elseif command == 'help' or command == 'h' then displayHelp(help.commands) diff --git a/addons/BattleStations/constants.lua b/addons/BattleStations/constants.lua index 8087093fde..950ecc103b 100644 --- a/addons/BattleStations/constants.lua +++ b/addons/BattleStations/constants.lua @@ -48,10 +48,10 @@ packets = { } player = { - statuses = { + statuses = { idle = 0x00, fighting = 0x01, - }, + }, buffs = { reiveMark = 511 } diff --git a/addons/BattleStations/helpers.lua b/addons/BattleStations/helpers.lua index f30e51eec4..17b2acfa2c 100644 --- a/addons/BattleStations/helpers.lua +++ b/addons/BattleStations/helpers.lua @@ -38,7 +38,7 @@ function buildHelpCommandEntry(command, description) end function buildHelpTypeEntry(name, description) - local entry_template = "%s %s %s" + local entry_template = "%s %s %s" local name = name:color(colors.secondary) local sep = "=>":color(colors.primary) local description = description:color(colors.info) diff --git a/addons/addons.xml b/addons/addons.xml index c98bca3cf3..f09c2cb2d5 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -87,7 +87,7 @@ https://github.com/Byrth/Lua-Byrth/issues https://discord.gg/b275nMv - + BattleStations Sjshovan (Apogee) Change or remove the default battle music. From b42f730f1df8d45126122d313ae8ac3217988823 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Wed, 1 Jan 2020 00:15:02 -0500 Subject: [PATCH 0334/1002] Path Augments for Dyna D/Necks --- addons/libs/extdata.lua | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/addons/libs/extdata.lua b/addons/libs/extdata.lua index 1070e03c65..d8759655f6 100644 --- a/addons/libs/extdata.lua +++ b/addons/libs/extdata.lua @@ -1534,6 +1534,8 @@ function tools.aug.unpack_augment(sys,short) return short:byte(1), short:byte(2) elseif sys == 3 then return short:byte(1) + short:byte(2)%8*256, math.floor(short:byte(2)%128/8) + elseif sys == 4 then + return short:byte(1), short:byte(2) end end @@ -1611,6 +1613,11 @@ function decode.Augmented(str) rettab.rank = math.floor(str:byte(3)%128/4) rettab.RP = math.max(points_map[rettab.rank] or 0 - str:byte(6)*256 - str:byte(5),0) rettab.augments = tools.aug.augments_to_table(rettab.augment_system,str:sub(7,12)) + elseif flag_2 == 131 then + rettab.augment_system = 4 + local path_map = {[0] = 'A',[1] = 'B', [2] = 'C', [3] = 'D'} + rettab.path = path_map[math.floor(str:byte(5)%4)] + rettab.augments = {'Path: ' ..rettab.path} elseif flag_2/128 >= 1 then -- Evolith rettab.augment_system = 3 local slot_type_map = {[0] = 'None', [1] = 'Filled Upside-down Triangle', [2] = 'Filled Diamond', [3] = 'Filled Star', [4] = 'Empty Triangle', [5] = 'Empty Square', [6] = 'Empty Circle', [7] = 'Empty Upside-down Triangle', [8] = 'Empty Diamond', [9] = 'Empty Star', [10] = 'Filled Triangle', [11] = 'Filled Square', [12] = 'Filled Circle', [13] = 'Empty Circle', [14] = 'Fire', [15] = 'Ice'} @@ -1658,6 +1665,7 @@ function decode.Equipment(str) local flag_1_mapping = { [1] = decode.Enchanted, [2] = decode.Augmented, + [3] = decode.Augmented, } if flag_1_mapping[flag_1] then rettab = flag_1_mapping[flag_1](str:sub(1,12)) From 788e8119cc36160c0671a18973bac76590436bf1 Mon Sep 17 00:00:00 2001 From: nekonok Date: Mon, 6 Jan 2020 13:16:53 +0900 Subject: [PATCH 0335/1002] add sub command 'wearable' to 'gs export' --- addons/GearSwap/README.md | 4 ++-- addons/GearSwap/export.lua | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/addons/GearSwap/README.md b/addons/GearSwap/README.md index 8b417af362..650af8511d 100644 --- a/addons/GearSwap/README.md +++ b/addons/GearSwap/README.md @@ -26,7 +26,7 @@ Commands (<> indicates a field. You do not actually have to use <>s): ** APPDATA/Windower/GearSwap/ ** ..Windower/addons/libs/ * gs reload : Reloads the current user file. -* gs export : Exports your currently equipped gear, inventory, or all the items in your current Lua files' sets into GearSwap .lua or spellcast .xml format. Takes options "inventory", "sets", and "xml." Defaults to currently equipped gear and lua otherwise. Also exports appropriate advanced set tables with augments for currently equipped gear and inventory. +* gs export : Exports your currently equipped gear, inventory, or all the items in your current Lua files' sets into GearSwap .lua or spellcast .xml format. Takes options "inventory", "all", "wearable", "sets", and "xml." Defaults to currently equipped gear and lua otherwise. Also exports appropriate advanced set tables with augments for currently equipped gear and inventory. * gs enable : Enables equip commands targeting a specified slot. "All" will allow all equip commands. Providing no slot argument will enable user GearSwap file execution, if it was disabled. * gs disable : Disables equip commands targeting a given slot. "All" will prevent all equip commands. Providing no second argument will disable user GearSwap file execution, although registered events will still run. * gs validate : This command checks to see whether the equipment in the sets table also exists in your inventory (default), or (by passing "inv") whether the equipment in your inventory exists in your sets table. is an optional list of words that restricts the output to only those items that contain text from one of the filter's words. @@ -37,4 +37,4 @@ Settings Files: There is no settings file for GearSwap. Additional Assistance: -The Windower/addons/GearSwap/beta_examples_and_information folder has a file in it named Variables.xlsx that gives more specific information. If that is insufficient, you can go to BlueGartr's FFXI section or FFXIAH and ask for more assistance. \ No newline at end of file +The Windower/addons/GearSwap/beta_examples_and_information folder has a file in it named Variables.xlsx that gives more specific information. If that is insufficient, you can go to BlueGartr's FFXI section or FFXIAH and ask for more assistance. diff --git a/addons/GearSwap/export.lua b/addons/GearSwap/export.lua index 4ad8b96e51..454bab4c77 100644 --- a/addons/GearSwap/export.lua +++ b/addons/GearSwap/export.lua @@ -33,6 +33,8 @@ function export_set(options) targinv = true elseif v:lower() == 'all' then all_items = true + elseif v:lower() == 'wearable' then + wearable = true elseif S{'xml'}:contains(v:lower()) then xml = true elseif S{'sets','set','s'}:contains(v:lower()) then @@ -60,6 +62,8 @@ function export_set(options) local buildmsg = 'Exporting ' if all_items then buildmsg = buildmsg..'all your items' + elseif wearable then + buildmsg = buildmsg..'all your items in inventory and wardrobes' elseif targinv then buildmsg = buildmsg..'your current inventory' elseif all_sets then @@ -96,6 +100,10 @@ function export_set(options) for i = 0, #res.bags do item_list:extend(get_item_list(items[res.bags[i].english:gsub(' ', ''):lower()])) end + elseif wearable then + for _, v in pairs(equippable_item_bags) do + item_list:extend(get_item_list(items[v.english:gsub(' ', ''):lower()])) + end elseif targinv then item_list:extend(get_item_list(items.inventory)) elseif all_sets then From 9ada9381a4a9f41d77223241aca1e7e4d128bf22 Mon Sep 17 00:00:00 2001 From: Ivaar <7287342+Ivaar@users.noreply.github.com> Date: Fri, 10 Jan 2020 16:38:21 -0800 Subject: [PATCH 0336/1002] Slips.lua: January 2020 update --- addons/libs/slips.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 3e1911c36f..2b5f752a44 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -26,7 +26,7 @@ slips.items = { [slips.storages[11]] = L{15297, 15298, 15299, 15919, 15929, 15921, 18871, 16273, 18166, 18167, 18256, 13216, 13217, 13218, 15455, 15456, 181, 182, 183, 184, 129, 11499, 18502, 18855, 19274, 18763, 19110, 15008, 17764, 19101, 365, 366, 367, 15860, 272, 273, 274, 275, 276, 11853, 11956, 11854, 11957, 11811, 11812, 11861, 11862, 3676, 18879, 3647, 3648, 3649, 3677, 18880, 18863, 18864, 15178, 14519, 10382, 11965, 11967, 15752, 15179, 14520, 10383, 11966, 11968, 15753, 10875, 3619, 3620, 3621, 3650, 3652, 10430, 10251, 10593, 10431, 10252, 10594, 10432, 10253, 10595, 10433, 10254, 10596, 10429, 10250, 17031, 17032, 10807, 18881, 10256, 10330, 10257, 10331, 10258, 10332, 10259, 10333, 10260, 10334, 10261, 10335, 10262, 10336, 10263, 10337, 10264, 10338, 10265, 10339, 10266, 10340, 10267, 10341, 10268, 10342, 10269, 10343, 10270, 10344, 10271, 10345, 10446, 10447, 426, 10808, 3654, 265, 266, 267, 269, 270, 271, 18464, 18545, 18563, 18912, 18913, 10293, 10809, 10810, 10811, 10812, 27803, 28086, 27804, 28087, 27805, 28088, 27806, 28089, 27765, 27911, 27760, 27906, 27759, 28661, 286, 27757, 27758, 287, 27899, 28185, 28324, 27898, 28655, 27756, 28511, 21118, 27902, 100, 21117, 87, 20953, 21280, 28652, 28650, 27726, 28509, 28651, 27727, 28510, 27872, 21113, 27873, 21114, 20532, 20533, 27717, 27718}, -- 192 [slips.storages[12]] = L{2033, 2034, 2035, 2036, 2037, 2038, 2039, 2040, 2041, 2042, 2043, 2044, 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079, 2080, 2081, 2082, 2083, 2084, 2085, 2086, 2087, 2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095, 2096, 2097, 2098, 2099, 2100, 2101, 2102, 2103, 2104, 2105, 2106, 2107, 2662, 2663, 2664, 2665, 2666, 2667, 2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676, 2718, 2719, 2720, 2721, 2722, 2723, 2724, 2725, 2726, 2727}, -- 100 [slips.storages[13]] = L{10650, 10670, 10690, 10710, 10730, 10651, 10671, 10691, 10711, 10731, 10652, 10672, 10692, 10712, 10732, 10653, 10673, 10693, 10713, 10733, 10654, 10674, 10694, 10714, 10734, 10655, 10675, 10695, 10715, 10735, 10656, 10676, 10696, 10716, 10736, 10657, 10677, 10697, 10717, 10737, 10658, 10678, 10698, 10718, 10738, 10659, 10679, 10699, 10719, 10739, 10660, 10680, 10700, 10720, 10740, 10661, 10681, 10701, 10721, 10741, 10662, 10682, 10702, 10722, 10742, 10663, 10683, 10703, 10723, 10743, 10664, 10684, 10704, 10724, 10744, 10665, 10685, 10705, 10725, 10745, 10666, 10686, 10706, 10726, 10746, 10667, 10687, 10707, 10727, 10747, 10668, 10688, 10708, 10728, 10748, 10669, 10689, 10709, 10729, 10749}, -- 100 - [slips.storages[14]] = L{10901, 10474, 10523, 10554, 10620, 10906, 10479, 10528, 10559, 10625, 10911, 10484, 10533, 10564, 10630, 19799, 18916, 10442, 10280, 16084, 27788, 27928, 28071, 28208, 27649, 27789, 27929, 28072, 28209, 27650, 27790, 27930, 28073, 28210, 27651, 27791, 27931, 28074, 28211, 27652, 27792, 27932, 28075, 28212, 27653, 27793, 27933, 28076, 28213, 27654, 27794, 27934, 28077, 28214, 27655, 27795, 27935, 28078, 28215, 27656, 27796, 27936, 28079, 28216, 27657, 27797, 27937, 28080, 28217, 27658, 27798, 27938, 28081, 28218, 27659, 27799, 27939, 28082, 28219, 27660, 27800, 27940, 28083, 28220, 27661, 27801, 27941, 28084, 28221, 27662, 27802, 27942, 28085, 28222}, -- 94 + [slips.storages[14]] = L{10901, 10474, 10523, 10554, 10620, 10906, 10479, 10528, 10559, 10625, 10911, 10484, 10533, 10564, 10630, 19799, 18916, 10442, 10280, 16084, 27788, 27928, 28071, 28208, 27649, 27789, 27929, 28072, 28209, 27650, 27790, 27930, 28073, 28210, 27651, 27791, 27931, 28074, 28211, 27652, 27792, 27932, 28075, 28212, 27653, 27793, 27933, 28076, 28213, 27654, 27794, 27934, 28077, 28214, 27655, 27795, 27935, 28078, 28215, 27656, 27796, 27936, 28079, 28216, 27657, 27797, 27937, 28080, 28217, 27658, 27798, 27938, 28081, 28218, 27659, 27799, 27939, 28082, 28219, 27660, 27800, 27940, 28083, 28220, 27661, 27801, 27941, 28084, 28221, 27662, 27802, 27942, 28085, 28222, 21510, 21566, 21622, 21665, 21712, 21769, 21822, 21864, 21912, 21976, 22006, 22088, 22133, 22144, 22219, 26413, 23738, 23741, 23744, 23747, 23750, 23739, 23742, 23745, 23748, 23751, 23740, 23743, 23746, 23749, 23752}, -- 125 [slips.storages[15]] = L{27663, 27807, 27943, 28090, 28223, 27664, 27808, 27944, 28091, 28224, 27665, 27809, 27945, 28092, 28225, 27666, 27810, 27946, 28093, 28226, 27667, 27811, 27947, 28094, 28227, 27668, 27812, 27948, 28095, 28228, 27669, 27813, 27949, 28096, 28229, 27670, 27814, 27950, 28097, 28230, 27671, 27815, 27951, 28098, 28231, 27672, 27816, 27952, 28099, 28232, 27673, 27817, 27953, 28100, 28233, 27674, 27818, 27954, 28101, 28234, 27675, 27819, 27955, 28102, 28235, 27676, 27820, 27956, 28103, 28236, 27677, 27821, 27957, 28104, 28237, 27678, 27822, 27958, 28105, 28238, 27679, 27823, 27959, 28106, 28239, 27680, 27824, 27960, 28107, 28240, 27681, 27825, 27961, 28108, 28241, 27682, 27826, 27962, 28109, 28242, 27683, 27827, 27963, 28110, 28243}, -- 105 [slips.storages[16]] = L{27684, 27828, 27964, 28111, 28244, 27685, 27829, 27965, 28112, 28245, 27686, 27830, 27966, 28113, 28246, 27687, 27831, 27967, 28114, 28247, 27688, 27832, 27968, 28115, 28248, 27689, 27833, 27969, 28116, 28249, 27690, 27834, 27970, 28117, 28250, 27691, 27835, 27971, 28118, 28251, 27692, 27836, 27972, 28119, 28252, 27693, 27837, 27973, 28120, 28253, 27694, 27838, 27974, 28121, 28254, 27695, 27839, 27975, 28122, 28255, 27696, 27840, 27976, 28123, 28256, 27697, 27841, 27977, 28124, 28257, 27698, 27842, 27978, 28125, 28258, 27699, 27843, 27979, 28126, 28259, 27700, 27844, 27980, 28127, 28260, 27701, 27845, 27981, 28128, 28261, 27702, 27846, 27982, 28129, 28262, 27703, 27847, 27983, 28130, 28263, 27704, 27848, 27984, 28131, 28264, 27705, 27849, 27985, 28132, 28265, 27706, 27850, 27986, 28133, 28266}, -- 115 [slips.storages[17]] = L{26624, 26800, 26976, 27152, 27328, 26626, 26802, 26978, 27154, 27330, 26628, 26804, 26980, 27156, 27332, 26630, 26806, 26982, 27158, 27334, 26632, 26808, 26984, 27160, 27336, 26634, 26810, 26986, 27162, 27338, 26636, 26812, 26988, 27164, 27340, 26638, 26814, 26990, 27166, 27342, 26640, 26816, 26992, 27168, 27344, 26642, 26818, 26994, 27170, 27346, 26644, 26820, 26996, 27172, 27348, 26646, 26822, 26998, 27174, 27350, 26648, 26824, 27000, 27176, 27352, 26650, 26826, 27002, 27178, 27354, 26652, 26828, 27004, 27180, 27356, 26654, 26830, 27006, 27182, 27358, 26656, 26832, 27008, 27184, 27360, 26658, 26834, 27010, 27186, 27362, 26660, 26836, 27012, 27188, 27364, 26662, 26838, 27014, 27190, 27366, 26664, 26840, 27016, 27192, 27368, 26666, 26842, 27018, 27194, 27370}, -- 110 @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757}, -- 191 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453,}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454,}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739}, -- 105 + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740}, -- 112 [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070}, --168 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330,}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665,}, --115 From f4068c4eea47e9be5139d78d29186ba157de0e38 Mon Sep 17 00:00:00 2001 From: Dean James Date: Mon, 13 Jan 2020 22:53:30 +0000 Subject: [PATCH 0337/1002] Added EmpyPopTracker addon. --- addons/EmpyPopTracker/EmpyPopTracker.lua | 339 +++++++++++++++++++++ addons/EmpyPopTracker/README.md | 53 ++++ addons/EmpyPopTracker/nms/README.md | 62 ++++ addons/EmpyPopTracker/nms/alfard.lua | 59 ++++ addons/EmpyPopTracker/nms/apademak.lua | 58 ++++ addons/EmpyPopTracker/nms/azdaja.lua | 37 +++ addons/EmpyPopTracker/nms/briareus.lua | 66 ++++ addons/EmpyPopTracker/nms/bukhis.lua | 59 ++++ addons/EmpyPopTracker/nms/carabosse.lua | 55 ++++ addons/EmpyPopTracker/nms/chloris.lua | 114 +++++++ addons/EmpyPopTracker/nms/cirein-croin.lua | 48 +++ addons/EmpyPopTracker/nms/dragua.lua | 37 +++ addons/EmpyPopTracker/nms/glavoid.lua | 83 +++++ addons/EmpyPopTracker/nms/index.lua | 54 ++++ addons/EmpyPopTracker/nms/isgebind.lua | 37 +++ addons/EmpyPopTracker/nms/itzpapalotl.lua | 59 ++++ addons/EmpyPopTracker/nms/kukulkan.lua | 66 ++++ addons/EmpyPopTracker/nms/orthrus.lua | 58 ++++ addons/EmpyPopTracker/nms/sedna.lua | 48 +++ addons/EmpyPopTracker/nms/sobek.lua | 59 ++++ addons/EmpyPopTracker/nms/ulhuadshi.lua | 48 +++ addons/EmpyPopTracker/readme/demo-full.png | Bin 0 -> 26460 bytes addons/EmpyPopTracker/readme/demo.png | Bin 0 -> 22426 bytes 23 files changed, 1499 insertions(+) create mode 100644 addons/EmpyPopTracker/EmpyPopTracker.lua create mode 100644 addons/EmpyPopTracker/README.md create mode 100644 addons/EmpyPopTracker/nms/README.md create mode 100644 addons/EmpyPopTracker/nms/alfard.lua create mode 100644 addons/EmpyPopTracker/nms/apademak.lua create mode 100644 addons/EmpyPopTracker/nms/azdaja.lua create mode 100644 addons/EmpyPopTracker/nms/briareus.lua create mode 100644 addons/EmpyPopTracker/nms/bukhis.lua create mode 100644 addons/EmpyPopTracker/nms/carabosse.lua create mode 100644 addons/EmpyPopTracker/nms/chloris.lua create mode 100644 addons/EmpyPopTracker/nms/cirein-croin.lua create mode 100644 addons/EmpyPopTracker/nms/dragua.lua create mode 100644 addons/EmpyPopTracker/nms/glavoid.lua create mode 100644 addons/EmpyPopTracker/nms/index.lua create mode 100644 addons/EmpyPopTracker/nms/isgebind.lua create mode 100644 addons/EmpyPopTracker/nms/itzpapalotl.lua create mode 100644 addons/EmpyPopTracker/nms/kukulkan.lua create mode 100644 addons/EmpyPopTracker/nms/orthrus.lua create mode 100644 addons/EmpyPopTracker/nms/sedna.lua create mode 100644 addons/EmpyPopTracker/nms/sobek.lua create mode 100644 addons/EmpyPopTracker/nms/ulhuadshi.lua create mode 100644 addons/EmpyPopTracker/readme/demo-full.png create mode 100644 addons/EmpyPopTracker/readme/demo.png diff --git a/addons/EmpyPopTracker/EmpyPopTracker.lua b/addons/EmpyPopTracker/EmpyPopTracker.lua new file mode 100644 index 0000000000..6fd546248a --- /dev/null +++ b/addons/EmpyPopTracker/EmpyPopTracker.lua @@ -0,0 +1,339 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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.name = "Empy Pop Tracker" +_addon.author = "Dean James (Xurion of Bismarck)" +_addon.commands = { "ept", "empypoptracker" } +_addon.version = "2.0.0" + +config = require("config") +res = require("resources") +nm_data = require("nms/index") + +active = false + +local EmpyPopTracker = {} + +local defaults = {} +defaults.text = {} +defaults.text.pos = {} +defaults.text.pos.x = 0 +defaults.text.pos.y = 0 +defaults.text.bg = {} +defaults.text.bg.alpha = 150 +defaults.text.bg.blue = 0 +defaults.text.bg.green = 0 +defaults.text.bg.red = 0 +defaults.text.bg.visible = true +defaults.text.padding = 8 +defaults.text.text = {} +defaults.text.text.font = "Consolas" +defaults.text.text.size = 10 +defaults.tracking = "briareus" +defaults.visible = true + +EmpyPopTracker.settings = config.load(defaults) +EmpyPopTracker.text = require("texts").new(EmpyPopTracker.settings.text, EmpyPopTracker.settings) + +colors = {} +colors.success = "\\cs(100,255,100)" +colors.danger = "\\cs(255,50,50)" +colors.warning = "\\cs(255,170,0)" +colors.close = "\\cr" + +function owns_item(id, items) + local owned = false + + -- Loop maximum 80 times over all slots. 80 indexes are returned for each bag regardless of max capacity. + for i = 1, 80, 1 do + if items.safe[i].id == id or + items.safe2[i].id == id or + items.locker[i].id == id or + items.sack[i].id == id or + items.satchel[i].id == id or + items.inventory[i].id == id or + items.storage[i].id == id then + owned = true + break + end + end + + return owned +end + +function owns_key_item(id, items) + local owned = false + + for _, item_id in pairs(items) do + if item_id == id then + owned = true + break + end + end + + return owned +end + +function item_treasure_pool_count(id, treasure) + local count = 0 + + for _, item in pairs(treasure) do + if item.item_id == id then + count = count + 1 + end + end + + return count +end + +function ucwords(str) + return string.gsub(str, "(%a)([%w_']*)", function(first, rest) + return first:upper() .. rest:lower() + end) +end + +function get_indent(depth) + return string.rep(" ", depth) +end + +function generate_text(data, key_items, items, depth) + local text = depth == 1 and data.name or "" + for _, pop in pairs(data.pops) do + local resource + local item_scope + local owns_pop + local in_pool_count = 0 + local item_identifier = '' + + if pop.type == 'key item' then + resource = res.key_items[pop.id] + owns_pop = owns_key_item(pop.id, key_items) + item_identifier = 'Ж ' + else + resource = res.items[pop.id] + owns_pop = owns_item(pop.id, items) + in_pool_count = item_treasure_pool_count(pop.id, items.treasure) + end + + local pop_name = 'Unknown pop' + if resource then + pop_name = ucwords(resource.en) + end + + --separator line for each top-level mob + if depth == 1 then + text = text .. "\n" + end + + local item_colour + if owns_pop then + item_colour = colors.success + else + item_colour = colors.danger + end + + local pool_notification = '' + if in_pool_count > 0 then + pool_notification = colors.warning .. ' [' .. in_pool_count .. ']' .. colors.close + end + text = text .. "\n" .. get_indent(depth) .. pop.dropped_from.name .. "\n" .. get_indent(depth) .. ' >> ' .. item_colour .. item_identifier .. pop_name .. colors.close .. pool_notification + if pop.dropped_from.pops then + text = text .. generate_text(pop.dropped_from, key_items, items, depth + 1) + end + end + + return text +end + +EmpyPopTracker.add_to_chat = function(message) + if type(message) ~= 'string' then + error('add_to_chat requires the message arg to be a string') + end + + windower.add_to_chat(8, message) +end + +EmpyPopTracker.generate_info = function(nm, key_items, items) + local nm_type = type(nm) + if nm_type ~= 'table' then + error('generate_info requires the nm arg to be a table, but got ' .. nm_type .. ' instead') + end + + local info = { + has_all_kis = true, + text = "" + } + + if nm.pops then + for _, key_item_data in pairs(nm.pops) do + local has_pop_ki = owns_key_item(key_item_data.id, key_items) + + if not has_pop_ki then + info.has_all_kis = false + end + end + end + + info.text = generate_text(nm, key_items, items, 1) + + return info +end + +function find_nms(query) + local matching_nms = {} + local lower_query = query:lower() + for _, nm in pairs(nm_data) do + local result = string.match(nm.name:lower(), '(.*' .. lower_query .. '.*)') + if result then + table.insert(matching_nms, result) + end + end + return matching_nms +end + +windower.register_event("addon command", function(command, ...) + if commands[command] then + commands[command](...) + else + commands.help() + end +end) + +commands = {} + +commands.track = function(...) + local args = {...} + local nm_name = args[1] + local matching_nm_names = find_nms(nm_name) + + if #matching_nm_names == 0 then + EmpyPopTracker.add_to_chat('Unable to find a NM using: "' .. nm_name .. '"') + elseif #matching_nm_names > 1 then + EmpyPopTracker.add_to_chat('"' .. nm_name .. '" matches ' .. #matching_nm_names .. ' NMs. Please be more explicit:') + for key, matching_file_name in pairs(matching_nm_names) do + EmpyPopTracker.add_to_chat(' Match ' .. key .. ': ' .. ucwords(matching_file_name)) + end + else + active = true + EmpyPopTracker.add_to_chat("Now tracking: " .. ucwords(matching_nm_names[1])) + EmpyPopTracker.settings.tracking = matching_nm_names[1] + EmpyPopTracker.update() + commands.show() + end +end +commands.t = commands.track + +commands.hide = function() + active = false + EmpyPopTracker.text:visible(false) + EmpyPopTracker.settings.visible = false + EmpyPopTracker.settings:save() +end + +commands.show = function() + active = true + EmpyPopTracker.text:visible(true) + EmpyPopTracker.settings.visible = true + EmpyPopTracker.settings:save() + EmpyPopTracker.update() +end + +commands.help = function() + EmpyPopTracker.add_to_chat("---Empy Pop Tracker---") + EmpyPopTracker.add_to_chat("Available commands:") + EmpyPopTracker.add_to_chat("//ept t|track briareus - tracks Briareus pops (partial names such as apadem work too!)") + EmpyPopTracker.add_to_chat("//ept hide - hides the UI") + EmpyPopTracker.add_to_chat("//ept show - shows the UI") + EmpyPopTracker.add_to_chat("//ept list - lists all trackable NMs") + EmpyPopTracker.add_to_chat("//ept help - displays this help") +end + +commands.list = function() + EmpyPopTracker.add_to_chat("---Empy Pop Tracker---") + EmpyPopTracker.add_to_chat("Trackable NMs:") + for _, nm in pairs(nm_data) do + EmpyPopTracker.add_to_chat(ucwords(nm.name)) + end +end + +commands.bg = function() + local tracking_nm = nm_data[EmpyPopTracker.settings.tracking] + windower.open_url(tracking_nm.bg_url) +end + +EmpyPopTracker.update = function() + local key_items = windower.ffxi.get_key_items() + local items = windower.ffxi.get_items() + local tracked_nm_data = nm_data[EmpyPopTracker.settings.tracking] + local generated_info = EmpyPopTracker.generate_info(tracked_nm_data, key_items, items) + EmpyPopTracker.text:text(generated_info.text) + if generated_info.has_all_kis then + EmpyPopTracker.text:bg_color(0, 75, 0) + else + EmpyPopTracker.text:bg_color(0, 0, 0) + end + if EmpyPopTracker.settings.visible then + EmpyPopTracker.text:visible(true) + end +end + +windower.register_event('load', function() + if windower.ffxi.get_info().logged_in and EmpyPopTracker.settings.visible then + active = true + EmpyPopTracker.update() + end +end) + +windower.register_event('add item', 'remove item', function() + if active then + EmpyPopTracker.update() + end +end) + +windower.register_event('incoming chunk', function(id) + --0x055: KI update + --0x0D2: Treasure pool addition + --0x0D3: Treasure pool lot/drop + if active and id == 0x055 or id == 0x0D2 or id == 0x0D3 then + EmpyPopTracker.update() + end +end) + +windower.register_event('login', function() + if EmpyPopTracker.settings.visible then + EmpyPopTracker.text:visible(true) + active = true + end +end) + +windower.register_event('logout', function() + EmpyPopTracker.text:visible(false) + active = false +end) + +return EmpyPopTracker diff --git a/addons/EmpyPopTracker/README.md b/addons/EmpyPopTracker/README.md new file mode 100644 index 0000000000..3631de1ecd --- /dev/null +++ b/addons/EmpyPopTracker/README.md @@ -0,0 +1,53 @@ +# FFXI Empy Pop Tracker + +An FFXI Windower 4 addon that tracks items and key items for popping Empyrean NMs in Abyssea, such as Briareus, Apademak and Sobek. + +![Example of Cirein-croin tracking](readme/demo.png) ![All KIs obtained](readme/demo-full.png) + +Key items are identified by the Zhe (Ж) character. Treasure pool counts for pop items are listed in amber after the item in the format of [3] (assuming 3 of that item in the pool). + +## Load + +`//lua load empypoptracker` + +## Track an NM + +`//ept track glavoid` tracks Glavoid pop items/key items. + +You can also track an NM by typing part of the name, because fuck having to remember how to spell Itzpapalotl: + +`//ept track itz` + +For a full list of trackable NMs, see the nms directory or use the `list` command (see below). + +## Other Commands + +### List Trackable NMs + +`//ept list` + +### Open BG Wiki for NM + +`//ept bg` + +### Hide UI + +`//ept hide` + +### Show UI + +`//ept show` + +### Display Help + +`//ept help` + +## Where is Fistule? + +Fistule is a unique NM when compared to the others. It does not require KIs that can be tracked, so it isn't included with the addon. + +## Contributing + +Notice something not quite right? [Raise an issue](https://github.com/xurion/ffxi-empy-pop-tracker/issues). + +[Pull requests](https://github.com/xurion/ffxi-empy-pop-tracker/pulls) welcome! diff --git a/addons/EmpyPopTracker/nms/README.md b/addons/EmpyPopTracker/nms/README.md new file mode 100644 index 0000000000..bad2e262b4 --- /dev/null +++ b/addons/EmpyPopTracker/nms/README.md @@ -0,0 +1,62 @@ +# NM data + +The data structure for each trackable NM uses a series of nested NM entities. A standard NM entity contains the following data: + +| Key | Type | Required? | Description | +| ------------------- | --------- | --------- | --------------------------------- | +| name | String | Required | Name of the NM | +| bg_url | String | Required | URL of the bgwiki page for the NM | +| pops | Table | Optional | The pop information for the NM | +| pops{}.id | Number | Required | The ID of the item/key item | +| pops{}.type | String | Required | Either "key item" or "item" | +| pops{}.dropped_from | NM Entity | Required | A nested set of NM information | + +A simple example of the above would be: + +```lua +{ + name = "Azdaja", + pops = { { + id = 1531, --Vacant Bugard Eye + type = "key item", + dropped_from = { name = "Deelgeed, Timed (F-9/F-10)" } + } } +} +``` + +A larger example with multiple nested entites: + +```lua +{ + name = "Bukhis", + pops = { { + id = 1508, --Ingrown Taurus Nail + type = "key item", + dropped_from = { + name = "Khalkotaur, Forced (F-4)", + pops = { { + id = 3098, --Gnarled Taurus Horn + type = "item", + dropped_from = { name = "Aestutaur (G-9/G-10)" } + } } + }, { + id = 1509, --Ossified Gargouille Hand + type = "key item", + dropped_from = { + name = "Quasimodo, Forced (F-4)", + pops = { { + id = 3099, --Gargouille Stone + type = "item", + dropped_from = { name = "Gruesome Gargouille (F-10/G-10)" } + } } + } + }, { + id = 1510, --Imbrued Vampyr Fang + type = "key item", + dropped_from = { name = "Lord Varney, Timed (G-10/H-10)" } + } } + } +} +``` + +The main addon file requires the index.lua file which in turn is responsible for requiring and returning data for each nm. diff --git a/addons/EmpyPopTracker/nms/alfard.lua b/addons/EmpyPopTracker/nms/alfard.lua new file mode 100644 index 0000000000..88dedb7a26 --- /dev/null +++ b/addons/EmpyPopTracker/nms/alfard.lua @@ -0,0 +1,59 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = "Alfard", + bg_url = 'https://www.bg-wiki.com/bg/Alfard', + pops = { { + id = 1530, --Venomous hydra fang + type = "key item", + dropped_from = { + name = "Ningishzida, Forced (I-7/I-8)", + pops = { { + id = 3262, --Jaculus Wing + type = "item", + dropped_from = { name = "Jaculus, Timed (I-8)" } + }, { + id = 3261, --Minaruja Skull + type = "item", + dropped_from = { + name = "Minaruja, Forced (I-10)", + pops = { { + id = 3267, --Pursuer's Wing + type = "item", + dropped_from = { name = "Faunus Wyvern (I-9)" } + } } + } + }, { + id = 3268, --High-Quality Wivre Hide + type = "item", + dropped_from = { name = "Glade Wivre (I-8)" } + } } + } + } } +} diff --git a/addons/EmpyPopTracker/nms/apademak.lua b/addons/EmpyPopTracker/nms/apademak.lua new file mode 100644 index 0000000000..f3c37a21e8 --- /dev/null +++ b/addons/EmpyPopTracker/nms/apademak.lua @@ -0,0 +1,58 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = "Apademak", + bg_url = 'https://www.bg-wiki.com/bg/Apademak', + pops = { { + id = 1525, --Torn Khimaira Wing + type = "key item", + dropped_from = { + name = "Dhorme Khimaira, Forced (F-7)", + pops = { { + id = 3246, --Snow God Core + type = "item", + dropped_from = { + name = "Upas-Kamuy, Forced (G-5)", + pops = { { + id = 3252, --Gelid Arm + dropped_from = { name = "Snowflake (G-5)" } + } } + } + }, { + id = 3247, --Sisyphus Fragment + type = "item", + dropped_from = { name = "Sisyphus, Timed (F-6/G-6)" } + }, { + id = 3253, --High-quality marid hide + type = "item", + dropped_from = { name = "Olyphant (F-6)" } + } } + } + } } +} diff --git a/addons/EmpyPopTracker/nms/azdaja.lua b/addons/EmpyPopTracker/nms/azdaja.lua new file mode 100644 index 0000000000..28716728a0 --- /dev/null +++ b/addons/EmpyPopTracker/nms/azdaja.lua @@ -0,0 +1,37 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = "Azdaja", + bg_url = 'https://www.bg-wiki.com/bg/Azdaja', + pops = { { + id = 1531, --Vacant Bugard Eye + type = "key item", + dropped_from = { name = "Deelgeed, Timed (F-9/F-10)" } + } } +} diff --git a/addons/EmpyPopTracker/nms/briareus.lua b/addons/EmpyPopTracker/nms/briareus.lua new file mode 100644 index 0000000000..141f27b64c --- /dev/null +++ b/addons/EmpyPopTracker/nms/briareus.lua @@ -0,0 +1,66 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = "Briareus", + bg_url = 'https://www.bg-wiki.com/bg/Briareus', + pops = { { + id = 1482, --Dented Gigas Shield + type = "key item", + dropped_from = { + name = "Adamastor, Forced (C-4)", + pops = { { + id = 2894, --Trophy Shield + type = "item", + dropped_from = { name = "Bathyal Gigas (C-5/D-5)" } + } } + } + }, { + id = 1484, --Severed Gigas Collar + type = "key item", + dropped_from = { + name = "Grandgousier, Forced (F-10)", + pops = { { + id = 2896, --Massive Armband + type = "item", + dropped_from = { name = "Demersal Gigas (E-9/F-9)" } + } } + } + }, { + id = 1483, --Warped Gigas Armband + type = "key item", + dropped_from = { + name = "Pantagruel, Forced (F-7)", + pops = { { + id = 2895, --Oversized Sock + type = "item", + dropped_from = { name = "Hadal Gigas (F-6/F-7)" } + } } + } + } } +} diff --git a/addons/EmpyPopTracker/nms/bukhis.lua b/addons/EmpyPopTracker/nms/bukhis.lua new file mode 100644 index 0000000000..4197cc0eb5 --- /dev/null +++ b/addons/EmpyPopTracker/nms/bukhis.lua @@ -0,0 +1,59 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = "Bukhis", + bg_url = 'https://www.bg-wiki.com/bg/Bukhis', + pops = { { + id = 1508, --Ingrown Taurus Nail + type = "key item", + dropped_from = { + name = "Khalkotaur, Forced (F-4)", + pops = { { + id = 3098, --Gnarled Taurus Horn + type = "item", + dropped_from = { name = "Aestutaur (G-9/G-10)" } + } } + } + }, { + id = 1509, --Ossified Gargouille Hand + type = "key item", + dropped_from = { + name = "Quasimodo, Forced (F-4)", + pops = { { + id = 3099, --Gargouille Stone + type = "item", + dropped_from = { name = "Gruesome Gargouille (F-10/G-10)" } + } } + } + }, { + id = 1510, --Imbrued Vampyr Fang + type = "key item", + dropped_from = { name = "Lord Varney, Timed (G-10/H-10)" } + } } +} diff --git a/addons/EmpyPopTracker/nms/carabosse.lua b/addons/EmpyPopTracker/nms/carabosse.lua new file mode 100644 index 0000000000..7f4c59c86b --- /dev/null +++ b/addons/EmpyPopTracker/nms/carabosse.lua @@ -0,0 +1,55 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = "Carabosse", + bg_url = 'https://www.bg-wiki.com/bg/Carabosse', + pops = { { + id = 1485, --Pellucid Fly Eye + type = "key item", + dropped_from = { + name = "La Theine Liege, Forced (I-7)", + pops = { { + id = 2897, --Transparent Insect Wing + type = "item", + dropped_from = { name = "Plateau Glider (H-7)" } + } } + } + }, { + id = 1486, --Shimmering Pixie Pinion + type = "key item", + dropped_from = { + name = "Baba Yaga, Forced (H-7)", + pops = { { + id = 2898, --Piceous Scale + type = "item", + dropped_from = { name = "Farfadet (H-7)" } + } } + } + } } +} diff --git a/addons/EmpyPopTracker/nms/chloris.lua b/addons/EmpyPopTracker/nms/chloris.lua new file mode 100644 index 0000000000..7695cd0e06 --- /dev/null +++ b/addons/EmpyPopTracker/nms/chloris.lua @@ -0,0 +1,114 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = "Chloris", + bg_url = 'https://www.bg-wiki.com/bg/Chloris', + pops = { { + id = 1470, --Gory Scorpion Claw + type = "key item", + dropped_from = { + name = "Hedetet, Forced (F-7)", + pops = { { + id = 2921, --Venomous Scorpion Stinger + type = "item", + dropped_from = { name = "Canyon Scorpion (F-7)" } + }, { + id = 2948, --Acidic Humus + type = "item", + dropped_from = { + name = "Gancanagh, Forced (H-8)", + pops = { { + id = 2920, --Alkaline Humus + type = "item", + dropped_from = { name = "Pachypodium (H-8)" } + } } + } + } } + } + }, { + id = 1469, --Torn Bat Wing + type = "key item", + dropped_from = { + name = "Treble Noctules, Forced (I-9)", + pops = { { + id = 2919, --Bloody Fang + type = "item", + dropped_from = { name = "Blood Bat (I-9)" } + }, { + id = 2947, --Exorcised Skull + type = "item", + dropped_from = { + name = "Cannered Noz, Forced (F-6)", + pops = { { + id = 2918, --Baleful Skull + type = "item", + dropped_from = { name = "Caoineag (F-6)" } + } } + } + } } + } + }, { + id = 1468, --Veinous Hecteyes Eyelid + type = "key item", + dropped_from = { + name = "Ophanim, Forced (G-9)", + pops = { { + id = 2946, --Tarnished Pincer + type = "item", + dropped_from = { + name = "Vetehinen, Forced (H-10)", + pops = { { + id = 2916, --High-quality Limule Pincer + type = "item", + dropped_from = { name = "Gulch Limule (H-10)" } + }, { + id = 2917, --Bloodshot Hecteye + type = "item", + dropped_from = { name = "Beholder (G-9)" } + }, { + id = 2945, --Shriveled Wing + type = "item", + dropped_from = { + name = "Halimede, Forced (G-12)", + pops = { { + id = 2915, --High-quality Clionid Wing + type = "item", + dropped_from = { name = "Gully Clionid (G-12)" } + } } + } + } } + } + } } + } + }, { + id = 1471, --Mossy Adamantoise Shell + type = "key item", + dropped_from = { name = "Chukwa, Timed (F-5)" } + } } +} diff --git a/addons/EmpyPopTracker/nms/cirein-croin.lua b/addons/EmpyPopTracker/nms/cirein-croin.lua new file mode 100644 index 0000000000..78354bcd66 --- /dev/null +++ b/addons/EmpyPopTracker/nms/cirein-croin.lua @@ -0,0 +1,48 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = "Cirein-Croin", + bg_url = 'https://www.bg-wiki.com/bg/Cirein-croin', + pops = { { + id = 1504, --Glistening Orobon Liver + type = "key item", + dropped_from = { + name = "Cep-Kamuy, Forced (F-4)", + pops = { { + id = 3089, --Orobon Cheekmeat + type = "item", + dropped_from = { name = "Ancient Orobon (F-5)" } + } } + } + }, { + id = 1505, --Doffed Poroggo Hat + type = "key item", + dropped_from = { name = "Heqet, Timed (I-6)" } + } } +} diff --git a/addons/EmpyPopTracker/nms/dragua.lua b/addons/EmpyPopTracker/nms/dragua.lua new file mode 100644 index 0000000000..c584499caa --- /dev/null +++ b/addons/EmpyPopTracker/nms/dragua.lua @@ -0,0 +1,37 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = "Dragua", + bg_url = 'https://www.bg-wiki.com/bg/Dragua', + pops = { { + id = 1521, --Bloodied Dragon Ear + type = "key item", + dropped_from = { name = "Hazhdiha, Timed (H-10)" } + } } +} diff --git a/addons/EmpyPopTracker/nms/glavoid.lua b/addons/EmpyPopTracker/nms/glavoid.lua new file mode 100644 index 0000000000..067d2a3454 --- /dev/null +++ b/addons/EmpyPopTracker/nms/glavoid.lua @@ -0,0 +1,83 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = "Glavoid", + bg_url = 'https://www.bg-wiki.com/bg/Glavoid', + pops = { { + id = 1473, --Sodden Sandworm Husk + type = "key item", + dropped_from = { name = "Minhocao, Timed (I-6)" } + }, { + id = 1475, --Sticky Gnat Wing + type = "key item", + dropped_from = { name = "Adze, Timed (G-5)" } + }, { + id = 1472, --Fat-lined Cockatrice Skin + type = "key item", + dropped_from = { + name = "Alectryon (H-8)", + pops = { { + id = 2923, --Cockatrice Tailmeat + type = "item", + dropped_from = { name = "Cluckatrice (H-8)" } + }, { + id = 2949, --Quivering Eft Egg + type = "item", + dropped_from = { + name = "Abas, Forced (K-10)", + pops = { { + id = 2922, --Eft Egg + dropped_from = { name = "Canyon Eft (J-10/J-11)" } + } } + } + } } + } + }, { + id = 1474, --Luxuriant manticore mane + type = "key item", + dropped_from = { + name = "Muscaliet, Forced (J-6)", + pops = { { + id = 2925, --Resilient Mane + type = "item", + dropped_from = { name = "Hieracosphinx (J-6)" } + }, { + id = 2950, --Smooth Whisker + type = "item", + dropped_from = { + name = "Tefenet, Forced (G-6)", + pops = { { + id = 2924, --Shocking Whisker + dropped_from = { name = "Jaguarundi (G-6)" } + } } + } + } } + } + } } +} diff --git a/addons/EmpyPopTracker/nms/index.lua b/addons/EmpyPopTracker/nms/index.lua new file mode 100644 index 0000000000..9091a466a9 --- /dev/null +++ b/addons/EmpyPopTracker/nms/index.lua @@ -0,0 +1,54 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +local nms = { + 'alfard', + 'apademak', + 'azdaja', + 'briareus', + 'bukhis', + 'carabosse', + 'chloris', + 'cirein-croin', + 'dragua', + 'glavoid', + 'isgebind', + 'itzpapalotl', + 'kukulkan', + 'orthrus', + 'sedna', + 'sobek', + 'ulhuadshi' +} + +nm_data = {} +for _, nm in pairs(nms) do + nm_data[nm] = require('nms/' .. nm) +end + +return nm_data diff --git a/addons/EmpyPopTracker/nms/isgebind.lua b/addons/EmpyPopTracker/nms/isgebind.lua new file mode 100644 index 0000000000..3d5f5ef1e5 --- /dev/null +++ b/addons/EmpyPopTracker/nms/isgebind.lua @@ -0,0 +1,37 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = "Isgebind", + bg_url = 'https://www.bg-wiki.com/bg/Isgebind', + pops = { { + id = 1526, --Begrimed Dragon Hide + type = "key item", + dropped_from = { name = "Kur, Timed (I-5/J-5)" } + } } +} diff --git a/addons/EmpyPopTracker/nms/itzpapalotl.lua b/addons/EmpyPopTracker/nms/itzpapalotl.lua new file mode 100644 index 0000000000..5e44302d21 --- /dev/null +++ b/addons/EmpyPopTracker/nms/itzpapalotl.lua @@ -0,0 +1,59 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = "Itzpapalotl", + bg_url = 'https://www.bg-wiki.com/bg/Itzpapalotl', + pops = { { + id = 1488, --Venomous Wamoura Feeler + type = "key item", + dropped_from = { + name = "Granite Borer, Forced (K-10)", + pops = { { + id = 3072, --Withered Cocoon + type = "item", + dropped_from = { name = "Gullycampa (K-10)" } + } } + } + }, { + id = 1490, --Distended Chigoe Abdomen + type = "key item", + dropped_from = { name = "Tunga, Timed (K-10)" } + }, { + id = 1489, --Bulbous crawler cocoon + type = "key item", + dropped_from = { + name = "Blazing Eruca, Forced (J-10)", + pops = { { + id = 3073, --Eruca Egg + type = "item", + dropped_from = { name = "Ignis Eruca (J-10)" } + } } + } + } } +} diff --git a/addons/EmpyPopTracker/nms/kukulkan.lua b/addons/EmpyPopTracker/nms/kukulkan.lua new file mode 100644 index 0000000000..5b1ddcc0b7 --- /dev/null +++ b/addons/EmpyPopTracker/nms/kukulkan.lua @@ -0,0 +1,66 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = "Kukulkan", + bg_url = 'https://www.bg-wiki.com/bg/Kukulkan', + pops = { { + id = 1466, --Mucid Ahriman Eyeball + type = "key item", + dropped_from = { + name = "Arimaspi, Forced (K-6)", + pops = { { + id = 2913, --Clouded Lens + type = "item", + dropped_from = { name = "Deep Eye (K-6/K-7)" } + } } + } + }, { + id = 1464, --Tattered Hippogryph Wing + type = "key item", + dropped_from = { + name = "Alkonost, Forced (H-6)", + pops = { { + id = 2912, --Giant Bugard Tusk + type = "item", + dropped_from = { name = "Ypotryll (I-7)" } + } } + } + }, { + id = 1465, --Cracked Wivre Horn + type = "key item", + dropped_from = { + name = "Keratyrannos, Forced (G-6)", + pops = { { + id = 2910, --Armored Dragonhorn + type = "item", + dropped_from = { name = "Mesa Wivre (G-6)" } + } } + } + } } +} diff --git a/addons/EmpyPopTracker/nms/orthrus.lua b/addons/EmpyPopTracker/nms/orthrus.lua new file mode 100644 index 0000000000..ea7a0d8172 --- /dev/null +++ b/addons/EmpyPopTracker/nms/orthrus.lua @@ -0,0 +1,58 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = "Orthrus", + bg_url = 'https://www.bg-wiki.com/bg/Orthrus', + pops = { { + id = 1520, --Steaming cerberus tongue + type = "key item", + dropped_from = { + name = "Amarok, Forced (E-6)", + pops = { { + id = 3231, --Sharabha Hide + type = "item", + dropped_from = { + name = "Sharabha, Forced (G-5)", + pops = { { + id = 3237, + dropped_from = { name = "Dune Manticore (F-5/F-6)" } + } } + } + }, { + id = 3232, --Tiger King Hide + type = "item", + dropped_from = { name = "Ansherekh, Timed (F-8/G-8)" } + }, { + id = 3238, --H.Q. Dhalmel Hide + type = "item", + dropped_from = { name = "Camelopardalis (F-7/G-7)" } + } } + } + } } +} diff --git a/addons/EmpyPopTracker/nms/sedna.lua b/addons/EmpyPopTracker/nms/sedna.lua new file mode 100644 index 0000000000..de3f84d1cb --- /dev/null +++ b/addons/EmpyPopTracker/nms/sedna.lua @@ -0,0 +1,48 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = "Sedna", + bg_url = 'https://www.bg-wiki.com/bg/Sedna', + pops = { { + id = 1512, --Shimmering Pugil Scale + type = "key item", + dropped_from = { name = "Hrosshvalur, Timed (J-6)" } + }, { + id = 1511, --Glossy Sea Monk Sucker + type = "key item", + dropped_from = { + name = "Iku-Turso, Forced (J-7)", + pops = { { + id = 3100, --Moonbeam Clam + type = "item", + dropped_from = { name = "Jasconius (I-7/J-7)" } + } } + } + } } +} diff --git a/addons/EmpyPopTracker/nms/sobek.lua b/addons/EmpyPopTracker/nms/sobek.lua new file mode 100644 index 0000000000..570fd9d51e --- /dev/null +++ b/addons/EmpyPopTracker/nms/sobek.lua @@ -0,0 +1,59 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = "Sobek", + bg_url = 'https://www.bg-wiki.com/bg/Sobek', + pops = { { + id = 1500, --Molted Peiste Skin + type = "key item", + dropped_from = { name = "Gukumatz, Timed (J-11)" } + }, { + id = 1498, --Bloodstained Bugard Fang + type = "key item", + dropped_from = { + name = "Minax Bugard, Forced (K-10)", + pops = { { + id = 3085, --Bewitching Tusk + type = "item", + dropped_from = { name = "Abyssobugard (J-10/K-11)" } + } } + } + }, { + id = 1499, --Gnarled Lizard Nail + type = "key item", + dropped_from = { + name = "Sirrush, Forced (I-11)", + pops = { { + id = 3086, --Molt Scraps + type = "item", + dropped_from = { name = "Dusk Lizard (J-11)" } + } } + } + } } +} diff --git a/addons/EmpyPopTracker/nms/ulhuadshi.lua b/addons/EmpyPopTracker/nms/ulhuadshi.lua new file mode 100644 index 0000000000..3d22113963 --- /dev/null +++ b/addons/EmpyPopTracker/nms/ulhuadshi.lua @@ -0,0 +1,48 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = "Ulhuadshi", + bg_url = 'https://www.bg-wiki.com/bg/Ulhuadshi', + pops = { { + id = 1492, --Shriveled Hecteyes Stalk + type = "key item", + dropped_from = { name = "Amun, Timed (H-8/I-9)" } + }, { + id = 1491, --Mucid Worm Segment + type = "key item", + dropped_from = { + name = "Pallid Percy, Forced (J-7)", + pops = { { + id = 3074, --Blanched Silver + type = "item", + dropped_from = { name = "Entozoon (J-7)" } + } } + } + } } +} diff --git a/addons/EmpyPopTracker/readme/demo-full.png b/addons/EmpyPopTracker/readme/demo-full.png new file mode 100644 index 0000000000000000000000000000000000000000..02df409dabe34d3fafaedacf0d13efe53a01c576 GIT binary patch literal 26460 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

QWC@pfDZ=P^XtlN03liT~${`5pATHe(-Ga*!vb( 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 a0t^65+0Q<)G5p&A0000# literal 0 HcmV?d00001 diff --git a/addons/EmpyPopTracker/readme/demo.png b/addons/EmpyPopTracker/readme/demo.png new file mode 100644 index 0000000000000000000000000000000000000000..db24c678e886cc87643b64ec01bc83a6d62734ce GIT binary patch literal 22426 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

%S})^feiZ?HGl^wWG|Gt6gB;9TL%CT3Ntw8Lx^# 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 literal 0 HcmV?d00001 From db5445aeb69b3f6e70a7285c1d24b985c7c97ea1 Mon Sep 17 00:00:00 2001 From: Dean James Date: Mon, 13 Jan 2020 23:00:26 +0000 Subject: [PATCH 0338/1002] Added EmpyPopTracker to addons.xml. --- addons/addons.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/addons/addons.xml b/addons/addons.xml index f09c2cb2d5..dfc12b02d4 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -205,6 +205,13 @@ https://github.com/tehkrizz/Lua/issues http://www.ffxiah.com/player/Bahamut/Krizz + + EmpyPopTracker + Dean James (Xurion of Bismarck) + Tracks items and key items for popping Empyrean NMs in Abyssea, such as Briareus, Apademak and Sobek. + https://github.com/xurion/ffxi-empy-pop-tracker/issues + https://www.ffxiah.com/forum/topic/54376/empyrean-pop-tracker-addon-10-years-late/ + Enemybar mmckee From 1cebfdbb2ce52a37e5d44b0ed6834a5c48eec3eb Mon Sep 17 00:00:00 2001 From: Dean James Date: Mon, 27 Jan 2020 22:50:37 +0000 Subject: [PATCH 0339/1002] Double quotes to singles. Fixed issue with ucwords where it would return a list. Futureproofed owns_items function. Referencing resources by name. Removed add_to_chat function and moved chat mode to settings. Removed unnecessary validation from generate_info function. Removed BG URL from each data file and inferred URL by NM name. Corrected indent size in data files. PR comments addressed. --- addons/EmpyPopTracker/EmpyPopTracker.lua | 382 ++++++++++----------- addons/EmpyPopTracker/nms/README.md | 83 ++--- addons/EmpyPopTracker/nms/alfard.lua | 53 ++- addons/EmpyPopTracker/nms/apademak.lua | 51 ++- addons/EmpyPopTracker/nms/azdaja.lua | 13 +- addons/EmpyPopTracker/nms/briareus.lua | 71 ++-- addons/EmpyPopTracker/nms/bukhis.lua | 55 +-- addons/EmpyPopTracker/nms/carabosse.lua | 49 ++- addons/EmpyPopTracker/nms/chloris.lua | 155 +++++---- addons/EmpyPopTracker/nms/cirein-croin.lua | 35 +- addons/EmpyPopTracker/nms/dragua.lua | 13 +- addons/EmpyPopTracker/nms/glavoid.lua | 97 +++--- addons/EmpyPopTracker/nms/index.lua | 36 +- addons/EmpyPopTracker/nms/isgebind.lua | 13 +- addons/EmpyPopTracker/nms/itzpapalotl.lua | 57 ++- addons/EmpyPopTracker/nms/kukulkan.lua | 71 ++-- addons/EmpyPopTracker/nms/orthrus.lua | 51 ++- addons/EmpyPopTracker/nms/sedna.lua | 35 +- addons/EmpyPopTracker/nms/sobek.lua | 57 ++- addons/EmpyPopTracker/nms/ulhuadshi.lua | 35 +- 20 files changed, 691 insertions(+), 721 deletions(-) diff --git a/addons/EmpyPopTracker/EmpyPopTracker.lua b/addons/EmpyPopTracker/EmpyPopTracker.lua index 6fd546248a..cb11451aa2 100644 --- a/addons/EmpyPopTracker/EmpyPopTracker.lua +++ b/addons/EmpyPopTracker/EmpyPopTracker.lua @@ -27,13 +27,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] _addon.name = "Empy Pop Tracker" -_addon.author = "Dean James (Xurion of Bismarck)" -_addon.commands = { "ept", "empypoptracker" } -_addon.version = "2.0.0" +_addon.author = 'Dean James (Xurion of Bismarck)' +_addon.commands = { 'ept', 'empypoptracker' } +_addon.version = '2.0.0' -config = require("config") -res = require("resources") -nm_data = require("nms/index") +config = require('config') +res = require('resources') +nm_data = require('nms/index') active = false @@ -52,288 +52,272 @@ defaults.text.bg.red = 0 defaults.text.bg.visible = true defaults.text.padding = 8 defaults.text.text = {} -defaults.text.text.font = "Consolas" +defaults.text.text.font = 'Consolas' defaults.text.text.size = 10 -defaults.tracking = "briareus" +defaults.tracking = 'briareus' defaults.visible = true +defaults.add_to_chat_mode = 8 EmpyPopTracker.settings = config.load(defaults) -EmpyPopTracker.text = require("texts").new(EmpyPopTracker.settings.text, EmpyPopTracker.settings) +EmpyPopTracker.text = require('texts').new(EmpyPopTracker.settings.text, EmpyPopTracker.settings) colors = {} -colors.success = "\\cs(100,255,100)" -colors.danger = "\\cs(255,50,50)" -colors.warning = "\\cs(255,170,0)" -colors.close = "\\cr" +colors.success = '\\cs(100,255,100)' +colors.danger = '\\cs(255,50,50)' +colors.warning = '\\cs(255,170,0)' +colors.close = '\\cr' function owns_item(id, items) - local owned = false - - -- Loop maximum 80 times over all slots. 80 indexes are returned for each bag regardless of max capacity. - for i = 1, 80, 1 do - if items.safe[i].id == id or - items.safe2[i].id == id or - items.locker[i].id == id or - items.sack[i].id == id or - items.satchel[i].id == id or - items.inventory[i].id == id or - items.storage[i].id == id then - owned = true - break - end + for _, bag in ipairs(items) do + for _, item in ipairs(bag) do + if item.id == id then + return true + end end + end - return owned + return false end function owns_key_item(id, items) - local owned = false + local owned = false - for _, item_id in pairs(items) do - if item_id == id then - owned = true - break - end + for _, item_id in pairs(items) do + if item_id == id then + owned = true + break end + end - return owned + return owned end function item_treasure_pool_count(id, treasure) - local count = 0 + local count = 0 - for _, item in pairs(treasure) do - if item.item_id == id then - count = count + 1 - end + for _, item in pairs(treasure) do + if item.item_id == id then + count = count + 1 end + end - return count + return count end function ucwords(str) - return string.gsub(str, "(%a)([%w_']*)", function(first, rest) - return first:upper() .. rest:lower() - end) + local result = string.gsub(str, '(%a)([%w_\']*)', function(first, rest) + return first:upper() .. rest:lower() + end) + + return result end function get_indent(depth) - return string.rep(" ", depth) + return string.rep(' ', depth) end function generate_text(data, key_items, items, depth) - local text = depth == 1 and data.name or "" - for _, pop in pairs(data.pops) do - local resource - local item_scope - local owns_pop - local in_pool_count = 0 - local item_identifier = '' - - if pop.type == 'key item' then - resource = res.key_items[pop.id] - owns_pop = owns_key_item(pop.id, key_items) - item_identifier = 'Ж ' - else - resource = res.items[pop.id] - owns_pop = owns_item(pop.id, items) - in_pool_count = item_treasure_pool_count(pop.id, items.treasure) - end - - local pop_name = 'Unknown pop' - if resource then - pop_name = ucwords(resource.en) - end - - --separator line for each top-level mob - if depth == 1 then - text = text .. "\n" - end - - local item_colour - if owns_pop then - item_colour = colors.success - else - item_colour = colors.danger - end - - local pool_notification = '' - if in_pool_count > 0 then - pool_notification = colors.warning .. ' [' .. in_pool_count .. ']' .. colors.close - end - text = text .. "\n" .. get_indent(depth) .. pop.dropped_from.name .. "\n" .. get_indent(depth) .. ' >> ' .. item_colour .. item_identifier .. pop_name .. colors.close .. pool_notification - if pop.dropped_from.pops then - text = text .. generate_text(pop.dropped_from, key_items, items, depth + 1) - end + local text = depth == 1 and data.name or '' + for _, pop in pairs(data.pops) do + local resource + local item_scope + local owns_pop + local in_pool_count = 0 + local item_identifier = '' + + if pop.type == 'key item' then + resource = res.key_items[pop.id] + owns_pop = owns_key_item(pop.id, key_items) + item_identifier = 'Ж ' + else + resource = res.items[pop.id] + owns_pop = owns_item(pop.id, items) + in_pool_count = item_treasure_pool_count(pop.id, items.treasure) end - return text -end - -EmpyPopTracker.add_to_chat = function(message) - if type(message) ~= 'string' then - error('add_to_chat requires the message arg to be a string') + local pop_name = 'Unknown pop' + if resource then + pop_name = ucwords(resource.name) end - windower.add_to_chat(8, message) -end + --separator line for each top-level mob + if depth == 1 then + text = text .. '\n' + end -EmpyPopTracker.generate_info = function(nm, key_items, items) - local nm_type = type(nm) - if nm_type ~= 'table' then - error('generate_info requires the nm arg to be a table, but got ' .. nm_type .. ' instead') + local item_colour + if owns_pop then + item_colour = colors.success + else + item_colour = colors.danger end - local info = { - has_all_kis = true, - text = "" - } + local pool_notification = '' + if in_pool_count > 0 then + pool_notification = colors.warning .. ' [' .. in_pool_count .. ']' .. colors.close + end + text = text .. '\n' .. get_indent(depth) .. pop.dropped_from.name .. '\n' .. get_indent(depth) .. ' >> ' .. item_colour .. item_identifier .. pop_name .. colors.close .. pool_notification + if pop.dropped_from.pops then + text = text .. generate_text(pop.dropped_from, key_items, items, depth + 1) + end + end - if nm.pops then - for _, key_item_data in pairs(nm.pops) do - local has_pop_ki = owns_key_item(key_item_data.id, key_items) + return text +end - if not has_pop_ki then - info.has_all_kis = false - end - end +EmpyPopTracker.generate_info = function(nm, key_items, items) + local nm_type = type(nm) + local info = { + has_all_kis = true, + text = '' + } + + if nm.pops then + for _, key_item_data in pairs(nm.pops) do + local has_pop_ki = owns_key_item(key_item_data.id, key_items) + + if not has_pop_ki then + info.has_all_kis = false + end end + end - info.text = generate_text(nm, key_items, items, 1) + info.text = generate_text(nm, key_items, items, 1) - return info + return info end function find_nms(query) - local matching_nms = {} - local lower_query = query:lower() - for _, nm in pairs(nm_data) do - local result = string.match(nm.name:lower(), '(.*' .. lower_query .. '.*)') - if result then - table.insert(matching_nms, result) - end + local matching_nms = {} + local lower_query = query:lower() + for _, nm in pairs(nm_data) do + local result = string.match(nm.name:lower(), '(.*' .. lower_query .. '.*)') + if result then + table.insert(matching_nms, result) end - return matching_nms + end + return matching_nms end -windower.register_event("addon command", function(command, ...) - if commands[command] then - commands[command](...) - else - commands.help() - end +windower.register_event('addon command', function(command, ...) + if commands[command] then + commands[command](...) + else + commands.help() + end end) commands = {} commands.track = function(...) - local args = {...} - local nm_name = args[1] - local matching_nm_names = find_nms(nm_name) - - if #matching_nm_names == 0 then - EmpyPopTracker.add_to_chat('Unable to find a NM using: "' .. nm_name .. '"') - elseif #matching_nm_names > 1 then - EmpyPopTracker.add_to_chat('"' .. nm_name .. '" matches ' .. #matching_nm_names .. ' NMs. Please be more explicit:') - for key, matching_file_name in pairs(matching_nm_names) do - EmpyPopTracker.add_to_chat(' Match ' .. key .. ': ' .. ucwords(matching_file_name)) - end - else - active = true - EmpyPopTracker.add_to_chat("Now tracking: " .. ucwords(matching_nm_names[1])) - EmpyPopTracker.settings.tracking = matching_nm_names[1] - EmpyPopTracker.update() - commands.show() + local args = {...} + local nm_name = args[1] + local matching_nm_names = find_nms(nm_name) + + if #matching_nm_names == 0 then + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, 'Unable to find a NM using: "' .. nm_name .. '"') + elseif #matching_nm_names > 1 then + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '"' .. nm_name .. '" matches ' .. #matching_nm_names .. ' NMs. Please be more explicit:') + for key, matching_file_name in pairs(matching_nm_names) do + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, ' Match ' .. key .. ': ' .. ucwords(matching_file_name)) end + else + active = true + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, 'Now tracking: ' .. ucwords(matching_nm_names[1])) + EmpyPopTracker.settings.tracking = matching_nm_names[1] + EmpyPopTracker.update() + commands.show() + end end commands.t = commands.track commands.hide = function() - active = false - EmpyPopTracker.text:visible(false) - EmpyPopTracker.settings.visible = false - EmpyPopTracker.settings:save() + active = false + EmpyPopTracker.text:visible(false) + EmpyPopTracker.settings.visible = false + EmpyPopTracker.settings:save() end commands.show = function() - active = true - EmpyPopTracker.text:visible(true) - EmpyPopTracker.settings.visible = true - EmpyPopTracker.settings:save() - EmpyPopTracker.update() + active = true + EmpyPopTracker.text:visible(true) + EmpyPopTracker.settings.visible = true + EmpyPopTracker.settings:save() + EmpyPopTracker.update() end commands.help = function() - EmpyPopTracker.add_to_chat("---Empy Pop Tracker---") - EmpyPopTracker.add_to_chat("Available commands:") - EmpyPopTracker.add_to_chat("//ept t|track briareus - tracks Briareus pops (partial names such as apadem work too!)") - EmpyPopTracker.add_to_chat("//ept hide - hides the UI") - EmpyPopTracker.add_to_chat("//ept show - shows the UI") - EmpyPopTracker.add_to_chat("//ept list - lists all trackable NMs") - EmpyPopTracker.add_to_chat("//ept help - displays this help") + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '---Empy Pop Tracker---') + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, 'Available commands:') + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '//ept track briareus - tracks Briareus pops (partial names such as apadem work too!)') + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '//ept hide - hides the UI') + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '//ept show - shows the UI') + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '//ept list - lists all trackable NMs') + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '//ept help - displays this help') end commands.list = function() - EmpyPopTracker.add_to_chat("---Empy Pop Tracker---") - EmpyPopTracker.add_to_chat("Trackable NMs:") - for _, nm in pairs(nm_data) do - EmpyPopTracker.add_to_chat(ucwords(nm.name)) - end + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '---Empy Pop Tracker---') + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, 'Trackable NMs:') + for _, nm in pairs(nm_data) do + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, ucwords(nm.name)) + end end commands.bg = function() - local tracking_nm = nm_data[EmpyPopTracker.settings.tracking] - windower.open_url(tracking_nm.bg_url) + local tracking_nm = nm_data[EmpyPopTracker.settings.tracking] + local url = 'https://www.bg-wiki.com/bg/' .. tracking_nm.name + windower.open_url(url) end EmpyPopTracker.update = function() - local key_items = windower.ffxi.get_key_items() - local items = windower.ffxi.get_items() - local tracked_nm_data = nm_data[EmpyPopTracker.settings.tracking] - local generated_info = EmpyPopTracker.generate_info(tracked_nm_data, key_items, items) - EmpyPopTracker.text:text(generated_info.text) - if generated_info.has_all_kis then - EmpyPopTracker.text:bg_color(0, 75, 0) - else - EmpyPopTracker.text:bg_color(0, 0, 0) - end - if EmpyPopTracker.settings.visible then - EmpyPopTracker.text:visible(true) - end + local key_items = windower.ffxi.get_key_items() + local items = windower.ffxi.get_items() + local tracked_nm_data = nm_data[EmpyPopTracker.settings.tracking] + local generated_info = EmpyPopTracker.generate_info(tracked_nm_data, key_items, items) + EmpyPopTracker.text:text(generated_info.text) + if generated_info.has_all_kis then + EmpyPopTracker.text:bg_color(0, 75, 0) + else + EmpyPopTracker.text:bg_color(0, 0, 0) + end + if EmpyPopTracker.settings.visible then + EmpyPopTracker.text:visible(true) + end end windower.register_event('load', function() - if windower.ffxi.get_info().logged_in and EmpyPopTracker.settings.visible then - active = true - EmpyPopTracker.update() - end + if windower.ffxi.get_info().logged_in and EmpyPopTracker.settings.visible then + active = true + EmpyPopTracker.update() + end end) windower.register_event('add item', 'remove item', function() - if active then - EmpyPopTracker.update() - end + if active then + EmpyPopTracker.update() + end end) windower.register_event('incoming chunk', function(id) - --0x055: KI update - --0x0D2: Treasure pool addition - --0x0D3: Treasure pool lot/drop - if active and id == 0x055 or id == 0x0D2 or id == 0x0D3 then - EmpyPopTracker.update() - end + --0x055: KI update + --0x0D2: Treasure pool addition + --0x0D3: Treasure pool lot/drop + if active and id == 0x055 or id == 0x0D2 or id == 0x0D3 then + EmpyPopTracker.update() + end end) windower.register_event('login', function() - if EmpyPopTracker.settings.visible then - EmpyPopTracker.text:visible(true) - active = true - end + if EmpyPopTracker.settings.visible then + EmpyPopTracker.text:visible(true) + active = true + end end) windower.register_event('logout', function() - EmpyPopTracker.text:visible(false) - active = false + EmpyPopTracker.text:visible(false) + active = false end) return EmpyPopTracker diff --git a/addons/EmpyPopTracker/nms/README.md b/addons/EmpyPopTracker/nms/README.md index bad2e262b4..720d0a7d4d 100644 --- a/addons/EmpyPopTracker/nms/README.md +++ b/addons/EmpyPopTracker/nms/README.md @@ -2,25 +2,24 @@ The data structure for each trackable NM uses a series of nested NM entities. A standard NM entity contains the following data: -| Key | Type | Required? | Description | -| ------------------- | --------- | --------- | --------------------------------- | -| name | String | Required | Name of the NM | -| bg_url | String | Required | URL of the bgwiki page for the NM | -| pops | Table | Optional | The pop information for the NM | -| pops{}.id | Number | Required | The ID of the item/key item | -| pops{}.type | String | Required | Either "key item" or "item" | -| pops{}.dropped_from | NM Entity | Required | A nested set of NM information | +| Key | Type | Required? | Description | +| ------------------- | --------- | --------- | ------------------------------ | +| name | String | Required | Name of the NM | +| pops | Table | Optional | The pop information for the NM | +| pops{}.id | Number | Required | The ID of the item/key item | +| pops{}.type | String | Required | Either "key item" or "item" | +| pops{}.dropped_from | NM Entity | Required | A nested set of NM information | A simple example of the above would be: ```lua { - name = "Azdaja", - pops = { { - id = 1531, --Vacant Bugard Eye - type = "key item", - dropped_from = { name = "Deelgeed, Timed (F-9/F-10)" } - } } + name = 'Azdaja', + pops = { { + id = 1531, --Vacant Bugard Eye + type = 'key item', + dropped_from = { name = 'Deelgeed, Timed (F-9/F-10)' } + } } } ``` @@ -28,34 +27,36 @@ A larger example with multiple nested entites: ```lua { - name = "Bukhis", - pops = { { - id = 1508, --Ingrown Taurus Nail - type = "key item", - dropped_from = { - name = "Khalkotaur, Forced (F-4)", - pops = { { - id = 3098, --Gnarled Taurus Horn - type = "item", - dropped_from = { name = "Aestutaur (G-9/G-10)" } - } } - }, { - id = 1509, --Ossified Gargouille Hand - type = "key item", - dropped_from = { - name = "Quasimodo, Forced (F-4)", - pops = { { - id = 3099, --Gargouille Stone - type = "item", - dropped_from = { name = "Gruesome Gargouille (F-10/G-10)" } - } } - } - }, { - id = 1510, --Imbrued Vampyr Fang - type = "key item", - dropped_from = { name = "Lord Varney, Timed (G-10/H-10)" } + name = 'Bukhis', + pops = { { + id = 1508, --Ingrown Taurus Nail + type = 'key item', + dropped_from = { + name = 'Khalkotaur, Forced (F-4)', + pops = { { + id = 3098, --Gnarled Taurus Horn + type = 'item', + dropped_from = { name = 'Aestutaur (G-9/G-10)' } + } } + }, { + id = 1509, --Ossified Gargouille Hand + type = 'key item', + dropped_from = { + name = 'Quasimodo, Forced (F-4)', + pops = { { + id = 3099, --Gargouille Stone + type = 'item', + dropped_from = { + name = 'Gruesome Gargouille (F-10/G-10)' + } } } - } + } + }, { + id = 1510, --Imbrued Vampyr Fang + type = 'key item', + dropped_from = { name = 'Lord Varney, Timed (G-10/H-10)' } + } } + } } ``` diff --git a/addons/EmpyPopTracker/nms/alfard.lua b/addons/EmpyPopTracker/nms/alfard.lua index 88dedb7a26..689d4ddcc6 100644 --- a/addons/EmpyPopTracker/nms/alfard.lua +++ b/addons/EmpyPopTracker/nms/alfard.lua @@ -27,33 +27,32 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = "Alfard", - bg_url = 'https://www.bg-wiki.com/bg/Alfard', - pops = { { - id = 1530, --Venomous hydra fang - type = "key item", + name = 'Alfard', + pops = { { + id = 1530, --Venomous hydra fang + type = 'key item', + dropped_from = { + name = 'Ningishzida, Forced (I-7/I-8)', + pops = { { + id = 3262, --Jaculus Wing + type = 'item', + dropped_from = { name = 'Jaculus, Timed (I-8)' } + }, { + id = 3261, --Minaruja Skull + type = 'item', dropped_from = { - name = "Ningishzida, Forced (I-7/I-8)", - pops = { { - id = 3262, --Jaculus Wing - type = "item", - dropped_from = { name = "Jaculus, Timed (I-8)" } - }, { - id = 3261, --Minaruja Skull - type = "item", - dropped_from = { - name = "Minaruja, Forced (I-10)", - pops = { { - id = 3267, --Pursuer's Wing - type = "item", - dropped_from = { name = "Faunus Wyvern (I-9)" } - } } - } - }, { - id = 3268, --High-Quality Wivre Hide - type = "item", - dropped_from = { name = "Glade Wivre (I-8)" } - } } + name = 'Minaruja, Forced (I-10)', + pops = { { + id = 3267, --Pursuer's Wing + type = 'item', + dropped_from = { name = 'Faunus Wyvern (I-9)' } + } } } - } } + }, { + id = 3268, --High-Quality Wivre Hide + type = 'item', + dropped_from = { name = 'Glade Wivre (I-8)' } + } } + } + } } } diff --git a/addons/EmpyPopTracker/nms/apademak.lua b/addons/EmpyPopTracker/nms/apademak.lua index f3c37a21e8..63315f5683 100644 --- a/addons/EmpyPopTracker/nms/apademak.lua +++ b/addons/EmpyPopTracker/nms/apademak.lua @@ -27,32 +27,31 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = "Apademak", - bg_url = 'https://www.bg-wiki.com/bg/Apademak', - pops = { { - id = 1525, --Torn Khimaira Wing - type = "key item", + name = 'Apademak', + pops = { { + id = 1525, --Torn Khimaira Wing + type = 'key item', + dropped_from = { + name = 'Dhorme Khimaira, Forced (F-7)', + pops = { { + id = 3246, --Snow God Core + type = 'item', dropped_from = { - name = "Dhorme Khimaira, Forced (F-7)", - pops = { { - id = 3246, --Snow God Core - type = "item", - dropped_from = { - name = "Upas-Kamuy, Forced (G-5)", - pops = { { - id = 3252, --Gelid Arm - dropped_from = { name = "Snowflake (G-5)" } - } } - } - }, { - id = 3247, --Sisyphus Fragment - type = "item", - dropped_from = { name = "Sisyphus, Timed (F-6/G-6)" } - }, { - id = 3253, --High-quality marid hide - type = "item", - dropped_from = { name = "Olyphant (F-6)" } - } } + name = 'Upas-Kamuy, Forced (G-5)', + pops = { { + id = 3252, --Gelid Arm + dropped_from = { name = 'Snowflake (G-5)' } + } } } - } } + }, { + id = 3247, --Sisyphus Fragment + type = 'item', + dropped_from = { name = 'Sisyphus, Timed (F-6/G-6)' } + }, { + id = 3253, --High-quality marid hide + type = 'item', + dropped_from = { name = 'Olyphant (F-6)' } + } } + } + } } } diff --git a/addons/EmpyPopTracker/nms/azdaja.lua b/addons/EmpyPopTracker/nms/azdaja.lua index 28716728a0..b6eb58f1d4 100644 --- a/addons/EmpyPopTracker/nms/azdaja.lua +++ b/addons/EmpyPopTracker/nms/azdaja.lua @@ -27,11 +27,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = "Azdaja", - bg_url = 'https://www.bg-wiki.com/bg/Azdaja', - pops = { { - id = 1531, --Vacant Bugard Eye - type = "key item", - dropped_from = { name = "Deelgeed, Timed (F-9/F-10)" } - } } + name = 'Azdaja', + pops = { { + id = 1531, --Vacant Bugard Eye + type = 'key item', + dropped_from = { name = 'Deelgeed, Timed (F-9/F-10)' } + } } } diff --git a/addons/EmpyPopTracker/nms/briareus.lua b/addons/EmpyPopTracker/nms/briareus.lua index 141f27b64c..553350cbd4 100644 --- a/addons/EmpyPopTracker/nms/briareus.lua +++ b/addons/EmpyPopTracker/nms/briareus.lua @@ -27,40 +27,39 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = "Briareus", - bg_url = 'https://www.bg-wiki.com/bg/Briareus', - pops = { { - id = 1482, --Dented Gigas Shield - type = "key item", - dropped_from = { - name = "Adamastor, Forced (C-4)", - pops = { { - id = 2894, --Trophy Shield - type = "item", - dropped_from = { name = "Bathyal Gigas (C-5/D-5)" } - } } - } - }, { - id = 1484, --Severed Gigas Collar - type = "key item", - dropped_from = { - name = "Grandgousier, Forced (F-10)", - pops = { { - id = 2896, --Massive Armband - type = "item", - dropped_from = { name = "Demersal Gigas (E-9/F-9)" } - } } - } - }, { - id = 1483, --Warped Gigas Armband - type = "key item", - dropped_from = { - name = "Pantagruel, Forced (F-7)", - pops = { { - id = 2895, --Oversized Sock - type = "item", - dropped_from = { name = "Hadal Gigas (F-6/F-7)" } - } } - } - } } + name = 'Briareus', + pops = { { + id = 1482, --Dented Gigas Shield + type = 'key item', + dropped_from = { + name = 'Adamastor, Forced (C-4)', + pops = { { + id = 2894, --Trophy Shield + type = 'item', + dropped_from = { name = 'Bathyal Gigas (C-5/D-5)' } + } } + } + }, { + id = 1484, --Severed Gigas Collar + type = 'key item', + dropped_from = { + name = 'Grandgousier, Forced (F-10)', + pops = { { + id = 2896, --Massive Armband + type = 'item', + dropped_from = { name = 'Demersal Gigas (E-9/F-9)' } + } } + } + }, { + id = 1483, --Warped Gigas Armband + type = 'key item', + dropped_from = { + name = 'Pantagruel, Forced (F-7)', + pops = { { + id = 2895, --Oversized Sock + type = 'item', + dropped_from = { name = 'Hadal Gigas (F-6/F-7)' } + } } + } + } } } diff --git a/addons/EmpyPopTracker/nms/bukhis.lua b/addons/EmpyPopTracker/nms/bukhis.lua index 4197cc0eb5..019864b732 100644 --- a/addons/EmpyPopTracker/nms/bukhis.lua +++ b/addons/EmpyPopTracker/nms/bukhis.lua @@ -27,33 +27,34 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = "Bukhis", - bg_url = 'https://www.bg-wiki.com/bg/Bukhis', - pops = { { - id = 1508, --Ingrown Taurus Nail - type = "key item", + name = 'Bukhis', + pops = { { + id = 1508, --Ingrown Taurus Nail + type = 'key item', + dropped_from = { + name = 'Khalkotaur, Forced (F-4)', + pops = { { + id = 3098, --Gnarled Taurus Horn + type = 'item', + dropped_from = { name = 'Aestutaur (G-9/G-10)' } + } } + } + }, { + id = 1509, --Ossified Gargouille Hand + type = 'key item', + dropped_from = { + name = 'Quasimodo, Forced (F-4)', + pops = { { + id = 3099, --Gargouille Stone + type = 'item', dropped_from = { - name = "Khalkotaur, Forced (F-4)", - pops = { { - id = 3098, --Gnarled Taurus Horn - type = "item", - dropped_from = { name = "Aestutaur (G-9/G-10)" } - } } + name = 'Gruesome Gargouille (F-10/G-10)' } - }, { - id = 1509, --Ossified Gargouille Hand - type = "key item", - dropped_from = { - name = "Quasimodo, Forced (F-4)", - pops = { { - id = 3099, --Gargouille Stone - type = "item", - dropped_from = { name = "Gruesome Gargouille (F-10/G-10)" } - } } - } - }, { - id = 1510, --Imbrued Vampyr Fang - type = "key item", - dropped_from = { name = "Lord Varney, Timed (G-10/H-10)" } - } } + } } + } + }, { + id = 1510, --Imbrued Vampyr Fang + type = 'key item', + dropped_from = { name = 'Lord Varney, Timed (G-10/H-10)' } + } } } diff --git a/addons/EmpyPopTracker/nms/carabosse.lua b/addons/EmpyPopTracker/nms/carabosse.lua index 7f4c59c86b..97b0c9c5e7 100644 --- a/addons/EmpyPopTracker/nms/carabosse.lua +++ b/addons/EmpyPopTracker/nms/carabosse.lua @@ -27,29 +27,28 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = "Carabosse", - bg_url = 'https://www.bg-wiki.com/bg/Carabosse', - pops = { { - id = 1485, --Pellucid Fly Eye - type = "key item", - dropped_from = { - name = "La Theine Liege, Forced (I-7)", - pops = { { - id = 2897, --Transparent Insect Wing - type = "item", - dropped_from = { name = "Plateau Glider (H-7)" } - } } - } - }, { - id = 1486, --Shimmering Pixie Pinion - type = "key item", - dropped_from = { - name = "Baba Yaga, Forced (H-7)", - pops = { { - id = 2898, --Piceous Scale - type = "item", - dropped_from = { name = "Farfadet (H-7)" } - } } - } - } } + name = 'Carabosse', + pops = { { + id = 1485, --Pellucid Fly Eye + type = 'key item', + dropped_from = { + name = 'La Theine Liege, Forced (I-7)', + pops = { { + id = 2897, --Transparent Insect Wing + type = 'item', + dropped_from = { name = 'Plateau Glider (H-7)' } + } } + } + }, { + id = 1486, --Shimmering Pixie Pinion + type = 'key item', + dropped_from = { + name = 'Baba Yaga, Forced (H-7)', + pops = { { + id = 2898, --Piceous Scale + type = 'item', + dropped_from = { name = 'Farfadet (H-7)' } + } } + } + } } } diff --git a/addons/EmpyPopTracker/nms/chloris.lua b/addons/EmpyPopTracker/nms/chloris.lua index 7695cd0e06..78dbaeacc1 100644 --- a/addons/EmpyPopTracker/nms/chloris.lua +++ b/addons/EmpyPopTracker/nms/chloris.lua @@ -27,88 +27,87 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = "Chloris", - bg_url = 'https://www.bg-wiki.com/bg/Chloris', - pops = { { - id = 1470, --Gory Scorpion Claw - type = "key item", + name = 'Chloris', + pops = { { + id = 1470, --Gory Scorpion Claw + type = 'key item', + dropped_from = { + name = 'Hedetet, Forced (F-7)', + pops = { { + id = 2921, --Venomous Scorpion Stinger + type = 'item', + dropped_from = { name = 'Canyon Scorpion (F-7)' } + }, { + id = 2948, --Acidic Humus + type = 'item', dropped_from = { - name = "Hedetet, Forced (F-7)", - pops = { { - id = 2921, --Venomous Scorpion Stinger - type = "item", - dropped_from = { name = "Canyon Scorpion (F-7)" } - }, { - id = 2948, --Acidic Humus - type = "item", - dropped_from = { - name = "Gancanagh, Forced (H-8)", - pops = { { - id = 2920, --Alkaline Humus - type = "item", - dropped_from = { name = "Pachypodium (H-8)" } - } } - } - } } + name = 'Gancanagh, Forced (H-8)', + pops = { { + id = 2920, --Alkaline Humus + type = 'item', + dropped_from = { name = 'Pachypodium (H-8)' } + } } } - }, { - id = 1469, --Torn Bat Wing - type = "key item", + } } + } + }, { + id = 1469, --Torn Bat Wing + type = 'key item', + dropped_from = { + name = 'Treble Noctules, Forced (I-9)', + pops = { { + id = 2919, --Bloody Fang + type = 'item', + dropped_from = { name = 'Blood Bat (I-9)' } + }, { + id = 2947, --Exorcised Skull + type = 'item', dropped_from = { - name = "Treble Noctules, Forced (I-9)", - pops = { { - id = 2919, --Bloody Fang - type = "item", - dropped_from = { name = "Blood Bat (I-9)" } - }, { - id = 2947, --Exorcised Skull - type = "item", - dropped_from = { - name = "Cannered Noz, Forced (F-6)", - pops = { { - id = 2918, --Baleful Skull - type = "item", - dropped_from = { name = "Caoineag (F-6)" } - } } - } - } } + name = 'Cannered Noz, Forced (F-6)', + pops = { { + id = 2918, --Baleful Skull + type = 'item', + dropped_from = { name = 'Caoineag (F-6)' } + } } } - }, { - id = 1468, --Veinous Hecteyes Eyelid - type = "key item", + } } + } + }, { + id = 1468, --Veinous Hecteyes Eyelid + type = 'key item', + dropped_from = { + name = 'Ophanim, Forced (G-9)', + pops = { { + id = 2946, --Tarnished Pincer + type = 'item', dropped_from = { - name = "Ophanim, Forced (G-9)", - pops = { { - id = 2946, --Tarnished Pincer - type = "item", - dropped_from = { - name = "Vetehinen, Forced (H-10)", - pops = { { - id = 2916, --High-quality Limule Pincer - type = "item", - dropped_from = { name = "Gulch Limule (H-10)" } - }, { - id = 2917, --Bloodshot Hecteye - type = "item", - dropped_from = { name = "Beholder (G-9)" } - }, { - id = 2945, --Shriveled Wing - type = "item", - dropped_from = { - name = "Halimede, Forced (G-12)", - pops = { { - id = 2915, --High-quality Clionid Wing - type = "item", - dropped_from = { name = "Gully Clionid (G-12)" } - } } - } - } } - } - } } + name = 'Vetehinen, Forced (H-10)', + pops = { { + id = 2916, --High-quality Limule Pincer + type = 'item', + dropped_from = { name = 'Gulch Limule (H-10)' } + }, { + id = 2917, --Bloodshot Hecteye + type = 'item', + dropped_from = { name = 'Beholder (G-9)' } + }, { + id = 2945, --Shriveled Wing + type = 'item', + dropped_from = { + name = 'Halimede, Forced (G-12)', + pops = { { + id = 2915, --High-quality Clionid Wing + type = 'item', + dropped_from = { name = 'Gully Clionid (G-12)' } + } } + } + } } } - }, { - id = 1471, --Mossy Adamantoise Shell - type = "key item", - dropped_from = { name = "Chukwa, Timed (F-5)" } - } } + } } + } + }, { + id = 1471, --Mossy Adamantoise Shell + type = 'key item', + dropped_from = { name = 'Chukwa, Timed (F-5)' } + } } } diff --git a/addons/EmpyPopTracker/nms/cirein-croin.lua b/addons/EmpyPopTracker/nms/cirein-croin.lua index 78354bcd66..7a8a40af72 100644 --- a/addons/EmpyPopTracker/nms/cirein-croin.lua +++ b/addons/EmpyPopTracker/nms/cirein-croin.lua @@ -27,22 +27,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = "Cirein-Croin", - bg_url = 'https://www.bg-wiki.com/bg/Cirein-croin', - pops = { { - id = 1504, --Glistening Orobon Liver - type = "key item", - dropped_from = { - name = "Cep-Kamuy, Forced (F-4)", - pops = { { - id = 3089, --Orobon Cheekmeat - type = "item", - dropped_from = { name = "Ancient Orobon (F-5)" } - } } - } - }, { - id = 1505, --Doffed Poroggo Hat - type = "key item", - dropped_from = { name = "Heqet, Timed (I-6)" } - } } + name = 'Cirein-croin', + pops = { { + id = 1504, --Glistening Orobon Liver + type = 'key item', + dropped_from = { + name = 'Cep-Kamuy, Forced (F-4)', + pops = { { + id = 3089, --Orobon Cheekmeat + type = 'item', + dropped_from = { name = 'Ancient Orobon (F-5)' } + } } + } + }, { + id = 1505, --Doffed Poroggo Hat + type = 'key item', + dropped_from = { name = 'Heqet, Timed (I-6)' } + } } } diff --git a/addons/EmpyPopTracker/nms/dragua.lua b/addons/EmpyPopTracker/nms/dragua.lua index c584499caa..aa841e0762 100644 --- a/addons/EmpyPopTracker/nms/dragua.lua +++ b/addons/EmpyPopTracker/nms/dragua.lua @@ -27,11 +27,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = "Dragua", - bg_url = 'https://www.bg-wiki.com/bg/Dragua', - pops = { { - id = 1521, --Bloodied Dragon Ear - type = "key item", - dropped_from = { name = "Hazhdiha, Timed (H-10)" } - } } + name = 'Dragua', + pops = { { + id = 1521, --Bloodied Dragon Ear + type = 'key item', + dropped_from = { name = 'Hazhdiha, Timed (H-10)' } + } } } diff --git a/addons/EmpyPopTracker/nms/glavoid.lua b/addons/EmpyPopTracker/nms/glavoid.lua index 067d2a3454..3acf9b513d 100644 --- a/addons/EmpyPopTracker/nms/glavoid.lua +++ b/addons/EmpyPopTracker/nms/glavoid.lua @@ -27,57 +27,56 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = "Glavoid", - bg_url = 'https://www.bg-wiki.com/bg/Glavoid', - pops = { { - id = 1473, --Sodden Sandworm Husk - type = "key item", - dropped_from = { name = "Minhocao, Timed (I-6)" } - }, { - id = 1475, --Sticky Gnat Wing - type = "key item", - dropped_from = { name = "Adze, Timed (G-5)" } - }, { - id = 1472, --Fat-lined Cockatrice Skin - type = "key item", + name = 'Glavoid', + pops = { { + id = 1473, --Sodden Sandworm Husk + type = 'key item', + dropped_from = { name = 'Minhocao, Timed (I-6)' } + }, { + id = 1475, --Sticky Gnat Wing + type = 'key item', + dropped_from = { name = 'Adze, Timed (G-5)' } + }, { + id = 1472, --Fat-lined Cockatrice Skin + type = 'key item', + dropped_from = { + name = 'Alectryon (H-8)', + pops = { { + id = 2923, --Cockatrice Tailmeat + type = 'item', + dropped_from = { name = 'Cluckatrice (H-8)' } + }, { + id = 2949, --Quivering Eft Egg + type = 'item', dropped_from = { - name = "Alectryon (H-8)", - pops = { { - id = 2923, --Cockatrice Tailmeat - type = "item", - dropped_from = { name = "Cluckatrice (H-8)" } - }, { - id = 2949, --Quivering Eft Egg - type = "item", - dropped_from = { - name = "Abas, Forced (K-10)", - pops = { { - id = 2922, --Eft Egg - dropped_from = { name = "Canyon Eft (J-10/J-11)" } - } } - } - } } + name = 'Abas, Forced (K-10)', + pops = { { + id = 2922, --Eft Egg + dropped_from = { name = 'Canyon Eft (J-10/J-11)' } + } } } - }, { - id = 1474, --Luxuriant manticore mane - type = "key item", + } } + } + }, { + id = 1474, --Luxuriant manticore mane + type = 'key item', + dropped_from = { + name = 'Muscaliet, Forced (J-6)', + pops = { { + id = 2925, --Resilient Mane + type = 'item', + dropped_from = { name = 'Hieracosphinx (J-6)' } + }, { + id = 2950, --Smooth Whisker + type = 'item', dropped_from = { - name = "Muscaliet, Forced (J-6)", - pops = { { - id = 2925, --Resilient Mane - type = "item", - dropped_from = { name = "Hieracosphinx (J-6)" } - }, { - id = 2950, --Smooth Whisker - type = "item", - dropped_from = { - name = "Tefenet, Forced (G-6)", - pops = { { - id = 2924, --Shocking Whisker - dropped_from = { name = "Jaguarundi (G-6)" } - } } - } - } } + name = 'Tefenet, Forced (G-6)', + pops = { { + id = 2924, --Shocking Whisker + dropped_from = { name = 'Jaguarundi (G-6)' } + } } } - } } + } } + } + } } } diff --git a/addons/EmpyPopTracker/nms/index.lua b/addons/EmpyPopTracker/nms/index.lua index 9091a466a9..e10a91c5c5 100644 --- a/addons/EmpyPopTracker/nms/index.lua +++ b/addons/EmpyPopTracker/nms/index.lua @@ -27,28 +27,28 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] local nms = { - 'alfard', - 'apademak', - 'azdaja', - 'briareus', - 'bukhis', - 'carabosse', - 'chloris', - 'cirein-croin', - 'dragua', - 'glavoid', - 'isgebind', - 'itzpapalotl', - 'kukulkan', - 'orthrus', - 'sedna', - 'sobek', - 'ulhuadshi' + 'alfard', + 'apademak', + 'azdaja', + 'briareus', + 'bukhis', + 'carabosse', + 'chloris', + 'cirein-croin', + 'dragua', + 'glavoid', + 'isgebind', + 'itzpapalotl', + 'kukulkan', + 'orthrus', + 'sedna', + 'sobek', + 'ulhuadshi' } nm_data = {} for _, nm in pairs(nms) do - nm_data[nm] = require('nms/' .. nm) + nm_data[nm] = require('nms/' .. nm) end return nm_data diff --git a/addons/EmpyPopTracker/nms/isgebind.lua b/addons/EmpyPopTracker/nms/isgebind.lua index 3d5f5ef1e5..266c59e4e3 100644 --- a/addons/EmpyPopTracker/nms/isgebind.lua +++ b/addons/EmpyPopTracker/nms/isgebind.lua @@ -27,11 +27,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = "Isgebind", - bg_url = 'https://www.bg-wiki.com/bg/Isgebind', - pops = { { - id = 1526, --Begrimed Dragon Hide - type = "key item", - dropped_from = { name = "Kur, Timed (I-5/J-5)" } - } } + name = 'Isgebind', + pops = { { + id = 1526, --Begrimed Dragon Hide + type = 'key item', + dropped_from = { name = 'Kur, Timed (I-5/J-5)' } + } } } diff --git a/addons/EmpyPopTracker/nms/itzpapalotl.lua b/addons/EmpyPopTracker/nms/itzpapalotl.lua index 5e44302d21..744677a52c 100644 --- a/addons/EmpyPopTracker/nms/itzpapalotl.lua +++ b/addons/EmpyPopTracker/nms/itzpapalotl.lua @@ -27,33 +27,32 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = "Itzpapalotl", - bg_url = 'https://www.bg-wiki.com/bg/Itzpapalotl', - pops = { { - id = 1488, --Venomous Wamoura Feeler - type = "key item", - dropped_from = { - name = "Granite Borer, Forced (K-10)", - pops = { { - id = 3072, --Withered Cocoon - type = "item", - dropped_from = { name = "Gullycampa (K-10)" } - } } - } - }, { - id = 1490, --Distended Chigoe Abdomen - type = "key item", - dropped_from = { name = "Tunga, Timed (K-10)" } - }, { - id = 1489, --Bulbous crawler cocoon - type = "key item", - dropped_from = { - name = "Blazing Eruca, Forced (J-10)", - pops = { { - id = 3073, --Eruca Egg - type = "item", - dropped_from = { name = "Ignis Eruca (J-10)" } - } } - } - } } + name = 'Itzpapalotl', + pops = { { + id = 1488, --Venomous Wamoura Feeler + type = 'key item', + dropped_from = { + name = 'Granite Borer, Forced (K-10)', + pops = { { + id = 3072, --Withered Cocoon + type = 'item', + dropped_from = { name = 'Gullycampa (K-10)' } + } } + } + }, { + id = 1490, --Distended Chigoe Abdomen + type = 'key item', + dropped_from = { name = 'Tunga, Timed (K-10)' } + }, { + id = 1489, --Bulbous crawler cocoon + type = 'key item', + dropped_from = { + name = 'Blazing Eruca, Forced (J-10)', + pops = { { + id = 3073, --Eruca Egg + type = 'item', + dropped_from = { name = 'Ignis Eruca (J-10)' } + } } + } + } } } diff --git a/addons/EmpyPopTracker/nms/kukulkan.lua b/addons/EmpyPopTracker/nms/kukulkan.lua index 5b1ddcc0b7..002a1926bc 100644 --- a/addons/EmpyPopTracker/nms/kukulkan.lua +++ b/addons/EmpyPopTracker/nms/kukulkan.lua @@ -27,40 +27,39 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = "Kukulkan", - bg_url = 'https://www.bg-wiki.com/bg/Kukulkan', - pops = { { - id = 1466, --Mucid Ahriman Eyeball - type = "key item", - dropped_from = { - name = "Arimaspi, Forced (K-6)", - pops = { { - id = 2913, --Clouded Lens - type = "item", - dropped_from = { name = "Deep Eye (K-6/K-7)" } - } } - } - }, { - id = 1464, --Tattered Hippogryph Wing - type = "key item", - dropped_from = { - name = "Alkonost, Forced (H-6)", - pops = { { - id = 2912, --Giant Bugard Tusk - type = "item", - dropped_from = { name = "Ypotryll (I-7)" } - } } - } - }, { - id = 1465, --Cracked Wivre Horn - type = "key item", - dropped_from = { - name = "Keratyrannos, Forced (G-6)", - pops = { { - id = 2910, --Armored Dragonhorn - type = "item", - dropped_from = { name = "Mesa Wivre (G-6)" } - } } - } - } } + name = 'Kukulkan', + pops = { { + id = 1466, --Mucid Ahriman Eyeball + type = 'key item', + dropped_from = { + name = 'Arimaspi, Forced (K-6)', + pops = { { + id = 2913, --Clouded Lens + type = 'item', + dropped_from = { name = 'Deep Eye (K-6/K-7)' } + } } + } + }, { + id = 1464, --Tattered Hippogryph Wing + type = 'key item', + dropped_from = { + name = 'Alkonost, Forced (H-6)', + pops = { { + id = 2912, --Giant Bugard Tusk + type = 'item', + dropped_from = { name = 'Ypotryll (I-7)' } + } } + } + }, { + id = 1465, --Cracked Wivre Horn + type = 'key item', + dropped_from = { + name = 'Keratyrannos, Forced (G-6)', + pops = { { + id = 2910, --Armored Dragonhorn + type = 'item', + dropped_from = { name = 'Mesa Wivre (G-6)' } + } } + } + } } } diff --git a/addons/EmpyPopTracker/nms/orthrus.lua b/addons/EmpyPopTracker/nms/orthrus.lua index ea7a0d8172..0a48cea5b0 100644 --- a/addons/EmpyPopTracker/nms/orthrus.lua +++ b/addons/EmpyPopTracker/nms/orthrus.lua @@ -27,32 +27,31 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = "Orthrus", - bg_url = 'https://www.bg-wiki.com/bg/Orthrus', - pops = { { - id = 1520, --Steaming cerberus tongue - type = "key item", + name = 'Orthrus', + pops = { { + id = 1520, --Steaming cerberus tongue + type = 'key item', + dropped_from = { + name = 'Amarok, Forced (E-6)', + pops = { { + id = 3231, --Sharabha Hide + type = 'item', dropped_from = { - name = "Amarok, Forced (E-6)", - pops = { { - id = 3231, --Sharabha Hide - type = "item", - dropped_from = { - name = "Sharabha, Forced (G-5)", - pops = { { - id = 3237, - dropped_from = { name = "Dune Manticore (F-5/F-6)" } - } } - } - }, { - id = 3232, --Tiger King Hide - type = "item", - dropped_from = { name = "Ansherekh, Timed (F-8/G-8)" } - }, { - id = 3238, --H.Q. Dhalmel Hide - type = "item", - dropped_from = { name = "Camelopardalis (F-7/G-7)" } - } } + name = 'Sharabha, Forced (G-5)', + pops = { { + id = 3237, + dropped_from = { name = 'Dune Manticore (F-5/F-6)' } + } } } - } } + }, { + id = 3232, --Tiger King Hide + type = 'item', + dropped_from = { name = 'Ansherekh, Timed (F-8/G-8)' } + }, { + id = 3238, --H.Q. Dhalmel Hide + type = 'item', + dropped_from = { name = 'Camelopardalis (F-7/G-7)' } + } } + } + } } } diff --git a/addons/EmpyPopTracker/nms/sedna.lua b/addons/EmpyPopTracker/nms/sedna.lua index de3f84d1cb..d6b20f9886 100644 --- a/addons/EmpyPopTracker/nms/sedna.lua +++ b/addons/EmpyPopTracker/nms/sedna.lua @@ -27,22 +27,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = "Sedna", - bg_url = 'https://www.bg-wiki.com/bg/Sedna', - pops = { { - id = 1512, --Shimmering Pugil Scale - type = "key item", - dropped_from = { name = "Hrosshvalur, Timed (J-6)" } - }, { - id = 1511, --Glossy Sea Monk Sucker - type = "key item", - dropped_from = { - name = "Iku-Turso, Forced (J-7)", - pops = { { - id = 3100, --Moonbeam Clam - type = "item", - dropped_from = { name = "Jasconius (I-7/J-7)" } - } } - } - } } + name = 'Sedna', + pops = { { + id = 1512, --Shimmering Pugil Scale + type = 'key item', + dropped_from = { name = 'Hrosshvalur, Timed (J-6)' } + }, { + id = 1511, --Glossy Sea Monk Sucker + type = 'key item', + dropped_from = { + name = 'Iku-Turso, Forced (J-7)', + pops = { { + id = 3100, --Moonbeam Clam + type = 'item', + dropped_from = { name = 'Jasconius (I-7/J-7)' } + } } + } + } } } diff --git a/addons/EmpyPopTracker/nms/sobek.lua b/addons/EmpyPopTracker/nms/sobek.lua index 570fd9d51e..f6e22e968a 100644 --- a/addons/EmpyPopTracker/nms/sobek.lua +++ b/addons/EmpyPopTracker/nms/sobek.lua @@ -27,33 +27,32 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = "Sobek", - bg_url = 'https://www.bg-wiki.com/bg/Sobek', - pops = { { - id = 1500, --Molted Peiste Skin - type = "key item", - dropped_from = { name = "Gukumatz, Timed (J-11)" } - }, { - id = 1498, --Bloodstained Bugard Fang - type = "key item", - dropped_from = { - name = "Minax Bugard, Forced (K-10)", - pops = { { - id = 3085, --Bewitching Tusk - type = "item", - dropped_from = { name = "Abyssobugard (J-10/K-11)" } - } } - } - }, { - id = 1499, --Gnarled Lizard Nail - type = "key item", - dropped_from = { - name = "Sirrush, Forced (I-11)", - pops = { { - id = 3086, --Molt Scraps - type = "item", - dropped_from = { name = "Dusk Lizard (J-11)" } - } } - } - } } + name = 'Sobek', + pops = { { + id = 1500, --Molted Peiste Skin + type = 'key item', + dropped_from = { name = 'Gukumatz, Timed (J-11)' } + }, { + id = 1498, --Bloodstained Bugard Fang + type = 'key item', + dropped_from = { + name = 'Minax Bugard, Forced (K-10)', + pops = { { + id = 3085, --Bewitching Tusk + type = 'item', + dropped_from = { name = 'Abyssobugard (J-10/K-11)' } + } } + } + }, { + id = 1499, --Gnarled Lizard Nail + type = 'key item', + dropped_from = { + name = 'Sirrush, Forced (I-11)', + pops = { { + id = 3086, --Molt Scraps + type = 'item', + dropped_from = { name = 'Dusk Lizard (J-11)' } + } } + } + } } } diff --git a/addons/EmpyPopTracker/nms/ulhuadshi.lua b/addons/EmpyPopTracker/nms/ulhuadshi.lua index 3d22113963..ad63f9168e 100644 --- a/addons/EmpyPopTracker/nms/ulhuadshi.lua +++ b/addons/EmpyPopTracker/nms/ulhuadshi.lua @@ -27,22 +27,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = "Ulhuadshi", - bg_url = 'https://www.bg-wiki.com/bg/Ulhuadshi', - pops = { { - id = 1492, --Shriveled Hecteyes Stalk - type = "key item", - dropped_from = { name = "Amun, Timed (H-8/I-9)" } - }, { - id = 1491, --Mucid Worm Segment - type = "key item", - dropped_from = { - name = "Pallid Percy, Forced (J-7)", - pops = { { - id = 3074, --Blanched Silver - type = "item", - dropped_from = { name = "Entozoon (J-7)" } - } } - } - } } + name = 'Ulhuadshi', + pops = { { + id = 1492, --Shriveled Hecteyes Stalk + type = 'key item', + dropped_from = { name = 'Amun, Timed (H-8/I-9)' } + }, { + id = 1491, --Mucid Worm Segment + type = 'key item', + dropped_from = { + name = 'Pallid Percy, Forced (J-7)', + pops = { { + id = 3074, --Blanched Silver + type = 'item', + dropped_from = { name = 'Entozoon (J-7)' } + } } + } + } } } From 5eaf5b0bf6e7b91aaf2b5b97910f36c31c2f50b1 Mon Sep 17 00:00:00 2001 From: Dean James Date: Sun, 9 Feb 2020 13:49:40 +0000 Subject: [PATCH 0340/1002] Switched to pattern matching. Reverted indents to 4 spaces. Commands now handle different cases. --- addons/EmpyPopTracker/EmpyPopTracker.lua | 349 +++++++++++---------- addons/EmpyPopTracker/README.md | 6 +- addons/EmpyPopTracker/nms/README.md | 67 ++-- addons/EmpyPopTracker/nms/alfard.lua | 52 +-- addons/EmpyPopTracker/nms/apademak.lua | 50 +-- addons/EmpyPopTracker/nms/azdaja.lua | 12 +- addons/EmpyPopTracker/nms/briareus.lua | 70 ++--- addons/EmpyPopTracker/nms/bukhis.lua | 56 ++-- addons/EmpyPopTracker/nms/carabosse.lua | 48 +-- addons/EmpyPopTracker/nms/chloris.lua | 152 ++++----- addons/EmpyPopTracker/nms/cirein-croin.lua | 34 +- addons/EmpyPopTracker/nms/dragua.lua | 12 +- addons/EmpyPopTracker/nms/glavoid.lua | 96 +++--- addons/EmpyPopTracker/nms/index.lua | 36 +-- addons/EmpyPopTracker/nms/isgebind.lua | 12 +- addons/EmpyPopTracker/nms/itzpapalotl.lua | 56 ++-- addons/EmpyPopTracker/nms/kukulkan.lua | 70 ++--- addons/EmpyPopTracker/nms/orthrus.lua | 50 +-- addons/EmpyPopTracker/nms/sedna.lua | 34 +- addons/EmpyPopTracker/nms/sobek.lua | 56 ++-- addons/EmpyPopTracker/nms/ulhuadshi.lua | 34 +- 21 files changed, 678 insertions(+), 674 deletions(-) diff --git a/addons/EmpyPopTracker/EmpyPopTracker.lua b/addons/EmpyPopTracker/EmpyPopTracker.lua index cb11451aa2..a87bbf5d20 100644 --- a/addons/EmpyPopTracker/EmpyPopTracker.lua +++ b/addons/EmpyPopTracker/EmpyPopTracker.lua @@ -26,7 +26,7 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] -_addon.name = "Empy Pop Tracker" +_addon.name = 'Empy Pop Tracker' _addon.author = 'Dean James (Xurion of Bismarck)' _addon.commands = { 'ept', 'empypoptracker' } _addon.version = '2.0.0' @@ -68,256 +68,259 @@ colors.warning = '\\cs(255,170,0)' colors.close = '\\cr' function owns_item(id, items) - for _, bag in ipairs(items) do - for _, item in ipairs(bag) do - if item.id == id then - return true - end + for _, bag in ipairs(items) do + for _, item in ipairs(bag) do + if item.id == id then + return true + end + end end - end - return false + return false end function owns_key_item(id, items) - local owned = false + local owned = false - for _, item_id in pairs(items) do - if item_id == id then - owned = true - break + for _, item_id in pairs(items) do + if item_id == id then + owned = true + break + end end - end - return owned + return owned end function item_treasure_pool_count(id, treasure) - local count = 0 + local count = 0 - for _, item in pairs(treasure) do - if item.item_id == id then - count = count + 1 + for _, item in pairs(treasure) do + if item.item_id == id then + count = count + 1 + end end - end - return count + return count end function ucwords(str) - local result = string.gsub(str, '(%a)([%w_\']*)', function(first, rest) - return first:upper() .. rest:lower() - end) + local result = string.gsub(str, '(%a)([%w_\']*)', function(first, rest) + return first:upper() .. rest:lower() + end) - return result + return result end function get_indent(depth) - return string.rep(' ', depth) + return string.rep(' ', depth) end function generate_text(data, key_items, items, depth) - local text = depth == 1 and data.name or '' - for _, pop in pairs(data.pops) do - local resource - local item_scope - local owns_pop - local in_pool_count = 0 - local item_identifier = '' - - if pop.type == 'key item' then - resource = res.key_items[pop.id] - owns_pop = owns_key_item(pop.id, key_items) - item_identifier = 'Ж ' - else - resource = res.items[pop.id] - owns_pop = owns_item(pop.id, items) - in_pool_count = item_treasure_pool_count(pop.id, items.treasure) - end - - local pop_name = 'Unknown pop' - if resource then - pop_name = ucwords(resource.name) - end - - --separator line for each top-level mob - if depth == 1 then - text = text .. '\n' - end - - local item_colour - if owns_pop then - item_colour = colors.success - else - item_colour = colors.danger - end - - local pool_notification = '' - if in_pool_count > 0 then - pool_notification = colors.warning .. ' [' .. in_pool_count .. ']' .. colors.close - end - text = text .. '\n' .. get_indent(depth) .. pop.dropped_from.name .. '\n' .. get_indent(depth) .. ' >> ' .. item_colour .. item_identifier .. pop_name .. colors.close .. pool_notification - if pop.dropped_from.pops then - text = text .. generate_text(pop.dropped_from, key_items, items, depth + 1) + local text = depth == 1 and data.name or '' + for _, pop in pairs(data.pops) do + local resource + local item_scope + local owns_pop + local in_pool_count = 0 + local item_identifier = '' + + if pop.type == 'key item' then + resource = res.key_items[pop.id] + owns_pop = owns_key_item(pop.id, key_items) + item_identifier = 'Ж ' + else + resource = res.items[pop.id] + owns_pop = owns_item(pop.id, items) + in_pool_count = item_treasure_pool_count(pop.id, items.treasure) + end + + local pop_name = 'Unknown pop' + if resource then + pop_name = ucwords(resource.name) + end + + --separator line for each top-level mob + if depth == 1 then + text = text .. '\n' + end + + local item_colour + if owns_pop then + item_colour = colors.success + else + item_colour = colors.danger + end + + local pool_notification = '' + if in_pool_count > 0 then + pool_notification = colors.warning .. ' [' .. in_pool_count .. ']' .. colors.close + end + text = text .. '\n' .. get_indent(depth) .. pop.dropped_from.name .. '\n' .. get_indent(depth) .. ' >> ' .. item_colour .. item_identifier .. pop_name .. colors.close .. pool_notification + if pop.dropped_from.pops then + text = text .. generate_text(pop.dropped_from, key_items, items, depth + 1) + end end - end - return text + return text end EmpyPopTracker.generate_info = function(nm, key_items, items) - local nm_type = type(nm) - local info = { - has_all_kis = true, - text = '' - } - - if nm.pops then - for _, key_item_data in pairs(nm.pops) do - local has_pop_ki = owns_key_item(key_item_data.id, key_items) - - if not has_pop_ki then - info.has_all_kis = false - end + local info = { + has_all_kis = true, + text = '' + } + + if nm.pops then + for _, key_item_data in pairs(nm.pops) do + local has_pop_ki = owns_key_item(key_item_data.id, key_items) + + if not has_pop_ki then + info.has_all_kis = false + end + end end - end - info.text = generate_text(nm, key_items, items, 1) + info.text = generate_text(nm, key_items, items, 1) - return info + return info end -function find_nms(query) - local matching_nms = {} - local lower_query = query:lower() - for _, nm in pairs(nm_data) do - local result = string.match(nm.name:lower(), '(.*' .. lower_query .. '.*)') - if result then - table.insert(matching_nms, result) +function find_nms(pattern) + local matching_nms = {} + local lower_pattern = pattern:lower() + for _, nm in pairs(nm_data) do + local nm_name = nm.name:lower() + local result = windower.wc_match(nm_name, lower_pattern) + if result then + table.insert(matching_nms, nm_name) + end end - end - return matching_nms + + return matching_nms end windower.register_event('addon command', function(command, ...) - if commands[command] then - commands[command](...) - else - commands.help() - end + command = command and command:lower() or 'help' + + if commands[command] then + commands[command](...) + else + commands.help() + end end) commands = {} commands.track = function(...) - local args = {...} - local nm_name = args[1] - local matching_nm_names = find_nms(nm_name) - - if #matching_nm_names == 0 then - windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, 'Unable to find a NM using: "' .. nm_name .. '"') - elseif #matching_nm_names > 1 then - windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '"' .. nm_name .. '" matches ' .. #matching_nm_names .. ' NMs. Please be more explicit:') - for key, matching_file_name in pairs(matching_nm_names) do - windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, ' Match ' .. key .. ': ' .. ucwords(matching_file_name)) + local args = {...} + local nm_search_pattern = args[1] + local matching_nm_names = find_nms(nm_search_pattern) + + if #matching_nm_names == 0 then + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, 'Unable to find a NM using: "' .. nm_search_pattern .. '"') + elseif #matching_nm_names > 1 then + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '"' .. nm_search_pattern .. '" matches ' .. #matching_nm_names .. ' NMs. Please be more explicit:') + for key, matching_file_name in pairs(matching_nm_names) do + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, ' Match ' .. key .. ': ' .. ucwords(matching_file_name)) + end + else + active = true + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, 'Now tracking: ' .. ucwords(matching_nm_names[1])) + EmpyPopTracker.settings.tracking = matching_nm_names[1] + EmpyPopTracker.update() + commands.show() end - else - active = true - windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, 'Now tracking: ' .. ucwords(matching_nm_names[1])) - EmpyPopTracker.settings.tracking = matching_nm_names[1] - EmpyPopTracker.update() - commands.show() - end end commands.t = commands.track commands.hide = function() - active = false - EmpyPopTracker.text:visible(false) - EmpyPopTracker.settings.visible = false - EmpyPopTracker.settings:save() + active = false + EmpyPopTracker.text:visible(false) + EmpyPopTracker.settings.visible = false + EmpyPopTracker.settings:save() end commands.show = function() - active = true - EmpyPopTracker.text:visible(true) - EmpyPopTracker.settings.visible = true - EmpyPopTracker.settings:save() - EmpyPopTracker.update() + active = true + EmpyPopTracker.text:visible(true) + EmpyPopTracker.settings.visible = true + EmpyPopTracker.settings:save() + EmpyPopTracker.update() end commands.help = function() - windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '---Empy Pop Tracker---') - windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, 'Available commands:') - windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '//ept track briareus - tracks Briareus pops (partial names such as apadem work too!)') - windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '//ept hide - hides the UI') - windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '//ept show - shows the UI') - windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '//ept list - lists all trackable NMs') - windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '//ept help - displays this help') + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '---Empy Pop Tracker---') + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, 'Available commands:') + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '//ept track briareus - tracks Briareus pops (search patterns such as apadem* work too!)') + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '//ept hide - hides the UI') + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '//ept show - shows the UI') + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '//ept list - lists all trackable NMs') + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '//ept help - displays this help') end commands.list = function() - windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '---Empy Pop Tracker---') - windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, 'Trackable NMs:') - for _, nm in pairs(nm_data) do - windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, ucwords(nm.name)) - end + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '---Empy Pop Tracker---') + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, 'Trackable NMs:') + for _, nm in pairs(nm_data) do + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, ucwords(nm.name)) + end end commands.bg = function() - local tracking_nm = nm_data[EmpyPopTracker.settings.tracking] - local url = 'https://www.bg-wiki.com/bg/' .. tracking_nm.name - windower.open_url(url) + local tracking_nm = nm_data[EmpyPopTracker.settings.tracking] + local url = 'https://www.bg-wiki.com/bg/' .. tracking_nm.name + windower.open_url(url) end EmpyPopTracker.update = function() - local key_items = windower.ffxi.get_key_items() - local items = windower.ffxi.get_items() - local tracked_nm_data = nm_data[EmpyPopTracker.settings.tracking] - local generated_info = EmpyPopTracker.generate_info(tracked_nm_data, key_items, items) - EmpyPopTracker.text:text(generated_info.text) - if generated_info.has_all_kis then - EmpyPopTracker.text:bg_color(0, 75, 0) - else - EmpyPopTracker.text:bg_color(0, 0, 0) - end - if EmpyPopTracker.settings.visible then - EmpyPopTracker.text:visible(true) - end + local key_items = windower.ffxi.get_key_items() + local items = windower.ffxi.get_items() + local tracked_nm_data = nm_data[EmpyPopTracker.settings.tracking] + local generated_info = EmpyPopTracker.generate_info(tracked_nm_data, key_items, items) + EmpyPopTracker.text:text(generated_info.text) + if generated_info.has_all_kis then + EmpyPopTracker.text:bg_color(0, 75, 0) + else + EmpyPopTracker.text:bg_color(0, 0, 0) + end + if EmpyPopTracker.settings.visible then + EmpyPopTracker.text:visible(true) + end end windower.register_event('load', function() - if windower.ffxi.get_info().logged_in and EmpyPopTracker.settings.visible then - active = true - EmpyPopTracker.update() - end + if windower.ffxi.get_info().logged_in and EmpyPopTracker.settings.visible then + active = true + EmpyPopTracker.update() + end end) windower.register_event('add item', 'remove item', function() - if active then - EmpyPopTracker.update() - end + if active then + EmpyPopTracker.update() + end end) windower.register_event('incoming chunk', function(id) - --0x055: KI update - --0x0D2: Treasure pool addition - --0x0D3: Treasure pool lot/drop - if active and id == 0x055 or id == 0x0D2 or id == 0x0D3 then - EmpyPopTracker.update() - end + --0x055: KI update + --0x0D2: Treasure pool addition + --0x0D3: Treasure pool lot/drop + if active and id == 0x055 or id == 0x0D2 or id == 0x0D3 then + EmpyPopTracker.update() + end end) windower.register_event('login', function() - if EmpyPopTracker.settings.visible then - EmpyPopTracker.text:visible(true) - active = true - end + if EmpyPopTracker.settings.visible then + EmpyPopTracker.text:visible(true) + active = true + end end) windower.register_event('logout', function() - EmpyPopTracker.text:visible(false) - active = false + EmpyPopTracker.text:visible(false) + active = false end) return EmpyPopTracker diff --git a/addons/EmpyPopTracker/README.md b/addons/EmpyPopTracker/README.md index 3631de1ecd..f674c3c942 100644 --- a/addons/EmpyPopTracker/README.md +++ b/addons/EmpyPopTracker/README.md @@ -1,4 +1,4 @@ -# FFXI Empy Pop Tracker +# FFXI Empyrean Pop Tracker An FFXI Windower 4 addon that tracks items and key items for popping Empyrean NMs in Abyssea, such as Briareus, Apademak and Sobek. @@ -14,9 +14,9 @@ Key items are identified by the Zhe (Ж) character. Treasure pool counts for pop `//ept track glavoid` tracks Glavoid pop items/key items. -You can also track an NM by typing part of the name, because fuck having to remember how to spell Itzpapalotl: +You can also track an NM by using a wildcard pattern, because fuck having to remember how to spell Itzpapalotl: -`//ept track itz` +`//ept track itz*` For a full list of trackable NMs, see the nms directory or use the `list` command (see below). diff --git a/addons/EmpyPopTracker/nms/README.md b/addons/EmpyPopTracker/nms/README.md index 720d0a7d4d..d9e9278bd9 100644 --- a/addons/EmpyPopTracker/nms/README.md +++ b/addons/EmpyPopTracker/nms/README.md @@ -14,12 +14,12 @@ A simple example of the above would be: ```lua { - name = 'Azdaja', - pops = { { - id = 1531, --Vacant Bugard Eye - type = 'key item', - dropped_from = { name = 'Deelgeed, Timed (F-9/F-10)' } - } } + name = 'Azdaja', + pops = { { + id = 1531, --Vacant Bugard Eye + type = 'key item', + dropped_from = { name = 'Deelgeed, Timed (F-9/F-10)' } + } } } ``` @@ -27,37 +27,38 @@ A larger example with multiple nested entites: ```lua { - name = 'Bukhis', - pops = { { - id = 1508, --Ingrown Taurus Nail - type = 'key item', - dropped_from = { - name = 'Khalkotaur, Forced (F-4)', - pops = { { - id = 3098, --Gnarled Taurus Horn - type = 'item', - dropped_from = { name = 'Aestutaur (G-9/G-10)' } - } } + name = 'Bukhis', + pops = { { + id = 1508, --Ingrown Taurus Nail + type = 'key item', + dropped_from = { + name = 'Khalkotaur, Forced (F-4)', + pops = { { + id = 3098, --Gnarled Taurus Horn + type = 'item', + dropped_from = { name = 'Aestutaur (G-9/G-10)' } + } } + } }, { - id = 1509, --Ossified Gargouille Hand - type = 'key item', - dropped_from = { - name = 'Quasimodo, Forced (F-4)', - pops = { { - id = 3099, --Gargouille Stone - type = 'item', - dropped_from = { - name = 'Gruesome Gargouille (F-10/G-10)' - } - } } - } + id = 1509, --Ossified Gargouille Hand + type = 'key item', + dropped_from = { + name = 'Quasimodo, Forced (F-4)', + pops = { { + id = 3099, --Gargouille Stone + type = 'item', + dropped_from = { + name = 'Gruesome Gargouille (F-10/G-10)' + } + } } + } }, { - id = 1510, --Imbrued Vampyr Fang - type = 'key item', - dropped_from = { name = 'Lord Varney, Timed (G-10/H-10)' } + id = 1510, --Imbrued Vampyr Fang + type = 'key item', + dropped_from = { name = 'Lord Varney, Timed (G-10/H-10)' } } } - } } + ``` The main addon file requires the index.lua file which in turn is responsible for requiring and returning data for each nm. diff --git a/addons/EmpyPopTracker/nms/alfard.lua b/addons/EmpyPopTracker/nms/alfard.lua index 689d4ddcc6..ee492fd252 100644 --- a/addons/EmpyPopTracker/nms/alfard.lua +++ b/addons/EmpyPopTracker/nms/alfard.lua @@ -27,32 +27,32 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = 'Alfard', - pops = { { - id = 1530, --Venomous hydra fang - type = 'key item', - dropped_from = { - name = 'Ningishzida, Forced (I-7/I-8)', - pops = { { - id = 3262, --Jaculus Wing - type = 'item', - dropped_from = { name = 'Jaculus, Timed (I-8)' } - }, { - id = 3261, --Minaruja Skull - type = 'item', + name = 'Alfard', + pops = { { + id = 1530, --Venomous hydra fang + type = 'key item', dropped_from = { - name = 'Minaruja, Forced (I-10)', - pops = { { - id = 3267, --Pursuer's Wing - type = 'item', - dropped_from = { name = 'Faunus Wyvern (I-9)' } - } } + name = 'Ningishzida, Forced (I-7/I-8)', + pops = { { + id = 3262, --Jaculus Wing + type = 'item', + dropped_from = { name = 'Jaculus, Timed (I-8)' } + }, { + id = 3261, --Minaruja Skull + type = 'item', + dropped_from = { + name = 'Minaruja, Forced (I-10)', + pops = { { + id = 3267, --Pursuer's Wing + type = 'item', + dropped_from = { name = 'Faunus Wyvern (I-9)' } + } } + } + }, { + id = 3268, --High-Quality Wivre Hide + type = 'item', + dropped_from = { name = 'Glade Wivre (I-8)' } + } } } - }, { - id = 3268, --High-Quality Wivre Hide - type = 'item', - dropped_from = { name = 'Glade Wivre (I-8)' } - } } - } - } } + } } } diff --git a/addons/EmpyPopTracker/nms/apademak.lua b/addons/EmpyPopTracker/nms/apademak.lua index 63315f5683..4ecec8aecc 100644 --- a/addons/EmpyPopTracker/nms/apademak.lua +++ b/addons/EmpyPopTracker/nms/apademak.lua @@ -27,31 +27,31 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = 'Apademak', - pops = { { - id = 1525, --Torn Khimaira Wing - type = 'key item', - dropped_from = { - name = 'Dhorme Khimaira, Forced (F-7)', - pops = { { - id = 3246, --Snow God Core - type = 'item', + name = 'Apademak', + pops = { { + id = 1525, --Torn Khimaira Wing + type = 'key item', dropped_from = { - name = 'Upas-Kamuy, Forced (G-5)', - pops = { { - id = 3252, --Gelid Arm - dropped_from = { name = 'Snowflake (G-5)' } - } } + name = 'Dhorme Khimaira, Forced (F-7)', + pops = { { + id = 3246, --Snow God Core + type = 'item', + dropped_from = { + name = 'Upas-Kamuy, Forced (G-5)', + pops = { { + id = 3252, --Gelid Arm + dropped_from = { name = 'Snowflake (G-5)' } + } } + } + }, { + id = 3247, --Sisyphus Fragment + type = 'item', + dropped_from = { name = 'Sisyphus, Timed (F-6/G-6)' } + }, { + id = 3253, --High-quality marid hide + type = 'item', + dropped_from = { name = 'Olyphant (F-6)' } + } } } - }, { - id = 3247, --Sisyphus Fragment - type = 'item', - dropped_from = { name = 'Sisyphus, Timed (F-6/G-6)' } - }, { - id = 3253, --High-quality marid hide - type = 'item', - dropped_from = { name = 'Olyphant (F-6)' } - } } - } - } } + } } } diff --git a/addons/EmpyPopTracker/nms/azdaja.lua b/addons/EmpyPopTracker/nms/azdaja.lua index b6eb58f1d4..cb06f668d9 100644 --- a/addons/EmpyPopTracker/nms/azdaja.lua +++ b/addons/EmpyPopTracker/nms/azdaja.lua @@ -27,10 +27,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = 'Azdaja', - pops = { { - id = 1531, --Vacant Bugard Eye - type = 'key item', - dropped_from = { name = 'Deelgeed, Timed (F-9/F-10)' } - } } + name = 'Azdaja', + pops = { { + id = 1531, --Vacant Bugard Eye + type = 'key item', + dropped_from = { name = 'Deelgeed, Timed (F-9/F-10)' } + } } } diff --git a/addons/EmpyPopTracker/nms/briareus.lua b/addons/EmpyPopTracker/nms/briareus.lua index 553350cbd4..7b2e68d4b7 100644 --- a/addons/EmpyPopTracker/nms/briareus.lua +++ b/addons/EmpyPopTracker/nms/briareus.lua @@ -27,39 +27,39 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = 'Briareus', - pops = { { - id = 1482, --Dented Gigas Shield - type = 'key item', - dropped_from = { - name = 'Adamastor, Forced (C-4)', - pops = { { - id = 2894, --Trophy Shield - type = 'item', - dropped_from = { name = 'Bathyal Gigas (C-5/D-5)' } - } } - } - }, { - id = 1484, --Severed Gigas Collar - type = 'key item', - dropped_from = { - name = 'Grandgousier, Forced (F-10)', - pops = { { - id = 2896, --Massive Armband - type = 'item', - dropped_from = { name = 'Demersal Gigas (E-9/F-9)' } - } } - } - }, { - id = 1483, --Warped Gigas Armband - type = 'key item', - dropped_from = { - name = 'Pantagruel, Forced (F-7)', - pops = { { - id = 2895, --Oversized Sock - type = 'item', - dropped_from = { name = 'Hadal Gigas (F-6/F-7)' } - } } - } - } } + name = 'Briareus', + pops = { { + id = 1482, --Dented Gigas Shield + type = 'key item', + dropped_from = { + name = 'Adamastor, Forced (C-4)', + pops = { { + id = 2894, --Trophy Shield + type = 'item', + dropped_from = { name = 'Bathyal Gigas (C-5/D-5)' } + } } + } + }, { + id = 1484, --Severed Gigas Collar + type = 'key item', + dropped_from = { + name = 'Grandgousier, Forced (F-10)', + pops = { { + id = 2896, --Massive Armband + type = 'item', + dropped_from = { name = 'Demersal Gigas (E-9/F-9)' } + } } + } + }, { + id = 1483, --Warped Gigas Armband + type = 'key item', + dropped_from = { + name = 'Pantagruel, Forced (F-7)', + pops = { { + id = 2895, --Oversized Sock + type = 'item', + dropped_from = { name = 'Hadal Gigas (F-6/F-7)' } + } } + } + } } } diff --git a/addons/EmpyPopTracker/nms/bukhis.lua b/addons/EmpyPopTracker/nms/bukhis.lua index 019864b732..b1926152a3 100644 --- a/addons/EmpyPopTracker/nms/bukhis.lua +++ b/addons/EmpyPopTracker/nms/bukhis.lua @@ -27,34 +27,34 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = 'Bukhis', - pops = { { - id = 1508, --Ingrown Taurus Nail - type = 'key item', - dropped_from = { - name = 'Khalkotaur, Forced (F-4)', - pops = { { - id = 3098, --Gnarled Taurus Horn - type = 'item', - dropped_from = { name = 'Aestutaur (G-9/G-10)' } - } } - } - }, { - id = 1509, --Ossified Gargouille Hand - type = 'key item', - dropped_from = { - name = 'Quasimodo, Forced (F-4)', - pops = { { - id = 3099, --Gargouille Stone - type = 'item', + name = 'Bukhis', + pops = { { + id = 1508, --Ingrown Taurus Nail + type = 'key item', dropped_from = { - name = 'Gruesome Gargouille (F-10/G-10)' + name = 'Khalkotaur, Forced (F-4)', + pops = { { + id = 3098, --Gnarled Taurus Horn + type = 'item', + dropped_from = { name = 'Aestutaur (G-9/G-10)' } + } } } - } } - } - }, { - id = 1510, --Imbrued Vampyr Fang - type = 'key item', - dropped_from = { name = 'Lord Varney, Timed (G-10/H-10)' } - } } + }, { + id = 1509, --Ossified Gargouille Hand + type = 'key item', + dropped_from = { + name = 'Quasimodo, Forced (F-4)', + pops = { { + id = 3099, --Gargouille Stone + type = 'item', + dropped_from = { + name = 'Gruesome Gargouille (F-10/G-10)' + } + } } + } + }, { + id = 1510, --Imbrued Vampyr Fang + type = 'key item', + dropped_from = { name = 'Lord Varney, Timed (G-10/H-10)' } + } } } diff --git a/addons/EmpyPopTracker/nms/carabosse.lua b/addons/EmpyPopTracker/nms/carabosse.lua index 97b0c9c5e7..ad9aa0079c 100644 --- a/addons/EmpyPopTracker/nms/carabosse.lua +++ b/addons/EmpyPopTracker/nms/carabosse.lua @@ -27,28 +27,28 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = 'Carabosse', - pops = { { - id = 1485, --Pellucid Fly Eye - type = 'key item', - dropped_from = { - name = 'La Theine Liege, Forced (I-7)', - pops = { { - id = 2897, --Transparent Insect Wing - type = 'item', - dropped_from = { name = 'Plateau Glider (H-7)' } - } } - } - }, { - id = 1486, --Shimmering Pixie Pinion - type = 'key item', - dropped_from = { - name = 'Baba Yaga, Forced (H-7)', - pops = { { - id = 2898, --Piceous Scale - type = 'item', - dropped_from = { name = 'Farfadet (H-7)' } - } } - } - } } + name = 'Carabosse', + pops = { { + id = 1485, --Pellucid Fly Eye + type = 'key item', + dropped_from = { + name = 'La Theine Liege, Forced (I-7)', + pops = { { + id = 2897, --Transparent Insect Wing + type = 'item', + dropped_from = { name = 'Plateau Glider (H-7)' } + } } + } + }, { + id = 1486, --Shimmering Pixie Pinion + type = 'key item', + dropped_from = { + name = 'Baba Yaga, Forced (H-7)', + pops = { { + id = 2898, --Piceous Scale + type = 'item', + dropped_from = { name = 'Farfadet (H-7)' } + } } + } + } } } diff --git a/addons/EmpyPopTracker/nms/chloris.lua b/addons/EmpyPopTracker/nms/chloris.lua index 78dbaeacc1..df7451eedb 100644 --- a/addons/EmpyPopTracker/nms/chloris.lua +++ b/addons/EmpyPopTracker/nms/chloris.lua @@ -27,87 +27,87 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = 'Chloris', - pops = { { - id = 1470, --Gory Scorpion Claw - type = 'key item', - dropped_from = { - name = 'Hedetet, Forced (F-7)', - pops = { { - id = 2921, --Venomous Scorpion Stinger - type = 'item', - dropped_from = { name = 'Canyon Scorpion (F-7)' } - }, { - id = 2948, --Acidic Humus - type = 'item', + name = 'Chloris', + pops = { { + id = 1470, --Gory Scorpion Claw + type = 'key item', dropped_from = { - name = 'Gancanagh, Forced (H-8)', - pops = { { - id = 2920, --Alkaline Humus - type = 'item', - dropped_from = { name = 'Pachypodium (H-8)' } - } } + name = 'Hedetet, Forced (F-7)', + pops = { { + id = 2921, --Venomous Scorpion Stinger + type = 'item', + dropped_from = { name = 'Canyon Scorpion (F-7)' } + }, { + id = 2948, --Acidic Humus + type = 'item', + dropped_from = { + name = 'Gancanagh, Forced (H-8)', + pops = { { + id = 2920, --Alkaline Humus + type = 'item', + dropped_from = { name = 'Pachypodium (H-8)' } + } } + } + } } } - } } - } - }, { - id = 1469, --Torn Bat Wing - type = 'key item', - dropped_from = { - name = 'Treble Noctules, Forced (I-9)', - pops = { { - id = 2919, --Bloody Fang - type = 'item', - dropped_from = { name = 'Blood Bat (I-9)' } - }, { - id = 2947, --Exorcised Skull - type = 'item', + }, { + id = 1469, --Torn Bat Wing + type = 'key item', dropped_from = { - name = 'Cannered Noz, Forced (F-6)', - pops = { { - id = 2918, --Baleful Skull - type = 'item', - dropped_from = { name = 'Caoineag (F-6)' } - } } + name = 'Treble Noctules, Forced (I-9)', + pops = { { + id = 2919, --Bloody Fang + type = 'item', + dropped_from = { name = 'Blood Bat (I-9)' } + }, { + id = 2947, --Exorcised Skull + type = 'item', + dropped_from = { + name = 'Cannered Noz, Forced (F-6)', + pops = { { + id = 2918, --Baleful Skull + type = 'item', + dropped_from = { name = 'Caoineag (F-6)' } + } } + } + } } } - } } - } - }, { - id = 1468, --Veinous Hecteyes Eyelid - type = 'key item', - dropped_from = { - name = 'Ophanim, Forced (G-9)', - pops = { { - id = 2946, --Tarnished Pincer - type = 'item', + }, { + id = 1468, --Veinous Hecteyes Eyelid + type = 'key item', dropped_from = { - name = 'Vetehinen, Forced (H-10)', - pops = { { - id = 2916, --High-quality Limule Pincer - type = 'item', - dropped_from = { name = 'Gulch Limule (H-10)' } - }, { - id = 2917, --Bloodshot Hecteye - type = 'item', - dropped_from = { name = 'Beholder (G-9)' } - }, { - id = 2945, --Shriveled Wing - type = 'item', - dropped_from = { - name = 'Halimede, Forced (G-12)', - pops = { { - id = 2915, --High-quality Clionid Wing + name = 'Ophanim, Forced (G-9)', + pops = { { + id = 2946, --Tarnished Pincer type = 'item', - dropped_from = { name = 'Gully Clionid (G-12)' } - } } - } - } } + dropped_from = { + name = 'Vetehinen, Forced (H-10)', + pops = { { + id = 2916, --High-quality Limule Pincer + type = 'item', + dropped_from = { name = 'Gulch Limule (H-10)' } + }, { + id = 2917, --Bloodshot Hecteye + type = 'item', + dropped_from = { name = 'Beholder (G-9)' } + }, { + id = 2945, --Shriveled Wing + type = 'item', + dropped_from = { + name = 'Halimede, Forced (G-12)', + pops = { { + id = 2915, --High-quality Clionid Wing + type = 'item', + dropped_from = { name = 'Gully Clionid (G-12)' } + } } + } + } } + } + } } } - } } - } - }, { - id = 1471, --Mossy Adamantoise Shell - type = 'key item', - dropped_from = { name = 'Chukwa, Timed (F-5)' } - } } + }, { + id = 1471, --Mossy Adamantoise Shell + type = 'key item', + dropped_from = { name = 'Chukwa, Timed (F-5)' } + } } } diff --git a/addons/EmpyPopTracker/nms/cirein-croin.lua b/addons/EmpyPopTracker/nms/cirein-croin.lua index 7a8a40af72..478c23ffea 100644 --- a/addons/EmpyPopTracker/nms/cirein-croin.lua +++ b/addons/EmpyPopTracker/nms/cirein-croin.lua @@ -27,21 +27,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = 'Cirein-croin', - pops = { { - id = 1504, --Glistening Orobon Liver - type = 'key item', - dropped_from = { - name = 'Cep-Kamuy, Forced (F-4)', - pops = { { - id = 3089, --Orobon Cheekmeat - type = 'item', - dropped_from = { name = 'Ancient Orobon (F-5)' } - } } - } - }, { - id = 1505, --Doffed Poroggo Hat - type = 'key item', - dropped_from = { name = 'Heqet, Timed (I-6)' } - } } + name = 'Cirein-croin', + pops = { { + id = 1504, --Glistening Orobon Liver + type = 'key item', + dropped_from = { + name = 'Cep-Kamuy, Forced (F-4)', + pops = { { + id = 3089, --Orobon Cheekmeat + type = 'item', + dropped_from = { name = 'Ancient Orobon (F-5)' } + } } + } + }, { + id = 1505, --Doffed Poroggo Hat + type = 'key item', + dropped_from = { name = 'Heqet, Timed (I-6)' } + } } } diff --git a/addons/EmpyPopTracker/nms/dragua.lua b/addons/EmpyPopTracker/nms/dragua.lua index aa841e0762..456a477b95 100644 --- a/addons/EmpyPopTracker/nms/dragua.lua +++ b/addons/EmpyPopTracker/nms/dragua.lua @@ -27,10 +27,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = 'Dragua', - pops = { { - id = 1521, --Bloodied Dragon Ear - type = 'key item', - dropped_from = { name = 'Hazhdiha, Timed (H-10)' } - } } + name = 'Dragua', + pops = { { + id = 1521, --Bloodied Dragon Ear + type = 'key item', + dropped_from = { name = 'Hazhdiha, Timed (H-10)' } + } } } diff --git a/addons/EmpyPopTracker/nms/glavoid.lua b/addons/EmpyPopTracker/nms/glavoid.lua index 3acf9b513d..9beca3c7d6 100644 --- a/addons/EmpyPopTracker/nms/glavoid.lua +++ b/addons/EmpyPopTracker/nms/glavoid.lua @@ -27,56 +27,56 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = 'Glavoid', - pops = { { - id = 1473, --Sodden Sandworm Husk - type = 'key item', - dropped_from = { name = 'Minhocao, Timed (I-6)' } - }, { - id = 1475, --Sticky Gnat Wing - type = 'key item', - dropped_from = { name = 'Adze, Timed (G-5)' } - }, { - id = 1472, --Fat-lined Cockatrice Skin - type = 'key item', - dropped_from = { - name = 'Alectryon (H-8)', - pops = { { - id = 2923, --Cockatrice Tailmeat - type = 'item', - dropped_from = { name = 'Cluckatrice (H-8)' } - }, { - id = 2949, --Quivering Eft Egg - type = 'item', + name = 'Glavoid', + pops = { { + id = 1473, --Sodden Sandworm Husk + type = 'key item', + dropped_from = { name = 'Minhocao, Timed (I-6)' } + }, { + id = 1475, --Sticky Gnat Wing + type = 'key item', + dropped_from = { name = 'Adze, Timed (G-5)' } + }, { + id = 1472, --Fat-lined Cockatrice Skin + type = 'key item', dropped_from = { - name = 'Abas, Forced (K-10)', - pops = { { - id = 2922, --Eft Egg - dropped_from = { name = 'Canyon Eft (J-10/J-11)' } - } } + name = 'Alectryon (H-8)', + pops = { { + id = 2923, --Cockatrice Tailmeat + type = 'item', + dropped_from = { name = 'Cluckatrice (H-8)' } + }, { + id = 2949, --Quivering Eft Egg + type = 'item', + dropped_from = { + name = 'Abas, Forced (K-10)', + pops = { { + id = 2922, --Eft Egg + dropped_from = { name = 'Canyon Eft (J-10/J-11)' } + } } + } + } } } - } } - } - }, { - id = 1474, --Luxuriant manticore mane - type = 'key item', - dropped_from = { - name = 'Muscaliet, Forced (J-6)', - pops = { { - id = 2925, --Resilient Mane - type = 'item', - dropped_from = { name = 'Hieracosphinx (J-6)' } - }, { - id = 2950, --Smooth Whisker - type = 'item', + }, { + id = 1474, --Luxuriant manticore mane + type = 'key item', dropped_from = { - name = 'Tefenet, Forced (G-6)', - pops = { { - id = 2924, --Shocking Whisker - dropped_from = { name = 'Jaguarundi (G-6)' } - } } + name = 'Muscaliet, Forced (J-6)', + pops = { { + id = 2925, --Resilient Mane + type = 'item', + dropped_from = { name = 'Hieracosphinx (J-6)' } + }, { + id = 2950, --Smooth Whisker + type = 'item', + dropped_from = { + name = 'Tefenet, Forced (G-6)', + pops = { { + id = 2924, --Shocking Whisker + dropped_from = { name = 'Jaguarundi (G-6)' } + } } + } + } } } - } } - } - } } + } } } diff --git a/addons/EmpyPopTracker/nms/index.lua b/addons/EmpyPopTracker/nms/index.lua index e10a91c5c5..9091a466a9 100644 --- a/addons/EmpyPopTracker/nms/index.lua +++ b/addons/EmpyPopTracker/nms/index.lua @@ -27,28 +27,28 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] local nms = { - 'alfard', - 'apademak', - 'azdaja', - 'briareus', - 'bukhis', - 'carabosse', - 'chloris', - 'cirein-croin', - 'dragua', - 'glavoid', - 'isgebind', - 'itzpapalotl', - 'kukulkan', - 'orthrus', - 'sedna', - 'sobek', - 'ulhuadshi' + 'alfard', + 'apademak', + 'azdaja', + 'briareus', + 'bukhis', + 'carabosse', + 'chloris', + 'cirein-croin', + 'dragua', + 'glavoid', + 'isgebind', + 'itzpapalotl', + 'kukulkan', + 'orthrus', + 'sedna', + 'sobek', + 'ulhuadshi' } nm_data = {} for _, nm in pairs(nms) do - nm_data[nm] = require('nms/' .. nm) + nm_data[nm] = require('nms/' .. nm) end return nm_data diff --git a/addons/EmpyPopTracker/nms/isgebind.lua b/addons/EmpyPopTracker/nms/isgebind.lua index 266c59e4e3..1fd4de0e63 100644 --- a/addons/EmpyPopTracker/nms/isgebind.lua +++ b/addons/EmpyPopTracker/nms/isgebind.lua @@ -27,10 +27,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = 'Isgebind', - pops = { { - id = 1526, --Begrimed Dragon Hide - type = 'key item', - dropped_from = { name = 'Kur, Timed (I-5/J-5)' } - } } + name = 'Isgebind', + pops = { { + id = 1526, --Begrimed Dragon Hide + type = 'key item', + dropped_from = { name = 'Kur, Timed (I-5/J-5)' } + } } } diff --git a/addons/EmpyPopTracker/nms/itzpapalotl.lua b/addons/EmpyPopTracker/nms/itzpapalotl.lua index 744677a52c..371d4ab8ca 100644 --- a/addons/EmpyPopTracker/nms/itzpapalotl.lua +++ b/addons/EmpyPopTracker/nms/itzpapalotl.lua @@ -27,32 +27,32 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = 'Itzpapalotl', - pops = { { - id = 1488, --Venomous Wamoura Feeler - type = 'key item', - dropped_from = { - name = 'Granite Borer, Forced (K-10)', - pops = { { - id = 3072, --Withered Cocoon - type = 'item', - dropped_from = { name = 'Gullycampa (K-10)' } - } } - } - }, { - id = 1490, --Distended Chigoe Abdomen - type = 'key item', - dropped_from = { name = 'Tunga, Timed (K-10)' } - }, { - id = 1489, --Bulbous crawler cocoon - type = 'key item', - dropped_from = { - name = 'Blazing Eruca, Forced (J-10)', - pops = { { - id = 3073, --Eruca Egg - type = 'item', - dropped_from = { name = 'Ignis Eruca (J-10)' } - } } - } - } } + name = 'Itzpapalotl', + pops = { { + id = 1488, --Venomous Wamoura Feeler + type = 'key item', + dropped_from = { + name = 'Granite Borer, Forced (K-10)', + pops = { { + id = 3072, --Withered Cocoon + type = 'item', + dropped_from = { name = 'Gullycampa (K-10)' } + } } + } + }, { + id = 1490, --Distended Chigoe Abdomen + type = 'key item', + dropped_from = { name = 'Tunga, Timed (K-10)' } + }, { + id = 1489, --Bulbous crawler cocoon + type = 'key item', + dropped_from = { + name = 'Blazing Eruca, Forced (J-10)', + pops = { { + id = 3073, --Eruca Egg + type = 'item', + dropped_from = { name = 'Ignis Eruca (J-10)' } + } } + } + } } } diff --git a/addons/EmpyPopTracker/nms/kukulkan.lua b/addons/EmpyPopTracker/nms/kukulkan.lua index 002a1926bc..d49fbc8aca 100644 --- a/addons/EmpyPopTracker/nms/kukulkan.lua +++ b/addons/EmpyPopTracker/nms/kukulkan.lua @@ -27,39 +27,39 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = 'Kukulkan', - pops = { { - id = 1466, --Mucid Ahriman Eyeball - type = 'key item', - dropped_from = { - name = 'Arimaspi, Forced (K-6)', - pops = { { - id = 2913, --Clouded Lens - type = 'item', - dropped_from = { name = 'Deep Eye (K-6/K-7)' } - } } - } - }, { - id = 1464, --Tattered Hippogryph Wing - type = 'key item', - dropped_from = { - name = 'Alkonost, Forced (H-6)', - pops = { { - id = 2912, --Giant Bugard Tusk - type = 'item', - dropped_from = { name = 'Ypotryll (I-7)' } - } } - } - }, { - id = 1465, --Cracked Wivre Horn - type = 'key item', - dropped_from = { - name = 'Keratyrannos, Forced (G-6)', - pops = { { - id = 2910, --Armored Dragonhorn - type = 'item', - dropped_from = { name = 'Mesa Wivre (G-6)' } - } } - } - } } + name = 'Kukulkan', + pops = { { + id = 1466, --Mucid Ahriman Eyeball + type = 'key item', + dropped_from = { + name = 'Arimaspi, Forced (K-6)', + pops = { { + id = 2913, --Clouded Lens + type = 'item', + dropped_from = { name = 'Deep Eye (K-6/K-7)' } + } } + } + }, { + id = 1464, --Tattered Hippogryph Wing + type = 'key item', + dropped_from = { + name = 'Alkonost, Forced (H-6)', + pops = { { + id = 2912, --Giant Bugard Tusk + type = 'item', + dropped_from = { name = 'Ypotryll (I-7)' } + } } + } + }, { + id = 1465, --Cracked Wivre Horn + type = 'key item', + dropped_from = { + name = 'Keratyrannos, Forced (G-6)', + pops = { { + id = 2910, --Armored Dragonhorn + type = 'item', + dropped_from = { name = 'Mesa Wivre (G-6)' } + } } + } + } } } diff --git a/addons/EmpyPopTracker/nms/orthrus.lua b/addons/EmpyPopTracker/nms/orthrus.lua index 0a48cea5b0..16ff706e66 100644 --- a/addons/EmpyPopTracker/nms/orthrus.lua +++ b/addons/EmpyPopTracker/nms/orthrus.lua @@ -27,31 +27,31 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = 'Orthrus', - pops = { { - id = 1520, --Steaming cerberus tongue - type = 'key item', - dropped_from = { - name = 'Amarok, Forced (E-6)', - pops = { { - id = 3231, --Sharabha Hide - type = 'item', + name = 'Orthrus', + pops = { { + id = 1520, --Steaming cerberus tongue + type = 'key item', dropped_from = { - name = 'Sharabha, Forced (G-5)', - pops = { { - id = 3237, - dropped_from = { name = 'Dune Manticore (F-5/F-6)' } - } } + name = 'Amarok, Forced (E-6)', + pops = { { + id = 3231, --Sharabha Hide + type = 'item', + dropped_from = { + name = 'Sharabha, Forced (G-5)', + pops = { { + id = 3237, + dropped_from = { name = 'Dune Manticore (F-5/F-6)' } + } } + } + }, { + id = 3232, --Tiger King Hide + type = 'item', + dropped_from = { name = 'Ansherekh, Timed (F-8/G-8)' } + }, { + id = 3238, --H.Q. Dhalmel Hide + type = 'item', + dropped_from = { name = 'Camelopardalis (F-7/G-7)' } + } } } - }, { - id = 3232, --Tiger King Hide - type = 'item', - dropped_from = { name = 'Ansherekh, Timed (F-8/G-8)' } - }, { - id = 3238, --H.Q. Dhalmel Hide - type = 'item', - dropped_from = { name = 'Camelopardalis (F-7/G-7)' } - } } - } - } } + } } } diff --git a/addons/EmpyPopTracker/nms/sedna.lua b/addons/EmpyPopTracker/nms/sedna.lua index d6b20f9886..e2d95077c7 100644 --- a/addons/EmpyPopTracker/nms/sedna.lua +++ b/addons/EmpyPopTracker/nms/sedna.lua @@ -27,21 +27,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = 'Sedna', - pops = { { - id = 1512, --Shimmering Pugil Scale - type = 'key item', - dropped_from = { name = 'Hrosshvalur, Timed (J-6)' } - }, { - id = 1511, --Glossy Sea Monk Sucker - type = 'key item', - dropped_from = { - name = 'Iku-Turso, Forced (J-7)', - pops = { { - id = 3100, --Moonbeam Clam - type = 'item', - dropped_from = { name = 'Jasconius (I-7/J-7)' } - } } - } - } } + name = 'Sedna', + pops = { { + id = 1512, --Shimmering Pugil Scale + type = 'key item', + dropped_from = { name = 'Hrosshvalur, Timed (J-6)' } + }, { + id = 1511, --Glossy Sea Monk Sucker + type = 'key item', + dropped_from = { + name = 'Iku-Turso, Forced (J-7)', + pops = { { + id = 3100, --Moonbeam Clam + type = 'item', + dropped_from = { name = 'Jasconius (I-7/J-7)' } + } } + } + } } } diff --git a/addons/EmpyPopTracker/nms/sobek.lua b/addons/EmpyPopTracker/nms/sobek.lua index f6e22e968a..a9dcaa033b 100644 --- a/addons/EmpyPopTracker/nms/sobek.lua +++ b/addons/EmpyPopTracker/nms/sobek.lua @@ -27,32 +27,32 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = 'Sobek', - pops = { { - id = 1500, --Molted Peiste Skin - type = 'key item', - dropped_from = { name = 'Gukumatz, Timed (J-11)' } - }, { - id = 1498, --Bloodstained Bugard Fang - type = 'key item', - dropped_from = { - name = 'Minax Bugard, Forced (K-10)', - pops = { { - id = 3085, --Bewitching Tusk - type = 'item', - dropped_from = { name = 'Abyssobugard (J-10/K-11)' } - } } - } - }, { - id = 1499, --Gnarled Lizard Nail - type = 'key item', - dropped_from = { - name = 'Sirrush, Forced (I-11)', - pops = { { - id = 3086, --Molt Scraps - type = 'item', - dropped_from = { name = 'Dusk Lizard (J-11)' } - } } - } - } } + name = 'Sobek', + pops = { { + id = 1500, --Molted Peiste Skin + type = 'key item', + dropped_from = { name = 'Gukumatz, Timed (J-11)' } + }, { + id = 1498, --Bloodstained Bugard Fang + type = 'key item', + dropped_from = { + name = 'Minax Bugard, Forced (K-10)', + pops = { { + id = 3085, --Bewitching Tusk + type = 'item', + dropped_from = { name = 'Abyssobugard (J-10/K-11)' } + } } + } + }, { + id = 1499, --Gnarled Lizard Nail + type = 'key item', + dropped_from = { + name = 'Sirrush, Forced (I-11)', + pops = { { + id = 3086, --Molt Scraps + type = 'item', + dropped_from = { name = 'Dusk Lizard (J-11)' } + } } + } + } } } diff --git a/addons/EmpyPopTracker/nms/ulhuadshi.lua b/addons/EmpyPopTracker/nms/ulhuadshi.lua index ad63f9168e..38ead13799 100644 --- a/addons/EmpyPopTracker/nms/ulhuadshi.lua +++ b/addons/EmpyPopTracker/nms/ulhuadshi.lua @@ -27,21 +27,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] return { - name = 'Ulhuadshi', - pops = { { - id = 1492, --Shriveled Hecteyes Stalk - type = 'key item', - dropped_from = { name = 'Amun, Timed (H-8/I-9)' } - }, { - id = 1491, --Mucid Worm Segment - type = 'key item', - dropped_from = { - name = 'Pallid Percy, Forced (J-7)', - pops = { { - id = 3074, --Blanched Silver - type = 'item', - dropped_from = { name = 'Entozoon (J-7)' } - } } - } - } } + name = 'Ulhuadshi', + pops = { { + id = 1492, --Shriveled Hecteyes Stalk + type = 'key item', + dropped_from = { name = 'Amun, Timed (H-8/I-9)' } + }, { + id = 1491, --Mucid Worm Segment + type = 'key item', + dropped_from = { + name = 'Pallid Percy, Forced (J-7)', + pops = { { + id = 3074, --Blanched Silver + type = 'item', + dropped_from = { name = 'Entozoon (J-7)' } + } } + } + } } } From 56e7eb6e55d1cc861696a8a373af76ad6189793c Mon Sep 17 00:00:00 2001 From: nassiralawar Date: Thu, 13 Feb 2020 19:59:37 -0800 Subject: [PATCH 0341/1002] Clean up a tab --- addons/scoreboard/scoreboard.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/scoreboard/scoreboard.lua b/addons/scoreboard/scoreboard.lua index 6a6c0fe399..be92b2363d 100644 --- a/addons/scoreboard/scoreboard.lua +++ b/addons/scoreboard/scoreboard.lua @@ -485,7 +485,7 @@ function find_pet_owner_name(actionpacket) for _, member in pairs(party) do if type(member) == 'table' and member.mob then if member.mob.pet_index and member.mob.pet_index> 0 and pet.index == member.mob.pet_index then - name = member.mob.name + name = member.mob.name break end end From edf900c66e4da636875787d10e47b017e0bc0d4d Mon Sep 17 00:00:00 2001 From: nassiralawar Date: Thu, 13 Feb 2020 20:00:16 -0800 Subject: [PATCH 0342/1002] Adding check for message_id 802 to cover the new Siren HP drain BP --- addons/scoreboard/scoreboard.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addons/scoreboard/scoreboard.lua b/addons/scoreboard/scoreboard.lua index be92b2363d..1d35ea1590 100644 --- a/addons/scoreboard/scoreboard.lua +++ b/addons/scoreboard/scoreboard.lua @@ -437,6 +437,9 @@ function action_handler(raw_actionpacket) dps_db:incr_ws_misses(target:get_name(), create_mob_name(actionpacket)) elseif main.resource and main.resource == 'weapon_skills' and main.conclusion then dps_db:add_ws_damage(target:get_name(), create_mob_name(actionpacket), main.param, main.spell_id) + -- Siren's Hysteric Assault does HP drain and falls under message_id 802 + elseif main.message_id == 802 then + dps_db:add_damage(target:get_name(), create_mob_name(actionpacket), main.param) elseif main.conclusion then if main.conclusion.subject == 'target' and T(main.conclusion.objects):contains('HP') and main.param ~= 0 then dps_db:add_damage(target:get_name(), create_mob_name(actionpacket), (main.conclusion.verb == 'gains' and -1 or 1)*main.param) From 6071a1a15c1447df9103cff47696ad9e8a0d1575 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Sun, 16 Feb 2020 23:47:32 -0500 Subject: [PATCH 0343/1002] Myhome warp all support --- addons/MyHome/MyHome.lua | 25 +++++++++++++++++++------ addons/MyHome/README.md | 6 ++++-- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/addons/MyHome/MyHome.lua b/addons/MyHome/MyHome.lua index a701f4f0a4..46dfe658ad 100644 --- a/addons/MyHome/MyHome.lua +++ b/addons/MyHome/MyHome.lua @@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.]] _addon.name = 'MyHome' _addon.author = 'from20020516' -_addon.version = '1.0' +_addon.version = '1.1' _addon.commands = {'myhome','mh','warp'} require('logger') @@ -85,15 +85,28 @@ function search_item() end end -windower.register_event('addon command',function() +windower.register_event('addon command',function(...) + local args = T{...} + local cmd = args[1] + if cmd == 'all' then + windower.chat.input('//myhome') + windower.send_ipc_message('myhome') + else local player = windower.ffxi.get_player() local get_spells = windower.ffxi.get_spells() local spell = S{player.main_job_id,player.sub_job_id}[4] and (get_spells[261] and player.vitals.mp >= 100 and {japanese='デジョン',english='"Warp"'} or get_spells[262] and player.vitals.mp >= 150 and {japanese='デジョンII',english='"Warp II"'}) - if spell then - windower.chat.input('/ma '..windower.to_shift_jis(spell[lang])..' ') - else - search_item() + if spell then + windower.chat.input('/ma '..windower.to_shift_jis(spell[lang])..' ') + else + search_item() + end + end +end) + +windower.register_event('ipc message',function (msg) + if msg == 'myhome' then + windower.chat.input('//myhome') end end) diff --git a/addons/MyHome/README.md b/addons/MyHome/README.md index 849497bfae..67d44fe4ee 100644 --- a/addons/MyHome/README.md +++ b/addons/MyHome/README.md @@ -4,11 +4,12 @@ ### Command - `//mh` OR `//warp` +- `//mh all` OR `//warp all` will warp all characters. - Priorities are: - 1. Warp - require learned and main job or sub job BLM. - 2. Warp II + 1. Warp - require learned and main job or sub job BLM. + 2. Warp II 3. Warp Ring - search inventory and wardrobes. 4. Warp Cudgel 5. Instant Warp - search inventory. @@ -18,6 +19,7 @@ ### Command - `//mh` または `//warp` +- `//mh all` または `//warp all` すべての文字をワープします。 - 優先順位: From 5ca42d9b61a7599bb992c12b22f5c2fbe2b36d8a Mon Sep 17 00:00:00 2001 From: Chiaia Date: Mon, 17 Feb 2020 00:16:01 -0500 Subject: [PATCH 0344/1002] Dimmer --- addons/Dimmer/Dimmer.lua | 104 +++++++++++++++++++++++++++++++++++++++ addons/Dimmer/README.md | 14 ++++++ addons/addons.xml | 7 +++ 3 files changed, 125 insertions(+) create mode 100644 addons/Dimmer/Dimmer.lua create mode 100644 addons/Dimmer/README.md diff --git a/addons/Dimmer/Dimmer.lua b/addons/Dimmer/Dimmer.lua new file mode 100644 index 0000000000..6520909b0d --- /dev/null +++ b/addons/Dimmer/Dimmer.lua @@ -0,0 +1,104 @@ +--[[ +Copyright © 2018, Chiaia +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 Dimmer 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.]] + +--Complete addon is almost a direct copy of MyHome from "from20020516" but for warping to a different area. + +_addon.name = 'Dimmer' +_addon.author = 'Chiaia' +_addon.version = '1.1' +_addon.commands = {'dim','dimmer'} + + +require('logger') +extdata = require('extdata') + +lang = string.lower(windower.ffxi.get_info().language) +item_info = { + [1]={id=26176,japanese='D.ホラリング',english='"Dim. Ring (Holla)"',slot=13}, + [2]={id=26177,japanese='D.デムリング',english='"Dim. Ring (Dem)"',slot=13}, + [3]={id=26178,japanese='D.メアリング',english='"Dim. Ring (Mea)"',slot=13}, + } + +function search_item() + local item_array = {} + local bags = {0,8,10,11,12} --inventory,wardrobe1-4 + local get_items = windower.ffxi.get_items + for i=1,#bags do + for _,item in ipairs(get_items(bags[i])) do + if item.id > 0 then + item_array[item.id] = item + item_array[item.id].bag = bags[i] + end + end + end + for index,stats in pairs(item_info) do + local item = item_array[stats.id] + local set_equip = windower.ffxi.set_equip + if item then + local ext = extdata.decode(item) + local enchant = ext.type == 'Enchanted Equipment' + local recast = enchant and ext.charges_remaining > 0 and math.max(ext.next_use_time+18000-os.time(),0) + local usable = recast and recast == 0 + log(stats[lang],usable and '' or recast and recast..' sec recast.') + if usable or ext.type == 'General' then + if enchant and item.status ~= 5 then --not equipped + set_equip(item.slot,stats.slot,item.bag) + log_flag = true + repeat --waiting cast delay + coroutine.sleep(1) + local ext = extdata.decode(get_items(item.bag,item.slot)) + local delay = ext.activation_time+18000-os.time() + if delay > 0 then + log(stats[lang],delay) + elseif log_flag then + log_flag = false + log('Item use within 3 seconds..') + end + until ext.usable or delay > 10 + end + windower.chat.input('/item '..windower.to_shift_jis(stats[lang])..' ') + break; + end + else + log('You don\'t have '..stats[lang]..'.') + end + end +end + +windower.register_event('addon command',function(...) + local args = T{...} + local cmd = args[1] + if cmd == 'all' then + windower.chat.input('//dimmer') + windower.send_ipc_message('dimmer') + else + search_item() + end +end) + +windower.register_event('ipc message',function (msg) + if msg == 'dimmer' then + windower.chat.input('//dimmer') + end +end) \ No newline at end of file diff --git a/addons/Dimmer/README.md b/addons/Dimmer/README.md new file mode 100644 index 0000000000..ea808e7adc --- /dev/null +++ b/addons/Dimmer/README.md @@ -0,0 +1,14 @@ +# Dimmer +## English +- Automatically choose and uses the first Dimensional Ring on cool down to warp to Reisenjima for you. + +### Command +- `//dim` OR `//dimmer` +- `//dim all` OR `//dimmer all` will use ring on all characters. +- Priorities are: + 1. Dim. Ring (Holla) + 2. Dim. Ring (Dem) + 3. Dim. Ring (Mea) + +## 日本語 +- Should support the Japanesse client too. \ No newline at end of file diff --git a/addons/addons.xml b/addons/addons.xml index dfc12b02d4..93f141aaa2 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -177,6 +177,13 @@ Displays Chocobo digging accuracy, fatigue and remaining greens after each dig. Also shows dig "recast" timer using the Timers plugin. https://github.com/svanheulen/digger-windower-addon/issues http://www.ffxiah.com/player/Odin/Acacia + + + Dimmer + Chiaia + Helps warp you to Reisenjima using (Dim) Rings. + https://github.com/Windower/Lua/issues + https://discord.gg/b275nMv Distance From 8becc89b27d5dc4be455a7ff6ce73160f177457a Mon Sep 17 00:00:00 2001 From: Chiaia Date: Mon, 17 Feb 2020 01:21:40 -0500 Subject: [PATCH 0345/1002] Update extdata.lua --- addons/libs/extdata.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/libs/extdata.lua b/addons/libs/extdata.lua index d8759655f6..c92e7bdcf1 100644 --- a/addons/libs/extdata.lua +++ b/addons/libs/extdata.lua @@ -173,6 +173,8 @@ augment_values = { [0x07C] = {{stat="Pet: Acc.", offset=1}, {stat="Pet: R.Acc.", offset=1}, {stat="Pet: Atk.", offset=1}, {stat="Pet: R.Atk.", offset=1}}, [0x07D] = {{stat="Pet: M.Acc.", offset=1}, {stat="Pet: M.Dmg.", offset=1}}, [0x07E] = {{stat='Pet: Magic Damage', offset=1}}, + [0x07F] = {{stat="Pet: Magic dmg. taken ", offset=1,multiplier=-1,percent=true}}, + [0x080] = {{stat="Pet:",offset = 0}}, --[0x081: Accuracy +1 Ranged Acc. +0 | value + 1 From 97766b57bc24fa8f7ff49c1a401888f8b54bf0bc Mon Sep 17 00:00:00 2001 From: Dean James Date: Mon, 24 Feb 2020 00:35:13 +0000 Subject: [PATCH 0346/1002] Added WoC and ADL to trackable NMs. Adjusted addon to allow tracking of NMs that use regular items as pops. Allowed tracking of NMs with spaces in their name. --- addons/EmpyPopTracker/EmpyPopTracker.lua | 23 +++-- addons/EmpyPopTracker/README.md | 6 +- .../EmpyPopTracker/nms/arch dynamis lord.lua | 87 +++++++++++++++++++ addons/EmpyPopTracker/nms/index.lua | 4 +- .../EmpyPopTracker/nms/warder of courage.lua | 79 +++++++++++++++++ 5 files changed, 186 insertions(+), 13 deletions(-) create mode 100644 addons/EmpyPopTracker/nms/arch dynamis lord.lua create mode 100644 addons/EmpyPopTracker/nms/warder of courage.lua diff --git a/addons/EmpyPopTracker/EmpyPopTracker.lua b/addons/EmpyPopTracker/EmpyPopTracker.lua index a87bbf5d20..e6d88c4236 100644 --- a/addons/EmpyPopTracker/EmpyPopTracker.lua +++ b/addons/EmpyPopTracker/EmpyPopTracker.lua @@ -29,7 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'Empy Pop Tracker' _addon.author = 'Dean James (Xurion of Bismarck)' _addon.commands = { 'ept', 'empypoptracker' } -_addon.version = '2.0.0' +_addon.version = '2.1.0' config = require('config') res = require('resources') @@ -167,16 +167,22 @@ end EmpyPopTracker.generate_info = function(nm, key_items, items) local info = { - has_all_kis = true, + has_all_pops = true, text = '' } if nm.pops then - for _, key_item_data in pairs(nm.pops) do - local has_pop_ki = owns_key_item(key_item_data.id, key_items) + for _, pop_item_data in pairs(nm.pops) do + local has_pop = false - if not has_pop_ki then - info.has_all_kis = false + if pop_item_data.type == 'key item' then + has_pop = owns_key_item(pop_item_data.id, key_items) + elseif pop_item_data.type == 'item' then + has_pop = owns_item(pop_item_data.id, items) + end + + if not has_pop then + info.has_all_pops = false end end end @@ -213,8 +219,7 @@ end) commands = {} commands.track = function(...) - local args = {...} - local nm_search_pattern = args[1] + local nm_search_pattern = table.concat({...}, ' ') local matching_nm_names = find_nms(nm_search_pattern) if #matching_nm_names == 0 then @@ -279,7 +284,7 @@ EmpyPopTracker.update = function() local tracked_nm_data = nm_data[EmpyPopTracker.settings.tracking] local generated_info = EmpyPopTracker.generate_info(tracked_nm_data, key_items, items) EmpyPopTracker.text:text(generated_info.text) - if generated_info.has_all_kis then + if generated_info.has_all_pops then EmpyPopTracker.text:bg_color(0, 75, 0) else EmpyPopTracker.text:bg_color(0, 0, 0) diff --git a/addons/EmpyPopTracker/README.md b/addons/EmpyPopTracker/README.md index f674c3c942..5fd2550af6 100644 --- a/addons/EmpyPopTracker/README.md +++ b/addons/EmpyPopTracker/README.md @@ -1,10 +1,10 @@ -# FFXI Empyrean Pop Tracker +# FFXI Empy Pop Tracker -An FFXI Windower 4 addon that tracks items and key items for popping Empyrean NMs in Abyssea, such as Briareus, Apademak and Sobek. +An FFXI Windower 4 addon that tracks items and key items for popping various NMs, such as Briareus, Apademak and Warder of Courage. ![Example of Cirein-croin tracking](readme/demo.png) ![All KIs obtained](readme/demo-full.png) -Key items are identified by the Zhe (Ж) character. Treasure pool counts for pop items are listed in amber after the item in the format of [3] (assuming 3 of that item in the pool). +Originally developed to track Abyssea Empyrean weapon NMs, hence the name. Key items are identified by the Zhe (Ж) character. Treasure pool counts for pop items are listed in amber after the item in the format of [3] (assuming 3 of that item in the pool). ## Load diff --git a/addons/EmpyPopTracker/nms/arch dynamis lord.lua b/addons/EmpyPopTracker/nms/arch dynamis lord.lua new file mode 100644 index 0000000000..3e693c7f70 --- /dev/null +++ b/addons/EmpyPopTracker/nms/arch dynamis lord.lua @@ -0,0 +1,87 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = 'Arch Dynamis Lord', + pops = { { + id = 3429, --Fiendish Tome (26) + type = 'item', + dropped_from = { + name = 'Dynamis Lord, Forced (E-8)', + pops = { { + id = 3358, --Shrouded Bijou + type = 'item', + dropped_from = { name = 'Various Demon lottery NMs' } + } } + } + }, { + id = 3430, --Fiendish Tome (27) + type = 'item', + dropped_from = { + name = 'Duke Haures, Forced (J-7)', + pops = { { + id = 3400, --Odious Skull + type = 'item', + dropped_from = { name = 'Kindred DRK, RDM & SAM' } + } } + } + }, { + id = 3431, --Fiendish Tome (28) + type = 'item', + dropped_from = { + name = 'Marquis Caim, Forced (J-6)', + pops = { { + id = 3401, --Odious Horn + type = 'item', + dropped_from = { name = 'Kindred BRD, NIN, SMN & WAR' } + } } + } + }, { + id = 3432, --Fiendish Tome (29) + type = 'item', + dropped_from = { + name = 'Baron Avnas, Forced (I-5)', + pops = { { + id = 3402, --Odious Blood + type = 'item', + dropped_from = { name = 'Kindred DRG, MNK, THF & WHM' } + } } + } + }, { + id = 3433, --Fiendish Tome (30) + type = 'item', + dropped_from = { + name = 'Count Haagenti, Forced (F-7)', + pops = { { + id = 3403, --Odious Pen + type = 'item', + dropped_from = { name = 'Kindred BLM, BST, PLD & RNG' } + } } + } + } } +} diff --git a/addons/EmpyPopTracker/nms/index.lua b/addons/EmpyPopTracker/nms/index.lua index 9091a466a9..425a2b4c56 100644 --- a/addons/EmpyPopTracker/nms/index.lua +++ b/addons/EmpyPopTracker/nms/index.lua @@ -29,6 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. local nms = { 'alfard', 'apademak', + 'arch dynamis lord', 'azdaja', 'briareus', 'bukhis', @@ -43,7 +44,8 @@ local nms = { 'orthrus', 'sedna', 'sobek', - 'ulhuadshi' + 'ulhuadshi', + 'warder of courage' } nm_data = {} diff --git a/addons/EmpyPopTracker/nms/warder of courage.lua b/addons/EmpyPopTracker/nms/warder of courage.lua new file mode 100644 index 0000000000..6534c62bb4 --- /dev/null +++ b/addons/EmpyPopTracker/nms/warder of courage.lua @@ -0,0 +1,79 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = "Warder of Courage", + pops = { { + id = 2986, --Primal Nazar + type = 'key item', + dropped_from = { + name = 'Dremi (NPC)', + pops = { { + id = 2976, --Primary Nazar + type = 'key item', + dropped_from = { name = 'Warder of Temperance (Zdei, portal #1)' } + }, { + id = 2977, --Secondary Nazar + type = 'key item', + dropped_from = { name = 'Warder of Fortitude (Ghrah, portal #3)' } + }, { + id = 2978, --Tertiary Nazar + type = 'key item', + dropped_from = { name = 'Warder of Faith (Euvhi, portal #12)' } + }, { + id = 2979, --Quaternary Nazar + type = 'key item', + dropped_from = { name = 'Warder of Justice (Xzomit, portal #6)' } + }, { + id = 2980, --Quinary Nazar + type = 'key item', + dropped_from = { name = 'Warder of Hope (Phuabo, portal #1)' } + }, { + id = 2981, --Senary Nazar + type = 'key item', + dropped_from = { name = 'Warder of Prudence (Hpemde, portal #9)' } + }, { + id = 2982, --Septenary Nazar + type = 'key item', + dropped_from = { name = 'Warder of Love (Yovra)' } + }, { + id = 2983, --Octonary Nazar + type = 'key item', + dropped_from = { name = 'Warder of Dignity (Limule, portal #4)' } + }, { + id = 2984, --Nonary Nazar + type = 'key item', + dropped_from = { name = 'Warder of Loyalty (Clionid, portal #13)' } + }, { + id = 2985, --Denary Nazar + type = 'key item', + dropped_from = { name = 'Warder of Mercy (Murex, portal #7)' } + }} + } + } } +} From 0548e9094ff5b325ffedd6d72fa29cfd3591d10e Mon Sep 17 00:00:00 2001 From: Dean James Date: Mon, 24 Feb 2020 21:15:42 +0000 Subject: [PATCH 0347/1002] Reduced generate_info to make it more concise. https://github.com/Windower/Lua/pull/1834 --- addons/EmpyPopTracker/EmpyPopTracker.lua | 28 +++++------------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/addons/EmpyPopTracker/EmpyPopTracker.lua b/addons/EmpyPopTracker/EmpyPopTracker.lua index e6d88c4236..ff52e45ed4 100644 --- a/addons/EmpyPopTracker/EmpyPopTracker.lua +++ b/addons/EmpyPopTracker/EmpyPopTracker.lua @@ -166,30 +166,12 @@ function generate_text(data, key_items, items, depth) end EmpyPopTracker.generate_info = function(nm, key_items, items) - local info = { - has_all_pops = true, - text = '' + return { + has_all_pops = not nm.pops or T(nm.pops):all(function(item) + return item.type == 'item' and owns_item(item.id, items) or owns_key_item(item.id, key_items) + end), + text = generate_text(nm, key_items, items, 1) } - - if nm.pops then - for _, pop_item_data in pairs(nm.pops) do - local has_pop = false - - if pop_item_data.type == 'key item' then - has_pop = owns_key_item(pop_item_data.id, key_items) - elseif pop_item_data.type == 'item' then - has_pop = owns_item(pop_item_data.id, items) - end - - if not has_pop then - info.has_all_pops = false - end - end - end - - info.text = generate_text(nm, key_items, items, 1) - - return info end function find_nms(pattern) From 641d089ea17433a6717bdf97e3d28c9c551e0499 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Wed, 26 Feb 2020 13:54:03 -0700 Subject: [PATCH 0348/1002] Add missing Ionis npc --- addons/craft/craft.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/craft/craft.lua b/addons/craft/craft.lua index ab8a2940b7..ef8922d570 100644 --- a/addons/craft/craft.lua +++ b/addons/craft/craft.lua @@ -97,6 +97,7 @@ local support_npcs = { {name = "Lih Pituu", zone = 241, menu = 10018, buff = 241}, {name = "Terude-Harude", zone = 241, menu = 10013, buff = 239}, {name = "Fleuricette", zone = 256, menu = 1201, buff = 512}, + {name = "Quiri-Aliri", zone = 257, menu = 1201, buff = 512}, } local exceptions = { From c49a292f022f43957e84f1ac4aabd9f4ba525c3a Mon Sep 17 00:00:00 2001 From: Nifim Date: Thu, 27 Feb 2020 21:30:45 -0800 Subject: [PATCH 0349/1002] Update bufftime offset bufftime offset has changed to `572662306` --- addons/GearSwap/packet_parsing.lua | 2 +- addons/libs/packets/fields.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/GearSwap/packet_parsing.lua b/addons/GearSwap/packet_parsing.lua index 7a5295e1a2..75c97315fd 100644 --- a/addons/GearSwap/packet_parsing.lua +++ b/addons/GearSwap/packet_parsing.lua @@ -456,7 +456,7 @@ parse.i[0x063] = function (data) for i=1,32 do local buff_id = data:unpack('H',i*2+7) if buff_id ~= 255 and buff_id ~= 0 then -- 255 is used for "no buff" - local t = data:unpack('I',i*4+0x45)/60+501079520+1009810800 + local t = data:unpack('I',i*4+0x45)/60+572662306+1009810800 newbuffs[i] = setmetatable({ name=res.buffs[buff_id].name, buff=copy_entry(res.buffs[buff_id]), diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index c9d325e879..626fc37556 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -95,7 +95,7 @@ do end bufftime = function(ts) - return fn((ts / 60) + 501079520 + 1009810800) + return fn((ts / 60) + 572662306 + 1009810800) end end From f61b311b99729a97f817e858d8390ec995f9d13d Mon Sep 17 00:00:00 2001 From: Dean James Date: Mon, 2 Mar 2020 00:04:36 +0000 Subject: [PATCH 0350/1002] EmpyPopTracker 2.1.1. Fixed issue where items would not show green. Updated addon description. --- addons/EmpyPopTracker/EmpyPopTracker.lua | 12 +++++++----- addons/addons.xml | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/addons/EmpyPopTracker/EmpyPopTracker.lua b/addons/EmpyPopTracker/EmpyPopTracker.lua index ff52e45ed4..751ea953f9 100644 --- a/addons/EmpyPopTracker/EmpyPopTracker.lua +++ b/addons/EmpyPopTracker/EmpyPopTracker.lua @@ -29,7 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'Empy Pop Tracker' _addon.author = 'Dean James (Xurion of Bismarck)' _addon.commands = { 'ept', 'empypoptracker' } -_addon.version = '2.1.0' +_addon.version = '2.1.1' config = require('config') res = require('resources') @@ -68,10 +68,12 @@ colors.warning = '\\cs(255,170,0)' colors.close = '\\cr' function owns_item(id, items) - for _, bag in ipairs(items) do - for _, item in ipairs(bag) do - if item.id == id then - return true + for _, bag in pairs(items) do + if type(bag) == 'table' then + for _, item in ipairs(bag) do + if item.id == id then + return true + end end end end diff --git a/addons/addons.xml b/addons/addons.xml index 93f141aaa2..7243b1c91c 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -215,7 +215,7 @@ EmpyPopTracker Dean James (Xurion of Bismarck) - Tracks items and key items for popping Empyrean NMs in Abyssea, such as Briareus, Apademak and Sobek. + Tracks items and key items for popping various NMs, such as Briareus, Apademak and Warder of Courage. https://github.com/xurion/ffxi-empy-pop-tracker/issues https://www.ffxiah.com/forum/topic/54376/empyrean-pop-tracker-addon-10-years-late/ From e70daa779c62af573cb1a9f786427b2cef3a8823 Mon Sep 17 00:00:00 2001 From: dtw <362017+dtw@users.noreply.github.com> Date: Mon, 2 Mar 2020 09:44:50 +0000 Subject: [PATCH 0351/1002] Add burdentracker to settings --- addons/autocontrol/autocontrol.lua | 7 +++++-- addons/autocontrol/maneuver.lua | 8 ++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/addons/autocontrol/autocontrol.lua b/addons/autocontrol/autocontrol.lua index abb7ababe9..f16f872c81 100644 --- a/addons/autocontrol/autocontrol.lua +++ b/addons/autocontrol/autocontrol.lua @@ -59,7 +59,8 @@ defaults.autosets.default = T{ } defaults.AutoActivate = true defaults.AutoDeusExAutomata = false defaults.maneuvertimers = true - +defaults.burdentracker = true + settings = config.load(defaults) require('maneuver') -- has to be loaded after settings are parsed. @@ -92,7 +93,9 @@ function initialize() if player.pet_index then running = 1 text_update_loop('start') - Burden_tb:show() + if settings.burdentracker then + Burden_tb:show() + end end end end diff --git a/addons/autocontrol/maneuver.lua b/addons/autocontrol/maneuver.lua index 44419829b3..0a6ae085cc 100644 --- a/addons/autocontrol/maneuver.lua +++ b/addons/autocontrol/maneuver.lua @@ -132,7 +132,9 @@ windower.register_event("action", function(act) windower.send_command('@timers d Overloaded!') heatupdate() elseif abil_ID == 136 or abil_ID == 310 then -- Activate or Deus Ex Automata - Burden_tb:show() + if settings.burdentracker then + Burden_tb:show() + end decay = get_decay() activate_burden() elseif abil_ID == 139 then @@ -397,7 +399,9 @@ function zone_check(to) if player_mob then if player_mob.pet_index and player_mob.pet_index ~= 0 then - Burden_tb:show() + if settings.burdentracker then + Burden_tb:show() + end activate_burden() end else From 553eb2126b51bd8d8de5c359c64abf5e7bf89f5a Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 8 Mar 2020 14:57:01 +0000 Subject: [PATCH 0352/1002] Create indinope.lua --- addons/indinope/indinope.lua | 64 ++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 addons/indinope/indinope.lua diff --git a/addons/indinope/indinope.lua b/addons/indinope/indinope.lua new file mode 100644 index 0000000000..67ca8b420d --- /dev/null +++ b/addons/indinope/indinope.lua @@ -0,0 +1,64 @@ +--[[ +Copyright © Lili, 2020 +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 Indi-Nope 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 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.name = 'Indi-Nope' +_addon.author = 'Lili' +_addon.version = '1.0.3' + +--[[ +Indi-nope 1.0.3 +Hides visual effects from geomancy on players. + +Currently does not hide geomancy effect around luopans. + +No commands. Load it and it's on, unload and it's off. + +Changelog: + +1.0.3 - A few tweaks. +1.0.1 - Fixed a bug where Indi-Nope would make Master stars disappear. Thanks Kenshi for finding out. +1.0.0 - Initial + +Thanks to Thorny, this addon is a port to windower of his Ashita code with the same functionality. +]] + +require('bit') + +offsets = { [0x00D] = 67, [0x037] = 89, } + +windower.register_event('incoming chunk',function(id,original,modified,injected,blocked) + if injected or blocked or not offsets[id] then return end + + offset = offsets[id] + flags = original:byte(offsets[id]) + + if bit.band(flags,0x7F) ~= 0 then + packet = table.concat({ original:sub(1,offset-1), string.char(bit.band(flags,0x80)), original:sub(offset+1) }) + return packet + end +end) From 1ed43ae31b2b37c552313f1575e7956013bd9cd2 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 8 Mar 2020 14:57:34 +0000 Subject: [PATCH 0353/1002] Create README.md --- addons/indinope/README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 addons/indinope/README.md diff --git a/addons/indinope/README.md b/addons/indinope/README.md new file mode 100644 index 0000000000..5385a9e31a --- /dev/null +++ b/addons/indinope/README.md @@ -0,0 +1,14 @@ +# Indi-nope 1.0.3 +Hides visual effects from geomancy on players. + +Currently does not hide geomancy effect around luopans. + +**No commands.** Load it and it's on, unload and it's off. + +### Changelog: + +1.0.3 - A few tweaks. +1.0.1 - Fixed a bug where Indi-Nope would make Master stars disappear. Thanks Kenshi for finding out. +1.0.0 - Initial release. + +Thanks to Thorny, this addon is a port to windower of his Ashita code with the same functionality. From 74d80eff24dd33bcae28c668f6968c5b5e1f9a34 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 8 Mar 2020 15:42:47 +0000 Subject: [PATCH 0354/1002] Update addons.xml --- addons/addons.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/addons/addons.xml b/addons/addons.xml index 7243b1c91c..853b12d31c 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -809,4 +809,11 @@ https://github.com/Windower/Lua/issues https://github.com/azamorapl + + Indi-Nope + Lili + Block graphical effects from Geomancer's Indi- spells. + https://github.com/Windower/Lua/issues + https://github.com/lili-ffxi + From 5607e271862b2225616462bc31b1d337b671cb4d Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 8 Mar 2020 15:47:57 +0000 Subject: [PATCH 0355/1002] Update addons.xml --- addons/addons.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/addons.xml b/addons/addons.xml index 853b12d31c..ed64f3a4f9 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -810,7 +810,7 @@ https://github.com/azamorapl - Indi-Nope + IndiNope Lili Block graphical effects from Geomancer's Indi- spells. https://github.com/Windower/Lua/issues From 54af6f6b5de04d9c4852a885c26a8c5b99443935 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 8 Mar 2020 15:52:46 +0000 Subject: [PATCH 0356/1002] Update indinope.lua --- addons/indinope/indinope.lua | 38 +++++++++++------------------------- 1 file changed, 11 insertions(+), 27 deletions(-) diff --git a/addons/indinope/indinope.lua b/addons/indinope/indinope.lua index 67ca8b420d..86119d2956 100644 --- a/addons/indinope/indinope.lua +++ b/addons/indinope/indinope.lua @@ -25,40 +25,24 @@ 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.name = 'Indi-Nope' _addon.author = 'Lili' -_addon.version = '1.0.3' - ---[[ -Indi-nope 1.0.3 -Hides visual effects from geomancy on players. - -Currently does not hide geomancy effect around luopans. - -No commands. Load it and it's on, unload and it's off. - -Changelog: - -1.0.3 - A few tweaks. -1.0.1 - Fixed a bug where Indi-Nope would make Master stars disappear. Thanks Kenshi for finding out. -1.0.0 - Initial - -Thanks to Thorny, this addon is a port to windower of his Ashita code with the same functionality. -]] +_addon.version = '1.0.4' require('bit') offsets = { [0x00D] = 67, [0x037] = 89, } windower.register_event('incoming chunk',function(id,original,modified,injected,blocked) - if injected or blocked or not offsets[id] then return end - - offset = offsets[id] - flags = original:byte(offsets[id]) + if injected or blocked or not offsets[id] then return end + + offset = offsets[id] + flags = original:byte(offsets[id]) - if bit.band(flags,0x7F) ~= 0 then - packet = table.concat({ original:sub(1,offset-1), string.char(bit.band(flags,0x80)), original:sub(offset+1) }) - return packet - end + -- if any of the bits 0 through 7 are set, a bubble is shown and we want to block it. + if bit.band(flags,0x7F) ~= 0 then + packet = original:sub(1,offset-1)..string.char(bit.band(flags,0x80))..original:sub(offset+1) -- preserve bit 8 (Job Master stars) + return packet + end end) From 60bd06633e5625650aaf9b01fd4f6954f098de54 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 8 Mar 2020 15:53:16 +0000 Subject: [PATCH 0357/1002] Update README.md --- addons/indinope/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/indinope/README.md b/addons/indinope/README.md index 5385a9e31a..5f4568c815 100644 --- a/addons/indinope/README.md +++ b/addons/indinope/README.md @@ -1,4 +1,4 @@ -# Indi-nope 1.0.3 +# Indi-nope 1.0.4 Hides visual effects from geomancy on players. Currently does not hide geomancy effect around luopans. @@ -7,6 +7,7 @@ Currently does not hide geomancy effect around luopans. ### Changelog: +1.0.4 - More tweaks. 1.0.3 - A few tweaks. 1.0.1 - Fixed a bug where Indi-Nope would make Master stars disappear. Thanks Kenshi for finding out. 1.0.0 - Initial release. From 7832b6cee74b4cfd2cdcf5b48a1afe5ed4f5b917 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 8 Mar 2020 15:54:08 +0000 Subject: [PATCH 0358/1002] Update indinope.lua --- addons/indinope/indinope.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/indinope/indinope.lua b/addons/indinope/indinope.lua index 86119d2956..e9ee1622ba 100644 --- a/addons/indinope/indinope.lua +++ b/addons/indinope/indinope.lua @@ -10,7 +10,7 @@ modification, are permitted provided that the following conditions are met: * 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 Indi-Nope nor the + * Neither the name of IndiNope nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. @@ -26,7 +26,7 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] -_addon.name = 'Indi-Nope' +_addon.name = 'IndiNope' _addon.author = 'Lili' _addon.version = '1.0.4' From 5bbb10545add7cba114b8abcd7644013a29c2a6c Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 8 Mar 2020 15:58:18 +0000 Subject: [PATCH 0359/1002] Update README.md --- addons/indinope/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/indinope/README.md b/addons/indinope/README.md index 5f4568c815..16c82a4e4d 100644 --- a/addons/indinope/README.md +++ b/addons/indinope/README.md @@ -1,4 +1,4 @@ -# Indi-nope 1.0.4 +# IndiNope 1.0.4 Hides visual effects from geomancy on players. Currently does not hide geomancy effect around luopans. From b8460572d9f12175a7b100306883499760aedbbb Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 8 Mar 2020 16:02:30 +0000 Subject: [PATCH 0360/1002] Update indinope.lua --- addons/indinope/indinope.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/indinope/indinope.lua b/addons/indinope/indinope.lua index e9ee1622ba..36ceccf599 100644 --- a/addons/indinope/indinope.lua +++ b/addons/indinope/indinope.lua @@ -17,7 +17,7 @@ modification, are permitted provided that the following conditions are met: 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 BE LIABLE FOR ANY +DISCLAIMED. IN NO EVENT SHALL LILI 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 @@ -34,7 +34,7 @@ require('bit') offsets = { [0x00D] = 67, [0x037] = 89, } -windower.register_event('incoming chunk',function(id,original,modified,injected,blocked) +windower.register_event('incoming chunk', function(id, original, modified, injected, blocked) if injected or blocked or not offsets[id] then return end offset = offsets[id] @@ -42,7 +42,7 @@ windower.register_event('incoming chunk',function(id,original,modified,injected, -- if any of the bits 0 through 7 are set, a bubble is shown and we want to block it. if bit.band(flags,0x7F) ~= 0 then - packet = original:sub(1,offset-1)..string.char(bit.band(flags,0x80))..original:sub(offset+1) -- preserve bit 8 (Job Master stars) + packet = original:sub(1, offset - 1) .. string.char(bit.band(flags, 0x80)) .. original:sub(offset + 1) -- preserve bit 8 (Job Master stars) return packet end end) From 1c8c7d62feb8da3c45a03fabc8b1d3cbc756bb5d Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 8 Mar 2020 16:04:24 +0000 Subject: [PATCH 0361/1002] Update indinope.lua --- addons/indinope/indinope.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/indinope/indinope.lua b/addons/indinope/indinope.lua index 36ceccf599..e085b2b79b 100644 --- a/addons/indinope/indinope.lua +++ b/addons/indinope/indinope.lua @@ -41,7 +41,7 @@ windower.register_event('incoming chunk', function(id, original, modified, injec flags = original:byte(offsets[id]) -- if any of the bits 0 through 7 are set, a bubble is shown and we want to block it. - if bit.band(flags,0x7F) ~= 0 then + if bit.band(flags, 0x7F) ~= 0 then packet = original:sub(1, offset - 1) .. string.char(bit.band(flags, 0x80)) .. original:sub(offset + 1) -- preserve bit 8 (Job Master stars) return packet end From feb7f1d01bc99295f26f9dfa3e87427319f88a5a Mon Sep 17 00:00:00 2001 From: Dean James Date: Mon, 9 Mar 2020 16:54:59 +0000 Subject: [PATCH 0362/1002] Fixed incorrect Chloris data. Allowed configurable text colours. --- addons/EmpyPopTracker/EmpyPopTracker.lua | 39 ++++++++++++++++-------- addons/EmpyPopTracker/README.md | 6 ++-- addons/EmpyPopTracker/nms/chloris.lua | 28 ++++++++--------- 3 files changed, 45 insertions(+), 28 deletions(-) diff --git a/addons/EmpyPopTracker/EmpyPopTracker.lua b/addons/EmpyPopTracker/EmpyPopTracker.lua index 751ea953f9..797226ddba 100644 --- a/addons/EmpyPopTracker/EmpyPopTracker.lua +++ b/addons/EmpyPopTracker/EmpyPopTracker.lua @@ -29,7 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'Empy Pop Tracker' _addon.author = 'Dean James (Xurion of Bismarck)' _addon.commands = { 'ept', 'empypoptracker' } -_addon.version = '2.1.1' +_addon.version = '2.2.1' config = require('config') res = require('resources') @@ -57,15 +57,30 @@ defaults.text.text.size = 10 defaults.tracking = 'briareus' defaults.visible = true defaults.add_to_chat_mode = 8 +defaults.colors = {} +defaults.colors.needed = {} +defaults.colors.needed.red = 255 +defaults.colors.needed.green = 50 +defaults.colors.needed.blue = 50 +defaults.colors.obtained = {} +defaults.colors.obtained.red = 100 +defaults.colors.obtained.green = 255 +defaults.colors.obtained.blue = 100 +defaults.colors.pool = {} +defaults.colors.pool.red = 255 +defaults.colors.pool.green = 170 +defaults.colors.pool.blue = 0 +defaults.colors.bgall = {} +defaults.colors.bgall.red = 0 +defaults.colors.bgall.green = 75 +defaults.colors.bgall.blue = 0 EmpyPopTracker.settings = config.load(defaults) EmpyPopTracker.text = require('texts').new(EmpyPopTracker.settings.text, EmpyPopTracker.settings) -colors = {} -colors.success = '\\cs(100,255,100)' -colors.danger = '\\cs(255,50,50)' -colors.warning = '\\cs(255,170,0)' -colors.close = '\\cr' +function start_color(color) + return '\\cs(' .. EmpyPopTracker.settings.colors[color].red .. ',' .. EmpyPopTracker.settings.colors[color].green .. ',' .. EmpyPopTracker.settings.colors[color].blue .. ')' +end function owns_item(id, items) for _, bag in pairs(items) do @@ -149,16 +164,16 @@ function generate_text(data, key_items, items, depth) local item_colour if owns_pop then - item_colour = colors.success + item_colour = start_color('obtained') else - item_colour = colors.danger + item_colour = start_color('needed') end local pool_notification = '' if in_pool_count > 0 then - pool_notification = colors.warning .. ' [' .. in_pool_count .. ']' .. colors.close + pool_notification = start_color('pool') .. ' [' .. in_pool_count .. ']' .. '\\cr' end - text = text .. '\n' .. get_indent(depth) .. pop.dropped_from.name .. '\n' .. get_indent(depth) .. ' >> ' .. item_colour .. item_identifier .. pop_name .. colors.close .. pool_notification + text = text .. '\n' .. get_indent(depth) .. pop.dropped_from.name .. '\n' .. get_indent(depth) .. ' >> ' .. item_colour .. item_identifier .. pop_name .. '\\cr' .. pool_notification if pop.dropped_from.pops then text = text .. generate_text(pop.dropped_from, key_items, items, depth + 1) end @@ -269,9 +284,9 @@ EmpyPopTracker.update = function() local generated_info = EmpyPopTracker.generate_info(tracked_nm_data, key_items, items) EmpyPopTracker.text:text(generated_info.text) if generated_info.has_all_pops then - EmpyPopTracker.text:bg_color(0, 75, 0) + EmpyPopTracker.text:bg_color(EmpyPopTracker.settings.colors.bgall.red, EmpyPopTracker.settings.colors.bgall.green, EmpyPopTracker.settings.colors.bgall.blue) else - EmpyPopTracker.text:bg_color(0, 0, 0) + EmpyPopTracker.text:bg_color(EmpyPopTracker.settings.text.red, EmpyPopTracker.settings.text.green, EmpyPopTracker.settings.text.blue) end if EmpyPopTracker.settings.visible then EmpyPopTracker.text:visible(true) diff --git a/addons/EmpyPopTracker/README.md b/addons/EmpyPopTracker/README.md index 5fd2550af6..5ff3d1214f 100644 --- a/addons/EmpyPopTracker/README.md +++ b/addons/EmpyPopTracker/README.md @@ -6,6 +6,8 @@ An FFXI Windower 4 addon that tracks items and key items for popping various NMs Originally developed to track Abyssea Empyrean weapon NMs, hence the name. Key items are identified by the Zhe (Ж) character. Treasure pool counts for pop items are listed in amber after the item in the format of [3] (assuming 3 of that item in the pool). +All text colours are configurable via the auto-generated settings.xml file. + ## Load `//lua load empypoptracker` @@ -48,6 +50,6 @@ Fistule is a unique NM when compared to the others. It does not require KIs that ## Contributing -Notice something not quite right? [Raise an issue](https://github.com/xurion/ffxi-empy-pop-tracker/issues). +If there's an NM you want to have added, or if you notice something not quite right, please [raise an issue](https://github.com/xurion/ffxi-empy-pop-tracker/issues). -[Pull requests](https://github.com/xurion/ffxi-empy-pop-tracker/pulls) welcome! +Or better yet, [pull requests](https://github.com/xurion/ffxi-empy-pop-tracker/pulls) are welcome! diff --git a/addons/EmpyPopTracker/nms/chloris.lua b/addons/EmpyPopTracker/nms/chloris.lua index df7451eedb..875b5bff23 100644 --- a/addons/EmpyPopTracker/nms/chloris.lua +++ b/addons/EmpyPopTracker/nms/chloris.lua @@ -78,6 +78,10 @@ return { dropped_from = { name = 'Ophanim, Forced (G-9)', pops = { { + id = 2917, --Bloodshot Hecteye + type = 'item', + dropped_from = { name = 'Beholder (G-9)' } + }, { id = 2946, --Tarnished Pincer type = 'item', dropped_from = { @@ -86,21 +90,17 @@ return { id = 2916, --High-quality Limule Pincer type = 'item', dropped_from = { name = 'Gulch Limule (H-10)' } - }, { - id = 2917, --Bloodshot Hecteye - type = 'item', - dropped_from = { name = 'Beholder (G-9)' } - }, { - id = 2945, --Shriveled Wing + } } + } + }, { + id = 2945, --Shriveled Wing + type = 'item', + dropped_from = { + name = 'Halimede, Forced (G-12)', + pops = { { + id = 2915, --High-quality Clionid Wing type = 'item', - dropped_from = { - name = 'Halimede, Forced (G-12)', - pops = { { - id = 2915, --High-quality Clionid Wing - type = 'item', - dropped_from = { name = 'Gully Clionid (G-12)' } - } } - } + dropped_from = { name = 'Gully Clionid (G-12)' } } } } } } From 6f4231e067d14f3cedd3556ffebfc80f5c72e370 Mon Sep 17 00:00:00 2001 From: danpelope Date: Thu, 12 Mar 2020 03:02:11 -0400 Subject: [PATCH 0363/1002] Trusts - new trust Add support for Monberaux (added in March 2020 version update) --- addons/Trusts/Trusts.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/Trusts/Trusts.lua b/addons/Trusts/Trusts.lua index 20cf4aa647..331788b1f7 100644 --- a/addons/Trusts/Trusts.lua +++ b/addons/Trusts/Trusts.lua @@ -368,4 +368,5 @@ trusts = T{ [118]={id=1018,japanese="イロハII",english="Iroha II",name="Iroha",models=3112}, [119]={id=1019,japanese="シャントットII",english="Shantotto II",name="Shantotto",models=3110}, -- [120]={id=1003,japanese="コーネリア",english="Cornelia",name="Cornelia",models=3119}, --goodbye, my love + [121]={id=999,japanese="モンブロー",english="Monberaux",name="Monberaux",models=3120}, } From d7c47f77691bed20afc1a28347a8c9fe1fcf78be Mon Sep 17 00:00:00 2001 From: danpelope Date: Thu, 12 Mar 2020 04:05:51 -0400 Subject: [PATCH 0364/1002] Trusts whitespace My apologies. --- addons/Trusts/Trusts.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/Trusts/Trusts.lua b/addons/Trusts/Trusts.lua index 331788b1f7..ca911df186 100644 --- a/addons/Trusts/Trusts.lua +++ b/addons/Trusts/Trusts.lua @@ -368,5 +368,5 @@ trusts = T{ [118]={id=1018,japanese="イロハII",english="Iroha II",name="Iroha",models=3112}, [119]={id=1019,japanese="シャントットII",english="Shantotto II",name="Shantotto",models=3110}, -- [120]={id=1003,japanese="コーネリア",english="Cornelia",name="Cornelia",models=3119}, --goodbye, my love - [121]={id=999,japanese="モンブロー",english="Monberaux",name="Monberaux",models=3120}, + [121]={id=999,japanese="モンブロー",english="Monberaux",name="Monberaux",models=3120}, } From f900ce8dec3f857f68639a3cdb9c616d2fde7a2e Mon Sep 17 00:00:00 2001 From: Ivaar <7287342+Ivaar@users.noreply.github.com> Date: Thu, 12 Mar 2020 21:02:33 -0700 Subject: [PATCH 0365/1002] Slips.lua: March 2020 update --- addons/libs/slips.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 2b5f752a44..74480b33c7 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,8 +34,8 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757}, -- 191 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453,}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454,}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740}, -- 112 - [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070}, --168 + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 26545, 21977, 21978}, -- 115 + [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005}, --170 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330,}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665,}, --115 [slips.storages[26]] = L{23063, 23130, 23197, 23264, 23331, 23064, 23131, 23198, 23265, 23332, 23065, 23132, 23199, 23266, 23333, 23066, 23133, 23200, 23267, 23334, 23067, 23134, 23201, 23268, 23335, 23068, 23135, 23202, 23269, 23336, 23069, 23136, 23203, 23270, 23337, 23070, 23137, 23204, 23271, 23338, 23071, 23138, 23205, 23272, 23339, 23072, 23139, 23206, 23273, 23340, 23073, 23140, 23207, 23274, 23341, 23074, 23141, 23208, 23275, 23342, 23075, 23142, 23209, 23276, 23343, 23076, 23143, 23210, 23277, 23344, 23077, 23144, 23211, 23278, 23345, 23078, 23145, 23212, 23279, 23346, 23079, 23146, 23213, 23280, 23347, 23080, 23147, 23214, 23281, 23348, 23081, 23148, 23215, 23282, 23349, 23082, 23149, 23216, 23283, 23350, 23083, 23150, 23217, 23284, 23351, 23084, 23151, 23218, 23285, 23352,}, --110 From 7d84f6927837bcc5e414fe94019d39184b32d739 Mon Sep 17 00:00:00 2001 From: dtw Date: Fri, 13 Mar 2020 13:00:02 +0000 Subject: [PATCH 0366/1002] Change color of recommended action Just to make it stand out more in the log. --- addons/boxdestroyer/boxdestroyer.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/addons/boxdestroyer/boxdestroyer.lua b/addons/boxdestroyer/boxdestroyer.lua index a75e025564..0d0f7dbdab 100644 --- a/addons/boxdestroyer/boxdestroyer.lua +++ b/addons/boxdestroyer/boxdestroyer.lua @@ -67,6 +67,10 @@ observed_default = { thief_tools = {[1022] = true} +-- color codes for ease of use +txt = {} +txt[36] = string.char(31,36) -- yellow + -- global variables box = {} @@ -285,9 +289,9 @@ function display(id, chances) windower.add_to_chat(207, 'best guess: %d (%d%%)':format(box[id][math.ceil(#box[id] / 2)], 1 / remaining * 100)) local clue_value,guess_value = calculate_odds(id,chances) if clue_value > guess_value and remaining ~= 1 then - windower.add_to_chat(207, 'boxdestroyer recommends examining the chest') + windower.add_to_chat(207, 'boxdestroyer recommends'..txt[36]..' examining the chest') else - windower.add_to_chat(207, 'boxdestroyer recommends guessing %d':format(box[id][math.ceil(#box[id] / 2)])) + windower.add_to_chat(207, 'boxdestroyer recommends guessing'..txt[36]..' %d':format(box[id][math.ceil(#box[id] / 2)])) end end From e6b880d3d6fcaf2f9eaf0063cdd447c4471eb1cd Mon Sep 17 00:00:00 2001 From: dtw Date: Fri, 13 Mar 2020 13:01:00 +0000 Subject: [PATCH 0367/1002] Capitalize chat msgs Because OCD --- addons/boxdestroyer/boxdestroyer.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/boxdestroyer/boxdestroyer.lua b/addons/boxdestroyer/boxdestroyer.lua index 0d0f7dbdab..3c5802cd21 100644 --- a/addons/boxdestroyer/boxdestroyer.lua +++ b/addons/boxdestroyer/boxdestroyer.lua @@ -261,9 +261,9 @@ end function display(id, chances) if #box[id] == 90 then - windower.add_to_chat(207, 'possible combinations: 10~99') + windower.add_to_chat(207, 'Possible combinations: 10~99') else - windower.add_to_chat(207, 'possible combinations: ' .. table.concat(box[id], ' ')) + windower.add_to_chat(207, 'Possible combinations: ' .. table.concat(box[id], ' ')) end local remaining = math.floor(#box[id] / math.pow(2, (chances - 1))) if remaining == 0 then @@ -277,13 +277,13 @@ function display(id, chances) local printed = false for _,v in pairs(box[id]) do if math.floor(v/10) == v%10 then - windower.add_to_chat(207, 'best guess: %d (%d%%)':format(v, 1 / remaining * 100)) + windower.add_to_chat(207, 'Best guess: %d (%d%%)':format(v, 1 / remaining * 100)) printed = true break end end if not printed then - windower.add_to_chat(207, 'best guess: %d (%d%%)':format(box[id][math.ceil(#box[id] / 2)], 1 / remaining * 100)) + windower.add_to_chat(207, 'Best guess: %d (%d%%)':format(box[id][math.ceil(#box[id] / 2)], 1 / remaining * 100)) end else windower.add_to_chat(207, 'best guess: %d (%d%%)':format(box[id][math.ceil(#box[id] / 2)], 1 / remaining * 100)) From 91251f0d498bcbf129441cadc951c1967b4051a2 Mon Sep 17 00:00:00 2001 From: dtw Date: Fri, 13 Mar 2020 14:44:52 +0000 Subject: [PATCH 0368/1002] Add suggested amends --- addons/boxdestroyer/boxdestroyer.lua | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/addons/boxdestroyer/boxdestroyer.lua b/addons/boxdestroyer/boxdestroyer.lua index 3c5802cd21..33e68064af 100644 --- a/addons/boxdestroyer/boxdestroyer.lua +++ b/addons/boxdestroyer/boxdestroyer.lua @@ -36,11 +36,20 @@ _addon.author = 'Seth VanHeulen (Acacia@Odin)' require('pack') require('tables') +require('chat') -- load message constants require('messages') +-- config + +config = require('config') +defaults = { + HighlightResult: false, + HighlightColor: 36, +} + -- global constants default = { @@ -67,10 +76,6 @@ observed_default = { thief_tools = {[1022] = true} --- color codes for ease of use -txt = {} -txt[36] = string.char(31,36) -- yellow - -- global variables box = {} @@ -288,11 +293,9 @@ function display(id, chances) else windower.add_to_chat(207, 'best guess: %d (%d%%)':format(box[id][math.ceil(#box[id] / 2)], 1 / remaining * 100)) local clue_value,guess_value = calculate_odds(id,chances) - if clue_value > guess_value and remaining ~= 1 then - windower.add_to_chat(207, 'boxdestroyer recommends'..txt[36]..' examining the chest') - else - windower.add_to_chat(207, 'boxdestroyer recommends guessing'..txt[36]..' %d':format(box[id][math.ceil(#box[id] / 2)])) - end + local result = clue_value > guess_value and remaining ~= 1 and 'examining the chest' or 'guessing ' .. '%d':format(box[id][math.ceil(#box[id] / 2)]) + local formatted_result = settings.HighlightResult and result:color(settings.HighlightColor) or result + windower.add_to_chat(207, 'boxdestroyer recommends ' .. formatted_result .. '.') end end From 572053b72f634975bdbd70efce5deeef1814c799 Mon Sep 17 00:00:00 2001 From: Dean James Date: Sun, 15 Mar 2020 23:06:18 +0000 Subject: [PATCH 0369/1002] EmpyPopTracker 2.2.2. Fixed issue where text bg colour would not reset. Added default bg colours to settings. --- addons/EmpyPopTracker/EmpyPopTracker.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/addons/EmpyPopTracker/EmpyPopTracker.lua b/addons/EmpyPopTracker/EmpyPopTracker.lua index 797226ddba..f2803e6d6b 100644 --- a/addons/EmpyPopTracker/EmpyPopTracker.lua +++ b/addons/EmpyPopTracker/EmpyPopTracker.lua @@ -29,7 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'Empy Pop Tracker' _addon.author = 'Dean James (Xurion of Bismarck)' _addon.commands = { 'ept', 'empypoptracker' } -_addon.version = '2.2.1' +_addon.version = '2.2.2' config = require('config') res = require('resources') @@ -70,6 +70,10 @@ defaults.colors.pool = {} defaults.colors.pool.red = 255 defaults.colors.pool.green = 170 defaults.colors.pool.blue = 0 +defaults.colors.bg = {} +defaults.colors.bg.red = 0 +defaults.colors.bg.green = 0 +defaults.colors.bg.blue = 0 defaults.colors.bgall = {} defaults.colors.bgall.red = 0 defaults.colors.bgall.green = 75 @@ -286,7 +290,7 @@ EmpyPopTracker.update = function() if generated_info.has_all_pops then EmpyPopTracker.text:bg_color(EmpyPopTracker.settings.colors.bgall.red, EmpyPopTracker.settings.colors.bgall.green, EmpyPopTracker.settings.colors.bgall.blue) else - EmpyPopTracker.text:bg_color(EmpyPopTracker.settings.text.red, EmpyPopTracker.settings.text.green, EmpyPopTracker.settings.text.blue) + EmpyPopTracker.text:bg_color(EmpyPopTracker.settings.colors.bg.red, EmpyPopTracker.settings.colors.bg.green, EmpyPopTracker.settings.colors.bg.blue) end if EmpyPopTracker.settings.visible then EmpyPopTracker.text:visible(true) From 56641863cce9dc038ef99d2dd25a950027a6e5cc Mon Sep 17 00:00:00 2001 From: Lowclock Date: Mon, 23 Mar 2020 14:51:58 -0700 Subject: [PATCH 0370/1002] Update fields.lua --- addons/libs/packets/fields.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 626fc37556..a48ce7e2ed 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2865,7 +2865,7 @@ fields.incoming[0x061] = L{ {ctype='unsigned char', label='Main Hand iLevel'}, -- 56 {ctype='unsigned char', label='_unknown5'}, -- 57 Always 00 for me {ctype='bit[5]', label='Unity ID'}, -- 58 0=None, 1=Pieuje, 2=Ayame, 3=Invincible Shield, 4=Apururu, 5=Maat, 6=Aldo, 7=Jakoh Wahcondalo, 8=Naja Salaheem, 9=Flavira - {ctype='bit[5]', label='_unknown5'}, -- 58 Danger, 00ing caused my client to crash + {ctype='bit[5]', label='Unity Rank'}, -- 58 Danger, 00ing caused my client to crash {ctype='bit[16]', label='Unity Points'}, -- 59 {ctype='bit[6]', label='_unknown6'}, -- 5A No obvious function {ctype='unsigned int', label='_junk1'}, -- 5B @@ -2917,8 +2917,8 @@ func.incoming[0x063][0x03] = L{ {ctype='unsigned short', label='_unknown2'}, -- 0E 00 00 {ctype='unsigned short', label='_unknown3'}, -- 10 76 00 {ctype='unsigned short', label='Infamy'}, -- 12 - {ctype='unsigned int', label='_unknown2'}, -- 14 00s - {ctype='unsigned int', label='_unknown3'}, -- 18 00s + {ctype='unsigned int', label='_unknown4'}, -- 14 00s + {ctype='unsigned int', label='_unknown5'}, -- 18 00s {ctype='data[64]', label='Instinct Bitfield 1'}, -- 1C See below -- Bitpacked 2-bit values. 0 = no instincts from that species, 1 == first instinct, 2 == first and second instinct, 3 == first, second, and third instinct. {ctype='data[128]', label='Monster Level Char field'}, -- 5C Mapped onto the item ID for these creatures. (00 doesn't exist, 01 is rabbit, 02 is behemoth, etc.) From e404b828a75ff0e6b80f3b5f894535587219102a Mon Sep 17 00:00:00 2001 From: Lowclock Date: Mon, 23 Mar 2020 14:54:39 -0700 Subject: [PATCH 0371/1002] Update fields.lua --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index a48ce7e2ed..d0528e4131 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2865,7 +2865,7 @@ fields.incoming[0x061] = L{ {ctype='unsigned char', label='Main Hand iLevel'}, -- 56 {ctype='unsigned char', label='_unknown5'}, -- 57 Always 00 for me {ctype='bit[5]', label='Unity ID'}, -- 58 0=None, 1=Pieuje, 2=Ayame, 3=Invincible Shield, 4=Apururu, 5=Maat, 6=Aldo, 7=Jakoh Wahcondalo, 8=Naja Salaheem, 9=Flavira - {ctype='bit[5]', label='Unity Rank'}, -- 58 Danger, 00ing caused my client to crash + {ctype='bit[5]', label='Unity Rank'}, -- 58 Danger, 00ing caused my client to crash {ctype='bit[16]', label='Unity Points'}, -- 59 {ctype='bit[6]', label='_unknown6'}, -- 5A No obvious function {ctype='unsigned int', label='_junk1'}, -- 5B From fe8cc725c0b2e059710d6ea44087ea599c381317 Mon Sep 17 00:00:00 2001 From: Lowclock Date: Mon, 23 Mar 2020 21:41:41 -0700 Subject: [PATCH 0372/1002] Corrected labels. Corrected incoming 0x065 labels for Animation and Rotation. --- addons/libs/packets/fields.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index d0528e4131..0d91a21674 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2960,8 +2960,8 @@ fields.incoming[0x065] = L{ {ctype='float', label='Y'}, -- 0C {ctype='unsigned int', label='ID', fn=id}, -- 10 {ctype='unsigned short', label='Index', fn=index}, -- 14 - {ctype='unsigned char', label='_unknown1'}, -- 16 1 observed. May indicate repositoning type. - {ctype='unsigned char', label='_unknown2'}, -- 17 Unknown, but matches the same byte of a matching spawn packet + {ctype='unsigned char', label='Animation'}, -- 16 + {ctype='unsigned char', label='Rotation'}, -- 17 {ctype='data[6]', label='_unknown3'}, -- 18 All zeros observed. } From 90ade5c7fbba0c5bda8185a5de5eea56b42f1319 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Thu, 26 Mar 2020 11:07:08 -0400 Subject: [PATCH 0373/1002] Tidying up a bit --- addons/GearSwap/flow.lua | 6 +++++- addons/GearSwap/triggers.lua | 9 +++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/addons/GearSwap/flow.lua b/addons/GearSwap/flow.lua index c65e9941fe..1c136861e4 100644 --- a/addons/GearSwap/flow.lua +++ b/addons/GearSwap/flow.lua @@ -254,7 +254,11 @@ function equip_sets_exit(swap_type,ts,val1) -- Item use packet handling here if bit.band(val1.target.spawn_type, 2) == 2 and find_inventory_item(val1.id) then -- 0x36 packet - command_registry[ts].proposed_packet = assemble_menu_item_packet(val1.target.id,val1.target.index,val1.id) + if val1.target.distance <= 6 then + command_registry[ts].proposed_packet = assemble_menu_item_packet(val1.target.id,val1.target.index,val1.id) + else + windower.add_to_chat(67, "Target out of range.") + end elseif find_usable_item(val1.id) then -- 0x37 packet command_registry[ts].proposed_packet = assemble_use_item_packet(val1.target.id,val1.target.index,val1.id) diff --git a/addons/GearSwap/triggers.lua b/addons/GearSwap/triggers.lua index 47f2015ee4..6c863061ee 100644 --- a/addons/GearSwap/triggers.lua +++ b/addons/GearSwap/triggers.lua @@ -135,9 +135,14 @@ windower.register_event('outgoing text',function(original,modified,blocked,ffxi, if spell.prefix == '/item' then -- Item use packet handling here - if bit.band(spell.target.spawn_type, 2) == 2 and find_inventory_item(spell.id) then + if bit.band(spell.target.spawn_type, 2) == 2 and find_inventory_item(spell.id) and then --0x36 packet - command_registry[ts].proposed_packet = assemble_menu_item_packet(spell.target.id,spell.target.index,spell.id) + if spell.target.distance <= 6 then + command_registry[ts].proposed_packet = assemble_menu_item_packet(spell.target.id,spell.target.index,spell.id) + else + windower.add_to_chat(67, "Target out of range.") + return true + end elseif find_usable_item(spell.id) then --0x37 packet command_registry[ts].proposed_packet = assemble_use_item_packet(spell.target.id,spell.target.index,spell.id) From e8d86c27b3b07b203042b208656e29354f550d32 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Thu, 26 Mar 2020 11:11:43 -0400 Subject: [PATCH 0374/1002] Update triggers.lua --- addons/GearSwap/triggers.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/GearSwap/triggers.lua b/addons/GearSwap/triggers.lua index 6c863061ee..be7f213538 100644 --- a/addons/GearSwap/triggers.lua +++ b/addons/GearSwap/triggers.lua @@ -135,7 +135,7 @@ windower.register_event('outgoing text',function(original,modified,blocked,ffxi, if spell.prefix == '/item' then -- Item use packet handling here - if bit.band(spell.target.spawn_type, 2) == 2 and find_inventory_item(spell.id) and then + if bit.band(spell.target.spawn_type, 2) == 2 and find_inventory_item(spell.id) then --0x36 packet if spell.target.distance <= 6 then command_registry[ts].proposed_packet = assemble_menu_item_packet(spell.target.id,spell.target.index,spell.id) From e56eea6a29417bcfed453a49eca0d1ef14e50bb1 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Fri, 27 Mar 2020 00:52:25 -0400 Subject: [PATCH 0375/1002] fixing varibles --- addons/boxdestroyer/boxdestroyer.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/boxdestroyer/boxdestroyer.lua b/addons/boxdestroyer/boxdestroyer.lua index 33e68064af..7231082640 100644 --- a/addons/boxdestroyer/boxdestroyer.lua +++ b/addons/boxdestroyer/boxdestroyer.lua @@ -46,8 +46,8 @@ require('messages') config = require('config') defaults = { - HighlightResult: false, - HighlightColor: 36, + HighlightResult = false, + HighlightColor = 36, } -- global constants From 0e9318e55307f6cc596f852de41786b0f9ddae81 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Fri, 27 Mar 2020 05:40:47 -0400 Subject: [PATCH 0376/1002] Update organizer.lua --- addons/organizer/organizer.lua | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/addons/organizer/organizer.lua b/addons/organizer/organizer.lua index 88f485854a..93898f97c1 100644 --- a/addons/organizer/organizer.lua +++ b/addons/organizer/organizer.lua @@ -51,7 +51,10 @@ _static = { sack=6, case=7, wardrobe=8, - safe2=9 + safe2=9, + wardrobe2=10, + wardrobe3=11, + wardrobe4=12, } } @@ -67,14 +70,15 @@ _valid_dump = {} default_settings = { dump_bags = {['Safe']=1,['Safe2']=2,['Locker']=3,['Storage']=4}, - bag_priority = {['Safe']=1,['Safe2']=2,['Locker']=3,['Storage']=4,['Satchel']=5,['Sack']=6,['Case']=7,['Inventory']=8,['Wardrobe']=9}, + bag_priority = {['Safe']=1,['Safe2']=2,['Locker']=3,['Storage']=4,['Satchel']=5,['Sack']=6,['Case']=7,['Inventory']=8,['Wardrobe']=9,['Wardrobe2']=10,['Wardrobe3']=11,['Wardrobe4']=12,}, item_delay = 0, ignore = {}, retain = { ["moogle_slip_gear"]=false, ["seals"]=false, ["items"]=false, - ["slips"]=false + ["slips"]=false, + ["some_slips_gear"]={}, }, auto_heal = false, default_file='default.lua', @@ -214,6 +218,12 @@ function options_load( ) _valid_pull[0] = 1 _valid_dump[8] = 1 _valid_pull[8] = 1 + _valid_dump[10] = 1 + _valid_pull[10] = 1 + _valid_dump[11] = 1 + _valid_pull[11] = 1 + _valid_dump[12] = 1 + _valid_pull[12] = 1 end From 2e6bd9bc0166e814749caae37921dc8608d4b1df Mon Sep 17 00:00:00 2001 From: Chiaia Date: Sat, 28 Mar 2020 03:40:26 -0400 Subject: [PATCH 0377/1002] Update boxdestroyer.lua --- addons/boxdestroyer/boxdestroyer.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/boxdestroyer/boxdestroyer.lua b/addons/boxdestroyer/boxdestroyer.lua index 7231082640..af70616bba 100644 --- a/addons/boxdestroyer/boxdestroyer.lua +++ b/addons/boxdestroyer/boxdestroyer.lua @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- addon information _addon.name = 'boxdestroyer' -_addon.version = '1.0.4' +_addon.version = '1.0.5' _addon.command = 'boxdestroyer' _addon.author = 'Seth VanHeulen (Acacia@Odin)' @@ -49,7 +49,7 @@ defaults = { HighlightResult = false, HighlightColor = 36, } - +settings = config.load(defaults) -- global constants default = { From 896a5cc7c293663328f2d9dde950a9808e1c736a Mon Sep 17 00:00:00 2001 From: Chiaia Date: Sat, 28 Mar 2020 04:04:41 -0400 Subject: [PATCH 0378/1002] Update organizer.lua --- addons/organizer/organizer.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/addons/organizer/organizer.lua b/addons/organizer/organizer.lua index 93898f97c1..a4b3b774fb 100644 --- a/addons/organizer/organizer.lua +++ b/addons/organizer/organizer.lua @@ -37,7 +37,7 @@ config = require 'config' _addon.name = 'Organizer' _addon.author = 'Byrth, maintainer: Rooks' -_addon.version = 0.20150923 +_addon.version = 0.20200328 _addon.commands = {'organizer','org'} _static = { @@ -78,7 +78,6 @@ default_settings = { ["seals"]=false, ["items"]=false, ["slips"]=false, - ["some_slips_gear"]={}, }, auto_heal = false, default_file='default.lua', From 1c712cde3a90c47e88486c0a824430c4fd875061 Mon Sep 17 00:00:00 2001 From: posimagi Date: Sun, 5 Apr 2020 14:39:17 -0700 Subject: [PATCH 0379/1002] battlemod: Englishier monster level upon check --- addons/battlemod/battlemod.lua | 4 ++-- addons/battlemod/statics.lua | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index 494ed3fc34..f8d9ed3652 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -352,9 +352,9 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec if am.message_id > 169 and am.message_id <179 then if am.param_1 > 2147483647 then - skill = 'like level -1 ('..ratings_arr[am.param_2-63]..')' + skill = 'to be level -1 ('..ratings_arr[am.param_2-63]..')' else - skill = 'like level '..am.param_1..' ('..ratings_arr[am.param_2-63]..')' + skill = 'to be level '..am.param_1..' ('..ratings_arr[am.param_2-63]..')' end end local outstr = (res.action_messages[am.message_id][language] diff --git a/addons/battlemod/statics.lua b/addons/battlemod/statics.lua index a6dc6d33b3..01e9ddd463 100644 --- a/addons/battlemod/statics.lua +++ b/addons/battlemod/statics.lua @@ -25,7 +25,7 @@ --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','EEP','EP','DC','EM','T','VT','IT'} +ratings_arr = {'TW','IEP','EP','DC','EM','T','VT','IT'} current_job = 'NONE' default_filt = false rcol = string.char(0x1E,0x01) From e46e0aa23d82551ec5f3575b426b0668f40ab9d3 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Tue, 7 Apr 2020 16:14:00 +0200 Subject: [PATCH 0380/1002] Strings: Added string.encode --- addons/libs/strings.lua | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/addons/libs/strings.lua b/addons/libs/strings.lua index 6f653acd02..9a4ee5ac5a 100644 --- a/addons/libs/strings.lua +++ b/addons/libs/strings.lua @@ -434,7 +434,6 @@ string.decode = (function() return function(str, charset) if type(charset) == 'string' then - local tmp = charset charset = charset:sub(2):split() charset[0] = charset:sub(1, 1) end @@ -442,6 +441,22 @@ string.decode = (function() end end)() +-- Returns a string encoded given the appropriate information. +string.encode = (function() + local chunk_size = function(t) + local e, f = math.frexp(#t) + return f + math.ceil(e - 1.5) + end + + return function(str, charset) + if type(charset) == 'string' then + charset = charset:sub(2):split() + charset[0] = charset:sub(1, 1) + end + return str:map(string.zfill-{chunk_size(charset)} .. math.binary .. table.find+{charset}):parse_binary() + end +end)() + -- Returns a plural version of a string, if the provided table contains more than one element. -- Defaults to appending an s, but accepts an option string as second argument which it will the string with. function string.plural(str, t, replace) From 36d45b30225cde3f0ed7b20320c505eb57ccc9d8 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Tue, 7 Apr 2020 16:45:04 +0200 Subject: [PATCH 0381/1002] Packets: Added encoding mechanism to packets.build --- addons/libs/packets.lua | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/addons/libs/packets.lua b/addons/libs/packets.lua index dd2b90a58b..d63bef3c18 100644 --- a/addons/libs/packets.lua +++ b/addons/libs/packets.lua @@ -10,7 +10,6 @@ require('strings') require('functions') require('pack') -local list, math, string, functions = _libs.lists, _libs.maths, _libs.strings local table = require('table') local packets = {} @@ -69,7 +68,7 @@ local sizes = { } -- This defines whether to treat a type with brackets at the end as an array or something special -local non_array_types = S{'bit', 'data', 'char'} +local non_array_types = S{'bit', 'data', 'char'} -- Pattern to match variable size array local pointer_pattern = '(.+)%*' @@ -100,7 +99,7 @@ local size size = function(fields, count) -- A single field if fields.ctype then - local bits, type_count, type = parse_type(fields) + local bits, _, type = parse_type(fields) return bits or count * sizes[type] end @@ -394,6 +393,11 @@ function packets.new(dir, id, values, ...) return packet end +local lookup = function(packet, field) + local val = packet[field.label] + return field.enc and val:rpad(size(field), 0:char()):encode(field.enc) or val +end + -- Returns binary data from a packet function packets.build(packet) local fields = packets.fields(packet._dir, packet._id, packet._raw, unpack(packet._args or {})) @@ -403,7 +407,7 @@ function packets.build(packet) end local pack_string = fields:map(make_pack_string):concat() - local data = pack_string:pack(fields:map(table.lookup-{packet, 'label'}):unpack()) + local data = pack_string:pack(fields:map(lookup+{packet}):unpack()) local rem = #data % 4 if rem ~= 0 then data = data .. 0:char():rep(4 - rem) From 193ada7145746d8ff83a25bc8c53de8c6cb03b6d Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Tue, 7 Apr 2020 17:07:00 +0200 Subject: [PATCH 0382/1002] Packets: Fixed encoded string handling --- addons/libs/packets.lua | 2 +- addons/libs/packets/fields.lua | 4 ++-- addons/libs/strings.lua | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/addons/libs/packets.lua b/addons/libs/packets.lua index d63bef3c18..bf31403367 100644 --- a/addons/libs/packets.lua +++ b/addons/libs/packets.lua @@ -395,7 +395,7 @@ end local lookup = function(packet, field) local val = packet[field.label] - return field.enc and val:rpad(size(field), 0:char()):encode(field.enc) or val + return field.enc and (val .. 0:char()):encode(field.enc) or val end -- Returns binary data from a packet diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 0d91a21674..2d0701da9c 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -21,7 +21,7 @@ local func = { -- String decoding definitions local ls_name_msg = T('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ':split()) -ls_name_msg[0] = 0:char() +ls_name_msg[63] = 0:char() local item_inscr = T('0123456798ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz{':split()) item_inscr[0] = 0:char() local ls_name_ext = T(('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' .. 0:char():rep(11)):split()) @@ -3264,7 +3264,7 @@ fields.incoming[0x0CC] = L{ {ctype='unsigned int', label='Timestamp', fn=time}, -- 88 {ctype='char[16]', label='Player Name'}, -- 8C {ctype='unsigned int', label='Permissions'}, -- 98 - {ctype='char[16]', label='Linkshell', enc=ls_name_msg}, -- 9C 6-bit packed + {ctype='char[15]', label='Linkshell', enc=ls_name_msg}, -- 9C 6-bit packed } -- Found Item diff --git a/addons/libs/strings.lua b/addons/libs/strings.lua index 9a4ee5ac5a..c804ddfe98 100644 --- a/addons/libs/strings.lua +++ b/addons/libs/strings.lua @@ -189,12 +189,12 @@ function string.capitalize(str) return table.concat(res, ' ') end --- Takes a padding character pad and pads the string str to the left of it, until len is reached. pad defaults to a space. +-- Takes a padding character pad and pads the string str to the left of it, until len is reached. function string.lpad(str, pad, len) return (pad:rep(len) .. str):sub(-(len > #str and len or #str)) end --- Takes a padding character pad and pads the string str to the right of it, until len is reached. pad defaults to a space. +-- Takes a padding character pad and pads the string str to the right of it, until len is reached. function string.rpad(str, pad, len) return (str .. pad:rep(len)):sub(1, len > #str and len or #str) end From 1c3e6f6d346f6b4c9d03775cc89d776c99deed68 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Wed, 8 Apr 2020 18:08:14 +0200 Subject: [PATCH 0383/1002] Strings: Fixed various encoding issues --- addons/libs/packets/fields.lua | 27 ++++++++++----- addons/libs/strings.lua | 63 ++++++++++++++-------------------- 2 files changed, 44 insertions(+), 46 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 2d0701da9c..4394575f57 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -20,12 +20,23 @@ local func = { } -- String decoding definitions -local ls_name_msg = T('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ':split()) -ls_name_msg[63] = 0:char() -local item_inscr = T('0123456798ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz{':split()) -item_inscr[0] = 0:char() -local ls_name_ext = T(('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' .. 0:char():rep(11)):split()) -ls_name_ext[0] = '`' +local ls_enc = { + charset = T('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ':split()):update({ + [0] = '`', + [60] = 0:char(), + [63] = 0:char(), + }), + bits = 6, + terminator = function(str) + return (#str % 4 == 2 and 0x60 or 0x63):char() + end +} +local sign_enc = { + charset = T('0123456798ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz{':split()):update({ + [0] = 0:char(), + }), + bits = 6, +} -- Function definitions. Used to display packet field information. local res = require('resources') @@ -3243,7 +3254,7 @@ func.incoming[0x0C9][0x01] = L{ {ctype='bit[4]', label='_junk1'}, -- 11 {ctype='unsigned char', label='Main Job', fn=job}, -- 12 {ctype='unsigned char', label='Sub Job', fn=job}, -- 13 - {ctype='char[16]', label='Linkshell', enc=ls_name_msg}, -- 14 6-bit packed + {ctype='char[16]', label='Linkshell', enc=ls_enc}, -- 14 6-bit packed {ctype='unsigned char', label='Main Job Level'}, -- 24 {ctype='unsigned char', label='Sub Job Level'}, -- 25 {ctype='data[42]', label='_unknown5'}, -- 26 At least the first two bytes and the last twelve bytes are junk, possibly more @@ -3264,7 +3275,7 @@ fields.incoming[0x0CC] = L{ {ctype='unsigned int', label='Timestamp', fn=time}, -- 88 {ctype='char[16]', label='Player Name'}, -- 8C {ctype='unsigned int', label='Permissions'}, -- 98 - {ctype='char[15]', label='Linkshell', enc=ls_name_msg}, -- 9C 6-bit packed + {ctype='char[15]', label='Linkshell', enc=ls_enc}, -- 9C 6-bit packed } -- Found Item diff --git a/addons/libs/strings.lua b/addons/libs/strings.lua index c804ddfe98..835413e694 100644 --- a/addons/libs/strings.lua +++ b/addons/libs/strings.lua @@ -41,8 +41,7 @@ function string.psplit(str, sep, maxsplit, include) return str:split(sep, maxsplit, include, false) end --- Splits a string into a table by a separator string. -function string.split(str, sep, maxsplit, include, raw) +local rawsplit = function(str, sep, maxsplit, include, raw) if not sep or sep == '' then local res = {} local key = 0 @@ -51,12 +50,7 @@ function string.split(str, sep, maxsplit, include, raw) res[key] = c end - if _meta.L then - res.n = key - return setmetatable(res, _meta.L) - end - - return setmetatable(res, _meta.T and _meta.T or nil) + return res, key end maxsplit = maxsplit or 0 @@ -98,12 +92,23 @@ function string.split(str, sep, maxsplit, include, raw) end end + return res, key +end + +-- Splits a string into a table by a separator string. +function string.split(str, sep, maxsplit, include, raw) + local res, key = rawsplit(str, sep, maxsplit, include, raw) + if _meta.L then res.n = key return setmetatable(res, _meta.L) end - return setmetatable(res, _meta.T and _meta.T or nil) + if _meta.T then + return setmetatable(res, _meta.T) + end + + return res end -- Alias to string.sub, with some syntactic sugar. @@ -425,37 +430,19 @@ function string.chunks(str, size) end end --- Returns a string decoded given the appropriate information. -string.decode = (function() - local chunk_size = function(t) - local e, f = math.frexp(#t) - return f + math.ceil(e - 1.5) - end - - return function(str, charset) - if type(charset) == 'string' then - charset = charset:sub(2):split() - charset[0] = charset:sub(1, 1) - end - return str:binary():chunks(chunk_size(charset)):map(table.get+{charset} .. tonumber-{2}):concat():gsub('%z+$', '') - end -end)() - --- Returns a string encoded given the appropriate information. -string.encode = (function() - local chunk_size = function(t) - local e, f = math.frexp(#t) - return f + math.ceil(e - 1.5) - end +-- Returns a string decoded given the appropriate encoding. +string.decode = function(str, encoding) + return (str:binary():chunks(encoding.bits):map(table.get+{encoding.charset} .. tonumber-{2}):concat():gsub('%z+$', '')) +end - return function(str, charset) - if type(charset) == 'string' then - charset = charset:sub(2):split() - charset[0] = charset:sub(1, 1) - end - return str:map(string.zfill-{chunk_size(charset)} .. math.binary .. table.find+{charset}):parse_binary() +-- Returns a string encoded given the appropriate encoding. +string.encode = function(str, encoding) + local binary = str:map(string.zfill-{encoding.bits} .. math.binary .. table.find+{encoding.charset}) + if encoding.terminator then + binary = binary .. encoding.terminator(str):binary() end -end)() + return binary:rpad('0', (#binary / 8):ceil() * 8):parse_binary() +end -- Returns a plural version of a string, if the provided table contains more than one element. -- Defaults to appending an s, but accepts an option string as second argument which it will the string with. From 401fb7613024dc451648ed7a4d691693033b31c0 Mon Sep 17 00:00:00 2001 From: Krizz Date: Fri, 10 Apr 2020 09:38:09 -0400 Subject: [PATCH 0384/1002] Salvage2 Update I have restructured parts of Salvage2 so that it uses the new Texts for boxes, and it now works again. --- addons/salvage2/data/settings.xml | 55 ++++++++++++++++++--- addons/salvage2/salvage2.lua | 80 ++++++++++++++++--------------- 2 files changed, 91 insertions(+), 44 deletions(-) diff --git a/addons/salvage2/data/settings.xml b/addons/salvage2/data/settings.xml index 08ba0f7f94..725855ecb9 100644 --- a/addons/salvage2/data/settings.xml +++ b/addons/salvage2/data/settings.xml @@ -1,7 +1,50 @@ - + - - 1000 - 250 - - \ No newline at end of file + + + 200 + 30 + 30 + 30 + true + + + 200 + 200 + 200 + 200 + + + false + false + true + false + false + + 0 + + 1000 + 150 + + 900 + 250 + + 255 + 255 + Arial + + + + 255 + 255 + 12 + + 255 + 0 + 0 + 0 + 0 + + + + diff --git a/addons/salvage2/salvage2.lua b/addons/salvage2/salvage2.lua index 4e8fb289ae..a42ed78d0e 100644 --- a/addons/salvage2/salvage2.lua +++ b/addons/salvage2/salvage2.lua @@ -30,31 +30,33 @@ require('tables') require('strings') require('maths') require('logger') +texts = require 'texts' config = require('config') ----------------------------- -settingtab = config.load() --variables - posx = 1000 - posy = 250 - if settingtab['posx'] ~= nil then - posx = settingtab['posx'] - posy = settingtab['posy'] - end - pathos_ident = {'Main Weapon/Sub-Weapon restriction', 'Ranged Weapon/Ammo restriction', 'Head/Neck equipment restriction', 'Body equipment restriction', 'Hand equipment restriction', 'Earrings/Rings restriction', 'Back/Waist equipment restriction', 'Leg/Foot equipment restriction', 'Support Job restriction', 'Job Abilities restriction', 'Spellcasting restriction', 'Max HP Down', 'Max MP Down', 'STR Down', 'DEX Down', 'AGI Down', 'MND Down', 'INT Down', 'CHR Down', 'VIT Down'} - pathos_short = {'Weapon', 'Ranged', 'Head/Neck', 'Body', 'Hand', 'Earrings/Rings', 'Back/Waist', 'Leg/Foot', 'Support Job', 'Job Abilities', 'Spellcasting', 'Max HP', 'Max MP', 'STR', 'DEX', 'AGI', 'MND', 'INT', 'CHR', 'VIT'} +pathos_ident = {'Main Weapon/Sub-Weapon restriction', 'Ranged Weapon/Ammo restriction', 'Head/Neck equipment restriction', 'Body equipment restriction', 'Hand equipment restriction', 'Earrings/Rings restriction', 'Back/Waist equipment restriction', 'Leg/Foot equipment restriction', 'Support Job restriction', 'Job Abilities restriction', 'Spellcasting restriction', 'Max HP Down', 'Max MP Down', 'STR Down', 'DEX Down', 'AGI Down', 'MND Down', 'INT Down', 'CHR Down', 'VIT Down'} +pathos_short = {'Weapon', 'Ranged', 'Head/Neck', 'Body', 'Hand', 'Earrings/Rings', 'Back/Waist', 'Leg/Foot', 'Support Job', 'Job Abilities', 'Spellcasting', 'MaxHP', 'MaxMP', 'STR', 'DEX', 'AGI', 'MND', 'INT', 'CHR', 'VIT'} +salvage_zones = S{73, 74, 75, 76} -function settings_create() - -- get player's name - player = windower.ffxi.get_player()['name'] - -- set all pathos as needed - for i=1, #pathos_ident do - if pathos_ident[i] ~= nil then - pathos_ident[pathos_ident[i]] = 1 - end - end -end +defaults = {} +defaults.pos = {} +defaults.pos.x = 1000 +defaults.pos.y = 150 +defaults.color = {} +defaults.color.alpha = 200 +defaults.color.red = 200 +defaults.color.green = 200 +defaults.color.blue = 200 +defaults.bg = {} +defaults.bg.alpha = 200 +defaults.bg.red = 30 +defaults.bg.green = 30 +defaults.bg.blue = 30 + +settings = config.load(defaults) +salvage_box2 = texts.new('No pathos', settings) windower.register_event('addon command',function (...) local params = {...}; @@ -75,9 +77,9 @@ local params = {...}; windower.text.set_location('salvage_box2', posx, posy) end elseif params[1]:lower() == "hide" then - windower.text.set_visibility('salvage_box2', false) + salvage_box2:hide() elseif params[1]:lower() == "show" then - windower.text.set_visibility('salvage_box2', true) + salvage_box2:show() elseif params[1]:lower() == "timer" then if params[2] == "start" then windower.send_command('timers c Remaining 6000 up') @@ -88,11 +90,11 @@ local params = {...}; if params[2]:lower() == "start" then windower.send_command('timers c Remaining 6000 up') settings_create() - windower.text.set_visibility('salvage_box2', true) + salvage_box2:show() initialize() elseif params[2]:lower() == "stop" then windower.send_command('timers d Remaining') - windower.text.set_visibility('salvage_box2', false) + salvage_box2:hide() end elseif params[1]:lower() == "remove" then for i=1, #pathos_short do @@ -109,29 +111,37 @@ windower.register_event('login', function(name) player = name end) -salvage_zones = S{73, 74, 75, 76} +function settings_create() + -- get player's name + player = windower.ffxi.get_player()['name'] + -- set all pathos as needed + for i=1, #pathos_ident do + if pathos_ident[i] ~= nil then + pathos_ident[pathos_ident[i]] = 1 + end + end +end windower.register_event('zone change', function(id) if salvage_zones:contains(id) then windower.send_command('timers c Remaining 6000 up') settings_create() initialize() - windower.text.set_visibility('salvage_box2', true) + salvage_box2:show() else windower.send_command('timers d Remaining') settings_create() initialize() - windower.text.set_visibility('salvage_box2', false) + salvage_box2:hide() end end) windower.register_event('incoming text',function (original, new, color) - - a,b,pathos,name = string.find(original,'..(.*) removed for (%w+)\46') - + original = original:strip_format() + local pathos, name = original:match('(.*) removed for (%w+)') if pathos ~= nil then + --print('Pathos found '..pathos) if name == player then - -- Insert code to remove pathos from list for i=1, #pathos_ident do if pathos_ident[i]:lower() == pathos:lower() then if pathos_ident[pathos_ident[i]] == 1 then @@ -153,15 +163,9 @@ function initialize() pathos_remain = (pathos_remain..item..' \n ') end end - windower.text.create('salvage_box2') - windower.text.set_bg_color('salvage_box2',200,30,30,30) - windower.text.set_color('salvage_box2',255,200,200,200) - windower.text.set_location('salvage_box2',posx,posy) - windower.text.set_bg_visibility('salvage_box2',1) - windower.text.set_font('salvage_box2','Arial',12) - windower.text.set_text('salvage_box2', pathos_remain) + salvage_box2:text(pathos_remain) if pathos_remain == (" Pathos Remaining: \n ") then - windower.text.set_visibility('salvage_box2',false) + salvage_box2:hide() end end From 4554c09b124c0de841855f8c15d0008d69da8b90 Mon Sep 17 00:00:00 2001 From: Krizz Date: Fri, 10 Apr 2020 09:45:32 -0400 Subject: [PATCH 0385/1002] DynamisHelper Update Change textbox method to use Texts, and made other structure adjustments. --- addons/dynamishelper/data/settings.xml | 108 +++++++++-- addons/dynamishelper/dynamishelper.lua | 238 ++++++++++++++----------- 2 files changed, 233 insertions(+), 113 deletions(-) diff --git a/addons/dynamishelper/data/settings.xml b/addons/dynamishelper/data/settings.xml index dbd5ac88c3..df24557d43 100644 --- a/addons/dynamishelper/data/settings.xml +++ b/addons/dynamishelper/data/settings.xml @@ -1,12 +1,100 @@ - + - - on - off - 1000 - 250 - off - 900 - 250 - + + + on + on + on + + + + 200 + 30 + 30 + 30 + true + + + 200 + 200 + 200 + 200 + + + false + false + true + false + false + + 0 + + 1000 + 150 + + + 255 + 255 + Arial + + + + 255 + 255 + 12 + + 255 + 0 + 0 + 0 + 0 + + + + + + 200 + 30 + 30 + 30 + true + + + 200 + 200 + 200 + 200 + + + false + false + true + false + false + + 0 + + 1000 + 250 + + + 255 + 255 + Arial + + + + 255 + 255 + 12 + + 255 + 0 + 0 + 0 + 0 + + + + diff --git a/addons/dynamishelper/dynamishelper.lua b/addons/dynamishelper/dynamishelper.lua index 3ba0c8c5a3..3c7aa1548b 100644 --- a/addons/dynamishelper/dynamishelper.lua +++ b/addons/dynamishelper/dynamishelper.lua @@ -36,6 +36,8 @@ _addon.version = '1.0.2.0' require('strings') require('sets') +texts = require 'texts' +require('logger') config = require('config') res = require('resources') @@ -202,23 +204,50 @@ proctype = {"ja","magic","ws","random","none"} StaggerCount = 0 current_proc = "lolidk" currentime = 0 +obtained = nil goodzone = false -timer = "off" -tracker = "off" -proc = "off" -trposx = 1000 -trposy = 250 -pposx = 800 -pposy = 250 - -settings = config.load() -timer = settings['timer'] -tracker = settings['tracker'] -trposx = settings['trposx'] -trposy = settings['trposy'] -proc = settings['proc'] -pposx = settings['pposx'] -pposy = settings['pposy'] +timer = "on" +tracker = "on" +proc = "on" +debugMode = "off" + +defaults = {} +defaults.display = {} +defaults.display.timer = "on" +defaults.display.tracker = "on" +defaults.display.proc = "on" +defaults.proc_box = {} +defaults.proc_box.pos = {} +defaults.proc_box.pos.x = 1000 +defaults.proc_box.pos.y = 200 +defaults.proc_box.color = {} +defaults.proc_box.color.alpha = 200 +defaults.proc_box.color.red = 200 +defaults.proc_box.color.green = 200 +defaults.proc_box.color.blue = 200 +defaults.proc_box.bg = {} +defaults.proc_box.bg.alpha = 200 +defaults.proc_box.bg.red = 30 +defaults.proc_box.bg.green = 30 +defaults.proc_box.bg.blue = 30 +defaults.tracker_box = {} +defaults.tracker_box.pos = {} +defaults.tracker_box.pos.x = 1000 +defaults.tracker_box.pos.y = 250 +defaults.tracker_box.color = {} +defaults.tracker_box.color.alpha = 200 +defaults.tracker_box.color.red = 200 +defaults.tracker_box.color.green = 200 +defaults.tracker_box.color.blue = 200 +defaults.tracker_box.bg = {} +defaults.tracker_box.bg.alpha = 200 +defaults.tracker_box.bg.red = 30 +defaults.tracker_box.bg.green = 30 +defaults.tracker_box.bg.blue = 30 + +settings = config.load('data\\settings.xml',defaults) +dynamis_box = texts.new(' Empty', settings.tracker_box, settings) +proc_box = texts.new(' Unknown', settings.proc_box, settings) for i=1, #Currency do Currency[Currency[i]] = 0 @@ -228,7 +257,6 @@ windower.register_event('load', 'login', function() if windower.ffxi.get_info().logged_in then player = windower.ffxi.get_player().name obtained = nil - initializebox() end end) @@ -251,60 +279,76 @@ windower.register_event('addon command',function (...) timer = params[2] print('Timer feature is '..timer) else print("Invalid timer option.") - end - elseif params[1]:lower() == "tracker" then - if params[2]:lower() == "on" then - tracker = "on" - initializebox() - windower.text.set_visibility('dynamis_box',true) - print('Tracker enabled') - elseif params[2]:lower() == "off" then - tracker = "off" - windower.text.set_visibility('dynamis_box',false) - print('Tracker disabled') - elseif params[2]:lower() == "reset" then - for i=1, #Currency do - Currency[Currency[i]] = 0 - end - obtainedf() - initializebox() - print('Tracker reset') - elseif params[2]:lower() == "pos" then - if params[3] then - trposx, trposy = tonumber(params[3]), tonumber(params[4]) - obtainedf() - initializebox() - else print("Invalid tracker option.") - end - end - elseif params[1]:lower() == "ll" then - if params[2]:lower() == "create" then - player = windower.ffxi.get_player()['name'] - io.open(windower.addon_path..'../../plugins/ll/dynamis-'..player..'.txt',"w"):write('if item is 1452, 1453, 1455, 1456, 1449, 1450 then lot'):close() - windower.send_command('ll profile dynamis-'..player..'.txt') - else print("Invalid light luggage option.") - end - elseif params[1]:lower() == "proc" then - if params[2]:lower() == "on" then - proc = params[2] - print('Proc feature enabled.') - elseif params[2]:lower() == "off" then - proc = params[2] - windower.text.set_visibility('proc_box',false) - print('Proc feature disabled.') - elseif params[2]:lower() == "pos" then - pposx, pposy = tonumber(params[3]), tonumber(params[4]) - initializeproc() - end + end + elseif params[1]:lower() == "tracker" then + if params[2]:lower() == "on" then + tracker = "on" + initializebox() + print('Tracker enabled') + elseif params[2]:lower() == "off" then + tracker = "off" + dynamis_box:hide() + print('Tracker disabled') + elseif params[2]:lower() == "reset" then + settings = config.load(trdefaults) + dynamis_box = texts.new('Nothing to show', settings) + for i=1, #Currency do + Currency[Currency[i]] = 0 + end + obtainedf() + print('Tracker reset') + elseif params[2]:lower() == "pos" then + if params[3] then + trposx, trposy = tonumber(params[3]), tonumber(params[4]) + dynamis_box:pos(posx, posy) + else print("Invalid tracker option.") + end + end + elseif params[1]:lower() == "ll" then + if params[2]:lower() == "create" then + player = windower.ffxi.get_player()['name'] + io.open(windower.addon_path..'../../plugins/ll/dynamis-'..player..'.txt',"w"):write('if item is 1452, 1453, 1455, 1456, 1449, 1450 then lot'):close() + windower.send_command('ll profile dynamis-'..player..'.txt') + else print("Invalid light luggage option.") + end + elseif params[1]:lower() == "proc" then + if params[2]:lower() == "on" then + proc = params[2] + print('Proc feature enabled.') + elseif params[2]:lower() == "off" then + proc = params[2] + proc_box:hide() + print('Proc feature disabled.') + elseif params[2]:lower() == "pos" then + pposx, pposy = tonumber(params[3]), tonumber(params[4]) + proc_box:pos(posx, posy) + end + elseif params[1]:lower() == "debug" then + if params[2]:lower() == "on" then + debugMode = "on" + goodzone = true + proc = "on" + tracker = "on" + mob = "Test" + obtained = "1" + setproc() + initializebox() + elseif params[2]:lower() == "off" then + debugMode = "off" + goodzone = ProcZones:contains(windower.ffxi.get_info().zone) + initializeproc() + initializebox() + end + end end - end end) windower.register_event('incoming text',function (original, new, color) -- print('event_incoming_text function') + original = original:strip_format() if timer == 'on' then - a,b,fiend = string.find(original,"%w+'s attack staggers the (%w+)%!") + local fiend = original:match("%w+'s attack staggers the (%w+)%!") if fiend == 'fiend' then StaggerCount = StaggerCount + 1 windower.send_command('timers c '..StaggerCount..' 30 down') @@ -312,18 +356,19 @@ windower.register_event('incoming text',function (original, new, color) end end if tracker == 'on' then - a,b,item = string.find(original,"%w+ obtains an? ..(%w+ %w+ %w+ %w+)..\46") - if item == nil then - a,b,item = string.find(original,"%w+ obtains an? ..(%w+ %w+ %w+)..\46") - if item == nil then - a,b,item = string.find(original,"%w+ obtains an? ..(%w+%-%w+ %w+)..\46") - if item == nil then - a,b,item = string.find(original,"%w+ obtains an? ..(%w+ %w+)..\46") - end - end - end --- a,b,item = string.find(original,"%w+ obtains an? ..(.*)..\46") - if item ~= nil then + if debugMode == "on" then print("Starting tracker function") end + local item = original:match("%w+ obtains an? (%w+ %w+ %w+ %w+).") + if item == nil then + item = original:match("%w+ obtains an? (%w+ %w+ %w+).") + end + if item == nil then + item = original:match("%w+ obtains an? (%w+%-%w+ %w+).") + end + if item == nil then + item = original:match("%w+ obtains an? (%w+ %w+).") + end + if item then + if debugMode == "on" then print(item) end item = item:lower() for i=1, #Currency do if item == Currency[i]:lower() then @@ -351,33 +396,28 @@ end windower.register_event('zone change', function(id) goodzone = ProcZones:contains(id) + if debugMode == "on" then goodzone = true end if not goodzone then - windower.text.set_visibility('proc_box', false) + proc_box:hide() + dynamis_box:hide() end end) function initializebox() if obtained ~= nil and tracker == "on" then - windower.text.create('dynamis_box') - windower.text.set_bg_color('dynamis_box',200,30,30,30) - windower.text.set_color('dynamis_box',255,200,200,200) - windower.text.set_location('dynamis_box',trposx,trposy) - windower.text.set_visibility('dynamis_box',true) - windower.text.set_bg_visibility('dynamis_box',true) - windower.text.set_font('dynamis_box','Arial',12) - windower.text.set_text('dynamis_box',obtained); + dynamis_box:show() + dynamis_box:text(obtained) end + end windower.register_event('target change', function(targ_id) - --goodzone = ProcZones:contains(windower.ffxi.get_info().zone) + goodzone = ProcZones:contains(windower.ffxi.get_info().zone) + if debugMode == "on" then goodzone = true end if goodzone and proc == 'on' and targ_id ~= 0 then mob = windower.ffxi.get_mob_by_index(targ_id)['name'] setproc() end - - --print(ProcZones:contains(windower.ffxi.get_info().zone)) - end) function setproc() @@ -409,23 +449,15 @@ function setproc() end function initializeproc() --- print('initializeproc function') - windower.text.create('proc_box') - windower.text.set_bg_color('proc_box',200,30,30,30) - windower.text.set_color('proc_box',255,200,200,200) - windower.text.set_location('proc_box',pposx,pposy) - if proc == 'on' then - windower.text.set_visibility('proc_box', true) - end - windower.text.set_bg_visibility('proc_box',1) - windower.text.set_font('proc_box','Arial',12) - windower.text.set_text('proc_box',' Current proc for \n '..mob..'\n is '..current_proc); - if proc == "off" then - windower.text.set_visibility('proc_box', false) + if goodzone == true and proc == 'on' then + proc_box:show() + proc_box:text(' Current proc for \n '..mob..'\n is '..current_proc) + else + proc_box:hide() end end windower.register_event('unload',function () windower.text.delete('dynamis_box') windower.text.delete('proc_box') -end) +end) \ No newline at end of file From ed30313710e724c6ce4a2ef9306f852f5d5d7e01 Mon Sep 17 00:00:00 2001 From: Krizz Date: Fri, 10 Apr 2020 10:03:10 -0400 Subject: [PATCH 0386/1002] Revert "DynamisHelper Update" This reverts commit 4554c09b124c0de841855f8c15d0008d69da8b90. --- addons/dynamishelper/data/settings.xml | 108 ++--------- addons/dynamishelper/dynamishelper.lua | 238 +++++++++++-------------- 2 files changed, 113 insertions(+), 233 deletions(-) diff --git a/addons/dynamishelper/data/settings.xml b/addons/dynamishelper/data/settings.xml index df24557d43..dbd5ac88c3 100644 --- a/addons/dynamishelper/data/settings.xml +++ b/addons/dynamishelper/data/settings.xml @@ -1,100 +1,12 @@ - + - - - on - on - on - - - - 200 - 30 - 30 - 30 - true - - - 200 - 200 - 200 - 200 - - - false - false - true - false - false - - 0 - - 1000 - 150 - - - 255 - 255 - Arial - - - - 255 - 255 - 12 - - 255 - 0 - 0 - 0 - 0 - - - - - - 200 - 30 - 30 - 30 - true - - - 200 - 200 - 200 - 200 - - - false - false - true - false - false - - 0 - - 1000 - 250 - - - 255 - 255 - Arial - - - - 255 - 255 - 12 - - 255 - 0 - 0 - 0 - 0 - - - - + + on + off + 1000 + 250 + off + 900 + 250 + diff --git a/addons/dynamishelper/dynamishelper.lua b/addons/dynamishelper/dynamishelper.lua index 3c7aa1548b..3ba0c8c5a3 100644 --- a/addons/dynamishelper/dynamishelper.lua +++ b/addons/dynamishelper/dynamishelper.lua @@ -36,8 +36,6 @@ _addon.version = '1.0.2.0' require('strings') require('sets') -texts = require 'texts' -require('logger') config = require('config') res = require('resources') @@ -204,50 +202,23 @@ proctype = {"ja","magic","ws","random","none"} StaggerCount = 0 current_proc = "lolidk" currentime = 0 -obtained = nil goodzone = false -timer = "on" -tracker = "on" -proc = "on" -debugMode = "off" - -defaults = {} -defaults.display = {} -defaults.display.timer = "on" -defaults.display.tracker = "on" -defaults.display.proc = "on" -defaults.proc_box = {} -defaults.proc_box.pos = {} -defaults.proc_box.pos.x = 1000 -defaults.proc_box.pos.y = 200 -defaults.proc_box.color = {} -defaults.proc_box.color.alpha = 200 -defaults.proc_box.color.red = 200 -defaults.proc_box.color.green = 200 -defaults.proc_box.color.blue = 200 -defaults.proc_box.bg = {} -defaults.proc_box.bg.alpha = 200 -defaults.proc_box.bg.red = 30 -defaults.proc_box.bg.green = 30 -defaults.proc_box.bg.blue = 30 -defaults.tracker_box = {} -defaults.tracker_box.pos = {} -defaults.tracker_box.pos.x = 1000 -defaults.tracker_box.pos.y = 250 -defaults.tracker_box.color = {} -defaults.tracker_box.color.alpha = 200 -defaults.tracker_box.color.red = 200 -defaults.tracker_box.color.green = 200 -defaults.tracker_box.color.blue = 200 -defaults.tracker_box.bg = {} -defaults.tracker_box.bg.alpha = 200 -defaults.tracker_box.bg.red = 30 -defaults.tracker_box.bg.green = 30 -defaults.tracker_box.bg.blue = 30 - -settings = config.load('data\\settings.xml',defaults) -dynamis_box = texts.new(' Empty', settings.tracker_box, settings) -proc_box = texts.new(' Unknown', settings.proc_box, settings) +timer = "off" +tracker = "off" +proc = "off" +trposx = 1000 +trposy = 250 +pposx = 800 +pposy = 250 + +settings = config.load() +timer = settings['timer'] +tracker = settings['tracker'] +trposx = settings['trposx'] +trposy = settings['trposy'] +proc = settings['proc'] +pposx = settings['pposx'] +pposy = settings['pposy'] for i=1, #Currency do Currency[Currency[i]] = 0 @@ -257,6 +228,7 @@ windower.register_event('load', 'login', function() if windower.ffxi.get_info().logged_in then player = windower.ffxi.get_player().name obtained = nil + initializebox() end end) @@ -279,76 +251,60 @@ windower.register_event('addon command',function (...) timer = params[2] print('Timer feature is '..timer) else print("Invalid timer option.") - end - elseif params[1]:lower() == "tracker" then - if params[2]:lower() == "on" then - tracker = "on" - initializebox() - print('Tracker enabled') - elseif params[2]:lower() == "off" then - tracker = "off" - dynamis_box:hide() - print('Tracker disabled') - elseif params[2]:lower() == "reset" then - settings = config.load(trdefaults) - dynamis_box = texts.new('Nothing to show', settings) - for i=1, #Currency do - Currency[Currency[i]] = 0 - end - obtainedf() - print('Tracker reset') - elseif params[2]:lower() == "pos" then - if params[3] then - trposx, trposy = tonumber(params[3]), tonumber(params[4]) - dynamis_box:pos(posx, posy) - else print("Invalid tracker option.") - end - end - elseif params[1]:lower() == "ll" then - if params[2]:lower() == "create" then - player = windower.ffxi.get_player()['name'] - io.open(windower.addon_path..'../../plugins/ll/dynamis-'..player..'.txt',"w"):write('if item is 1452, 1453, 1455, 1456, 1449, 1450 then lot'):close() - windower.send_command('ll profile dynamis-'..player..'.txt') - else print("Invalid light luggage option.") - end - elseif params[1]:lower() == "proc" then - if params[2]:lower() == "on" then - proc = params[2] - print('Proc feature enabled.') - elseif params[2]:lower() == "off" then - proc = params[2] - proc_box:hide() - print('Proc feature disabled.') - elseif params[2]:lower() == "pos" then - pposx, pposy = tonumber(params[3]), tonumber(params[4]) - proc_box:pos(posx, posy) - end - elseif params[1]:lower() == "debug" then - if params[2]:lower() == "on" then - debugMode = "on" - goodzone = true - proc = "on" - tracker = "on" - mob = "Test" - obtained = "1" - setproc() - initializebox() - elseif params[2]:lower() == "off" then - debugMode = "off" - goodzone = ProcZones:contains(windower.ffxi.get_info().zone) - initializeproc() - initializebox() - end - end + end + elseif params[1]:lower() == "tracker" then + if params[2]:lower() == "on" then + tracker = "on" + initializebox() + windower.text.set_visibility('dynamis_box',true) + print('Tracker enabled') + elseif params[2]:lower() == "off" then + tracker = "off" + windower.text.set_visibility('dynamis_box',false) + print('Tracker disabled') + elseif params[2]:lower() == "reset" then + for i=1, #Currency do + Currency[Currency[i]] = 0 + end + obtainedf() + initializebox() + print('Tracker reset') + elseif params[2]:lower() == "pos" then + if params[3] then + trposx, trposy = tonumber(params[3]), tonumber(params[4]) + obtainedf() + initializebox() + else print("Invalid tracker option.") + end + end + elseif params[1]:lower() == "ll" then + if params[2]:lower() == "create" then + player = windower.ffxi.get_player()['name'] + io.open(windower.addon_path..'../../plugins/ll/dynamis-'..player..'.txt',"w"):write('if item is 1452, 1453, 1455, 1456, 1449, 1450 then lot'):close() + windower.send_command('ll profile dynamis-'..player..'.txt') + else print("Invalid light luggage option.") + end + elseif params[1]:lower() == "proc" then + if params[2]:lower() == "on" then + proc = params[2] + print('Proc feature enabled.') + elseif params[2]:lower() == "off" then + proc = params[2] + windower.text.set_visibility('proc_box',false) + print('Proc feature disabled.') + elseif params[2]:lower() == "pos" then + pposx, pposy = tonumber(params[3]), tonumber(params[4]) + initializeproc() + end end + end end) windower.register_event('incoming text',function (original, new, color) -- print('event_incoming_text function') - original = original:strip_format() if timer == 'on' then - local fiend = original:match("%w+'s attack staggers the (%w+)%!") + a,b,fiend = string.find(original,"%w+'s attack staggers the (%w+)%!") if fiend == 'fiend' then StaggerCount = StaggerCount + 1 windower.send_command('timers c '..StaggerCount..' 30 down') @@ -356,19 +312,18 @@ windower.register_event('incoming text',function (original, new, color) end end if tracker == 'on' then - if debugMode == "on" then print("Starting tracker function") end - local item = original:match("%w+ obtains an? (%w+ %w+ %w+ %w+).") - if item == nil then - item = original:match("%w+ obtains an? (%w+ %w+ %w+).") - end - if item == nil then - item = original:match("%w+ obtains an? (%w+%-%w+ %w+).") - end - if item == nil then - item = original:match("%w+ obtains an? (%w+ %w+).") - end - if item then - if debugMode == "on" then print(item) end + a,b,item = string.find(original,"%w+ obtains an? ..(%w+ %w+ %w+ %w+)..\46") + if item == nil then + a,b,item = string.find(original,"%w+ obtains an? ..(%w+ %w+ %w+)..\46") + if item == nil then + a,b,item = string.find(original,"%w+ obtains an? ..(%w+%-%w+ %w+)..\46") + if item == nil then + a,b,item = string.find(original,"%w+ obtains an? ..(%w+ %w+)..\46") + end + end + end +-- a,b,item = string.find(original,"%w+ obtains an? ..(.*)..\46") + if item ~= nil then item = item:lower() for i=1, #Currency do if item == Currency[i]:lower() then @@ -396,28 +351,33 @@ end windower.register_event('zone change', function(id) goodzone = ProcZones:contains(id) - if debugMode == "on" then goodzone = true end if not goodzone then - proc_box:hide() - dynamis_box:hide() + windower.text.set_visibility('proc_box', false) end end) function initializebox() if obtained ~= nil and tracker == "on" then - dynamis_box:show() - dynamis_box:text(obtained) + windower.text.create('dynamis_box') + windower.text.set_bg_color('dynamis_box',200,30,30,30) + windower.text.set_color('dynamis_box',255,200,200,200) + windower.text.set_location('dynamis_box',trposx,trposy) + windower.text.set_visibility('dynamis_box',true) + windower.text.set_bg_visibility('dynamis_box',true) + windower.text.set_font('dynamis_box','Arial',12) + windower.text.set_text('dynamis_box',obtained); end - end windower.register_event('target change', function(targ_id) - goodzone = ProcZones:contains(windower.ffxi.get_info().zone) - if debugMode == "on" then goodzone = true end + --goodzone = ProcZones:contains(windower.ffxi.get_info().zone) if goodzone and proc == 'on' and targ_id ~= 0 then mob = windower.ffxi.get_mob_by_index(targ_id)['name'] setproc() end + + --print(ProcZones:contains(windower.ffxi.get_info().zone)) + end) function setproc() @@ -449,15 +409,23 @@ function setproc() end function initializeproc() - if goodzone == true and proc == 'on' then - proc_box:show() - proc_box:text(' Current proc for \n '..mob..'\n is '..current_proc) - else - proc_box:hide() +-- print('initializeproc function') + windower.text.create('proc_box') + windower.text.set_bg_color('proc_box',200,30,30,30) + windower.text.set_color('proc_box',255,200,200,200) + windower.text.set_location('proc_box',pposx,pposy) + if proc == 'on' then + windower.text.set_visibility('proc_box', true) + end + windower.text.set_bg_visibility('proc_box',1) + windower.text.set_font('proc_box','Arial',12) + windower.text.set_text('proc_box',' Current proc for \n '..mob..'\n is '..current_proc); + if proc == "off" then + windower.text.set_visibility('proc_box', false) end end windower.register_event('unload',function () windower.text.delete('dynamis_box') windower.text.delete('proc_box') -end) \ No newline at end of file +end) From 9e451bbd8a13dadbb7ebb6d9646a0b846a4ffd0d Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Fri, 10 Apr 2020 17:13:36 +0200 Subject: [PATCH 0387/1002] Packets: Fixed VLA field injection --- addons/libs/packets.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets.lua b/addons/libs/packets.lua index bf31403367..f39afa8285 100644 --- a/addons/libs/packets.lua +++ b/addons/libs/packets.lua @@ -100,7 +100,7 @@ size = function(fields, count) -- A single field if fields.ctype then local bits, _, type = parse_type(fields) - return bits or count * sizes[type] + return bits or type == 'char' and 8 or count and count * sizes[type] or 0 end -- A reference field From dea63f88e81f5368de0edbc44430944e4ad08f90 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Fri, 10 Apr 2020 17:15:42 +0200 Subject: [PATCH 0388/1002] Packets: Fixed bit packed string encoding --- addons/libs/packets/fields.lua | 2 +- addons/libs/strings.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 4394575f57..0bba3f5bfa 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -28,7 +28,7 @@ local ls_enc = { }), bits = 6, terminator = function(str) - return (#str % 4 == 2 and 0x60 or 0x63):char() + return (#str % 4 == 2 and 60 or 63):binary() end } local sign_enc = { diff --git a/addons/libs/strings.lua b/addons/libs/strings.lua index 835413e694..55ceb234ea 100644 --- a/addons/libs/strings.lua +++ b/addons/libs/strings.lua @@ -439,7 +439,7 @@ end string.encode = function(str, encoding) local binary = str:map(string.zfill-{encoding.bits} .. math.binary .. table.find+{encoding.charset}) if encoding.terminator then - binary = binary .. encoding.terminator(str):binary() + binary = binary .. encoding.terminator(str) end return binary:rpad('0', (#binary / 8):ceil() * 8):parse_binary() end From 618d9afe35f3998654d7a5d8ca65363405da04f9 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Fri, 10 Apr 2020 17:16:03 +0200 Subject: [PATCH 0389/1002] Packets: Fixed bit packed string decoding --- addons/libs/strings.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/strings.lua b/addons/libs/strings.lua index 55ceb234ea..cd7ac1e202 100644 --- a/addons/libs/strings.lua +++ b/addons/libs/strings.lua @@ -432,7 +432,7 @@ end -- Returns a string decoded given the appropriate encoding. string.decode = function(str, encoding) - return (str:binary():chunks(encoding.bits):map(table.get+{encoding.charset} .. tonumber-{2}):concat():gsub('%z+$', '')) + return (str:binary():chunks(encoding.bits):map(table.get+{encoding.charset} .. tonumber-{2}):concat():gsub('%z.*$', '')) end -- Returns a string encoded given the appropriate encoding. From f6f0b8c62308d774d290e417487a002f8eb9addd Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Fri, 10 Apr 2020 17:16:37 +0200 Subject: [PATCH 0390/1002] Fields/0x017: Fixed field definitions --- addons/libs/packets/fields.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 0bba3f5bfa..f4fc8eab4a 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1444,8 +1444,8 @@ fields.incoming[0x017] = L{ {ctype='unsigned char', label='Mode', fn=chat}, -- 04 {ctype='bool', label='GM'}, -- 05 {ctype='unsigned short', label='Zone', fn=zone}, -- 06 Set only for Yell - {ctype='char[16]', label='Sender Name'}, -- 08 - {ctype='char*', label='Message'}, -- 18 Max of 150 characters + {ctype='char[0x10]', label='Sender Name'}, -- 08 + {ctype='char[0xEC]', label='Message'}, -- 18 Max of 150 characters } -- Job Info From 68d0cdfd3b34a51248f5ccfae022c11744d4c596 Mon Sep 17 00:00:00 2001 From: Krizz Date: Fri, 10 Apr 2020 11:45:02 -0400 Subject: [PATCH 0391/1002] Delete settings.xml --- addons/salvage2/data/settings.xml | 50 ------------------------------- 1 file changed, 50 deletions(-) delete mode 100644 addons/salvage2/data/settings.xml diff --git a/addons/salvage2/data/settings.xml b/addons/salvage2/data/settings.xml deleted file mode 100644 index 725855ecb9..0000000000 --- a/addons/salvage2/data/settings.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - 200 - 30 - 30 - 30 - true - - - 200 - 200 - 200 - 200 - - - false - false - true - false - false - - 0 - - 1000 - 150 - - 900 - 250 - - 255 - 255 - Arial - - - - 255 - 255 - 12 - - 255 - 0 - 0 - 0 - 0 - - - - From 1810b61fc81c6484ace53729645dbeafd26d5c45 Mon Sep 17 00:00:00 2001 From: Krizz Date: Fri, 10 Apr 2020 11:45:47 -0400 Subject: [PATCH 0392/1002] Delete settings.xml --- addons/salvage2/data/settings.xml | 50 ------------------------------- 1 file changed, 50 deletions(-) delete mode 100644 addons/salvage2/data/settings.xml diff --git a/addons/salvage2/data/settings.xml b/addons/salvage2/data/settings.xml deleted file mode 100644 index 725855ecb9..0000000000 --- a/addons/salvage2/data/settings.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - 200 - 30 - 30 - 30 - true - - - 200 - 200 - 200 - 200 - - - false - false - true - false - false - - 0 - - 1000 - 150 - - 900 - 250 - - 255 - 255 - Arial - - - - 255 - 255 - 12 - - 255 - 0 - 0 - 0 - 0 - - - - From cab7299ea31b0abc4febc196bf3781d87d807faa Mon Sep 17 00:00:00 2001 From: Krizz Date: Fri, 10 Apr 2020 11:52:34 -0400 Subject: [PATCH 0393/1002] Salvage2 Tabs to Spaces As requested --- addons/salvage2/salvage2.lua | 188 +++++++++++++++++------------------ 1 file changed, 94 insertions(+), 94 deletions(-) diff --git a/addons/salvage2/salvage2.lua b/addons/salvage2/salvage2.lua index a42ed78d0e..5d525ae746 100644 --- a/addons/salvage2/salvage2.lua +++ b/addons/salvage2/salvage2.lua @@ -60,116 +60,116 @@ salvage_box2 = texts.new('No pathos', settings) windower.register_event('addon command',function (...) local params = {...}; - if #params < 1 then - return - end - if params[1] then - if params[1]:lower() == "help" then - print('Salvage2 available commands:') - print('s2 help : Shows this help message') - print('s2 pos : Positions the list') - print('s2 [hide/show] : Hides the box') - print('s2 timer [start/stop] : Starts or stops the zone timer') - print('s2 remove : Removes the pathos from the remaining list') - elseif params[1]:lower() == "pos" then - if params[3] then - local posx, posy = tonumber(params[2]), tonumber(params[3]) - windower.text.set_location('salvage_box2', posx, posy) - end - elseif params[1]:lower() == "hide" then - salvage_box2:hide() - elseif params[1]:lower() == "show" then - salvage_box2:show() - elseif params[1]:lower() == "timer" then - if params[2] == "start" then - windower.send_command('timers c Remaining 6000 up') - elseif params[2] == "stop" then - windower.send_command('timers d Remaining') - end - elseif params[1]:lower() == "debug" then - if params[2]:lower() == "start" then - windower.send_command('timers c Remaining 6000 up') - settings_create() - salvage_box2:show() - initialize() - elseif params[2]:lower() == "stop" then - windower.send_command('timers d Remaining') - salvage_box2:hide() - end - elseif params[1]:lower() == "remove" then - for i=1, #pathos_short do - if pathos_short[i]:lower() == params[2]:lower() then - pathos_ident[pathos_ident[i]] = 0 - initialize() - end - end - end - end + if #params < 1 then + return + end + if params[1] then + if params[1]:lower() == "help" then + print('Salvage2 available commands:') + print('s2 help : Shows this help message') + print('s2 pos : Positions the list') + print('s2 [hide/show] : Hides the box') + print('s2 timer [start/stop] : Starts or stops the zone timer') + print('s2 remove : Removes the pathos from the remaining list') + elseif params[1]:lower() == "pos" then + if params[3] then + local posx, posy = tonumber(params[2]), tonumber(params[3]) + windower.text.set_location('salvage_box2', posx, posy) + end + elseif params[1]:lower() == "hide" then + salvage_box2:hide() + elseif params[1]:lower() == "show" then + salvage_box2:show() + elseif params[1]:lower() == "timer" then + if params[2] == "start" then + windower.send_command('timers c Remaining 6000 up') + elseif params[2] == "stop" then + windower.send_command('timers d Remaining') + end + elseif params[1]:lower() == "debug" then + if params[2]:lower() == "start" then + windower.send_command('timers c Remaining 6000 up') + settings_create() + salvage_box2:show() + initialize() + elseif params[2]:lower() == "stop" then + windower.send_command('timers d Remaining') + salvage_box2:hide() + end + elseif params[1]:lower() == "remove" then + for i=1, #pathos_short do + if pathos_short[i]:lower() == params[2]:lower() then + pathos_ident[pathos_ident[i]] = 0 + initialize() + end + end + end + end end) windower.register_event('login', function(name) - player = name + player = name end) function settings_create() - -- get player's name - player = windower.ffxi.get_player()['name'] - -- set all pathos as needed - for i=1, #pathos_ident do - if pathos_ident[i] ~= nil then - pathos_ident[pathos_ident[i]] = 1 - end - end + -- get player's name + player = windower.ffxi.get_player()['name'] + -- set all pathos as needed + for i=1, #pathos_ident do + if pathos_ident[i] ~= nil then + pathos_ident[pathos_ident[i]] = 1 + end + end end windower.register_event('zone change', function(id) - if salvage_zones:contains(id) then - windower.send_command('timers c Remaining 6000 up') - settings_create() - initialize() - salvage_box2:show() - else - windower.send_command('timers d Remaining') - settings_create() - initialize() - salvage_box2:hide() - end + if salvage_zones:contains(id) then + windower.send_command('timers c Remaining 6000 up') + settings_create() + initialize() + salvage_box2:show() + else + windower.send_command('timers d Remaining') + settings_create() + initialize() + salvage_box2:hide() + end end) windower.register_event('incoming text',function (original, new, color) - original = original:strip_format() - local pathos, name = original:match('(.*) removed for (%w+)') - if pathos ~= nil then - --print('Pathos found '..pathos) - if name == player then - for i=1, #pathos_ident do - if pathos_ident[i]:lower() == pathos:lower() then - if pathos_ident[pathos_ident[i]] == 1 then - pathos_ident[pathos_ident[i]] = 0 - initialize() - end - end - end - end - return new, color - end + original = original:strip_format() + local pathos, name = original:match('(.*) removed for (%w+)') + if pathos ~= nil then + --print('Pathos found '..pathos) + if name == player then + for i=1, #pathos_ident do + if pathos_ident[i]:lower() == pathos:lower() then + if pathos_ident[pathos_ident[i]] == 1 then + pathos_ident[pathos_ident[i]] = 0 + initialize() + end + end + end + end + return new, color + end end) function initialize() - pathos_remain = (" Pathos Remaining: \n ") - for i=1, #pathos_ident do - if pathos_ident[pathos_ident[i]] == 1 then - item = pathos_short[i] - pathos_remain = (pathos_remain..item..' \n ') - end - end - salvage_box2:text(pathos_remain) - if pathos_remain == (" Pathos Remaining: \n ") then - salvage_box2:hide() - end + pathos_remain = (" Pathos Remaining: \n ") + for i=1, #pathos_ident do + if pathos_ident[pathos_ident[i]] == 1 then + item = pathos_short[i] + pathos_remain = (pathos_remain..item..' \n ') + end + end + salvage_box2:text(pathos_remain) + if pathos_remain == (" Pathos Remaining: \n ") then + salvage_box2:hide() + end end windower.register_event('unload',function () - windower.text.delete('salvage_box2') - windower.send_command('timers d Remaining') + windower.text.delete('salvage_box2') + windower.send_command('timers d Remaining') end ) From d8e413f460bde80143d6ced88aafd30ebc7011b8 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Fri, 10 Apr 2020 23:12:36 +0200 Subject: [PATCH 0394/1002] Fields/LS: Fixed bit packed ctype --- addons/libs/packets/fields.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index f4fc8eab4a..d3713d53da 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -3254,7 +3254,7 @@ func.incoming[0x0C9][0x01] = L{ {ctype='bit[4]', label='_junk1'}, -- 11 {ctype='unsigned char', label='Main Job', fn=job}, -- 12 {ctype='unsigned char', label='Sub Job', fn=job}, -- 13 - {ctype='char[16]', label='Linkshell', enc=ls_enc}, -- 14 6-bit packed + {ctype='data[15]', label='Linkshell', enc=ls_enc}, -- 14 6-bit packed {ctype='unsigned char', label='Main Job Level'}, -- 24 {ctype='unsigned char', label='Sub Job Level'}, -- 25 {ctype='data[42]', label='_unknown5'}, -- 26 At least the first two bytes and the last twelve bytes are junk, possibly more @@ -3275,7 +3275,7 @@ fields.incoming[0x0CC] = L{ {ctype='unsigned int', label='Timestamp', fn=time}, -- 88 {ctype='char[16]', label='Player Name'}, -- 8C {ctype='unsigned int', label='Permissions'}, -- 98 - {ctype='char[15]', label='Linkshell', enc=ls_enc}, -- 9C 6-bit packed + {ctype='data[15]', label='Linkshell', enc=ls_enc}, -- 9C 6-bit packed } -- Found Item From 0ed801b13cd1ba909d1a60b43723009307268ab1 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Fri, 10 Apr 2020 23:12:56 +0200 Subject: [PATCH 0395/1002] Packets: Fixed incorrect null terminator --- addons/libs/packets.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets.lua b/addons/libs/packets.lua index f39afa8285..4b61df1849 100644 --- a/addons/libs/packets.lua +++ b/addons/libs/packets.lua @@ -395,7 +395,7 @@ end local lookup = function(packet, field) local val = packet[field.label] - return field.enc and (val .. 0:char()):encode(field.enc) or val + return field.enc and val:encode(field.enc) or val end -- Returns binary data from a packet From e61dc31cf9b4fbecc8de46489f409b7c59b72677 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Sat, 11 Apr 2020 00:49:05 +0200 Subject: [PATCH 0396/1002] Fields/0x017: Fixed message ctype --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index d3713d53da..a02f2453fb 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1445,7 +1445,7 @@ fields.incoming[0x017] = L{ {ctype='bool', label='GM'}, -- 05 {ctype='unsigned short', label='Zone', fn=zone}, -- 06 Set only for Yell {ctype='char[0x10]', label='Sender Name'}, -- 08 - {ctype='char[0xEC]', label='Message'}, -- 18 Max of 150 characters + {ctype='char*', label='Message'}, -- 18 Max of 150 characters } -- Job Info From 72b75f614016c0d535ec22e291ea3faa5b494b20 Mon Sep 17 00:00:00 2001 From: Dean James Date: Tue, 14 Apr 2020 15:08:46 +0100 Subject: [PATCH 0397/1002] EmpyPopTracker 2.3.0 - added colorless soul NMs. --- addons/EmpyPopTracker/EmpyPopTracker.lua | 2 +- addons/EmpyPopTracker/README.md | 6 +++ addons/EmpyPopTracker/nms/brulo.lua | 50 ++++++++++++++++++++++++ addons/EmpyPopTracker/nms/index.lua | 3 ++ addons/EmpyPopTracker/nms/maere.lua | 50 ++++++++++++++++++++++++ addons/EmpyPopTracker/nms/ogopogo.lua | 50 ++++++++++++++++++++++++ 6 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 addons/EmpyPopTracker/nms/brulo.lua create mode 100644 addons/EmpyPopTracker/nms/maere.lua create mode 100644 addons/EmpyPopTracker/nms/ogopogo.lua diff --git a/addons/EmpyPopTracker/EmpyPopTracker.lua b/addons/EmpyPopTracker/EmpyPopTracker.lua index f2803e6d6b..cf178946e8 100644 --- a/addons/EmpyPopTracker/EmpyPopTracker.lua +++ b/addons/EmpyPopTracker/EmpyPopTracker.lua @@ -29,7 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'Empy Pop Tracker' _addon.author = 'Dean James (Xurion of Bismarck)' _addon.commands = { 'ept', 'empypoptracker' } -_addon.version = '2.2.2' +_addon.version = '2.3.0' config = require('config') res = require('resources') diff --git a/addons/EmpyPopTracker/README.md b/addons/EmpyPopTracker/README.md index 5ff3d1214f..24684f744b 100644 --- a/addons/EmpyPopTracker/README.md +++ b/addons/EmpyPopTracker/README.md @@ -8,10 +8,16 @@ Originally developed to track Abyssea Empyrean weapon NMs, hence the name. Key i All text colours are configurable via the auto-generated settings.xml file. +## Installation + +Empy Pop Tracker is now available via the Windower 4 addons list. + ## Load `//lua load empypoptracker` +Note: You won't have to do this if you obtained this addon via Windower. + ## Track an NM `//ept track glavoid` tracks Glavoid pop items/key items. diff --git a/addons/EmpyPopTracker/nms/brulo.lua b/addons/EmpyPopTracker/nms/brulo.lua new file mode 100644 index 0000000000..1c100b4132 --- /dev/null +++ b/addons/EmpyPopTracker/nms/brulo.lua @@ -0,0 +1,50 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = 'Brulo', + pops = { { + id = 1652, --Emerald demilune abyssite + type = 'key item', + dropped_from = { + name = 'Koios (Conflux #5)', + pops = { { + id = 1565, --Colorful demilune abyssite + type = 'key item', + dropped_from = { + name = 'Fire/Earth Elemental', + pops = { { + id = 1564, --Clear demilune abyssite + type = 'key item', + dropped_from = { name = 'Any Cruor Prospector' } + } } + } + } } + } + } } +} diff --git a/addons/EmpyPopTracker/nms/index.lua b/addons/EmpyPopTracker/nms/index.lua index 425a2b4c56..a2ab5b6049 100644 --- a/addons/EmpyPopTracker/nms/index.lua +++ b/addons/EmpyPopTracker/nms/index.lua @@ -32,6 +32,7 @@ local nms = { 'arch dynamis lord', 'azdaja', 'briareus', + 'brulo', 'bukhis', 'carabosse', 'chloris', @@ -41,6 +42,8 @@ local nms = { 'isgebind', 'itzpapalotl', 'kukulkan', + 'maere', + 'ogopogo', 'orthrus', 'sedna', 'sobek', diff --git a/addons/EmpyPopTracker/nms/maere.lua b/addons/EmpyPopTracker/nms/maere.lua new file mode 100644 index 0000000000..cfcc572147 --- /dev/null +++ b/addons/EmpyPopTracker/nms/maere.lua @@ -0,0 +1,50 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = 'Maere', + pops = { { + id = 1654, --Indigo demilune abyssite + type = 'key item', + dropped_from = { + name = 'Gamayun (Conflux #8)', + pops = { { + id = 1565, --Colorful demilune abyssite + type = 'key item', + dropped_from = { + name = 'Air/Dark Elemental', + pops = { { + id = 1564, --Clear demilune abyssite + type = 'key item', + dropped_from = { name = 'Any Cruor Prospector' } + } } + } + } } + } + } } +} diff --git a/addons/EmpyPopTracker/nms/ogopogo.lua b/addons/EmpyPopTracker/nms/ogopogo.lua new file mode 100644 index 0000000000..52a64ca259 --- /dev/null +++ b/addons/EmpyPopTracker/nms/ogopogo.lua @@ -0,0 +1,50 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = 'Ogopogo', + pops = { { + id = 1653, --Vermillion demilune abyssite + type = 'key item', + dropped_from = { + name = 'Chione (Conflux #7)', + pops = { { + id = 1565, --Colorful demilune abyssite + type = 'key item', + dropped_from = { + name = 'Ice/Water Elemental', + pops = { { + id = 1564, --Clear demilune abyssite + type = 'key item', + dropped_from = { name = 'Any Cruor Prospector' } + } } + } + } } + } + } } +} From acd8f0d1a3e599e001ebdc6e71fa5eba979cc0cc Mon Sep 17 00:00:00 2001 From: Krizz Date: Tue, 14 Apr 2020 20:13:26 -0400 Subject: [PATCH 0398/1002] Salvage2 and THTracker parenthesis and tabs Parenthesis and tabs --- addons/salvage2/salvage2.lua | 2 +- addons/thtracker/thtracker.lua | 50 +++++++++++++++++----------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/addons/salvage2/salvage2.lua b/addons/salvage2/salvage2.lua index 5d525ae746..1d9eb7cde9 100644 --- a/addons/salvage2/salvage2.lua +++ b/addons/salvage2/salvage2.lua @@ -30,7 +30,7 @@ require('tables') require('strings') require('maths') require('logger') -texts = require 'texts' +texts = require ('texts') config = require('config') ----------------------------- diff --git a/addons/thtracker/thtracker.lua b/addons/thtracker/thtracker.lua index 1a045ccd1a..e3be843640 100644 --- a/addons/thtracker/thtracker.lua +++ b/addons/thtracker/thtracker.lua @@ -30,8 +30,8 @@ _addon.author = 'Krizz' _addon.version = 1.1 _addon.commands = {'thtracker', 'th'} -config = require 'config' -texts = require 'texts' +config = require ('config') +texts = require ('texts') require('logger') defaults = {} @@ -75,32 +75,32 @@ windower.register_event('addon command', function(command, ...) end) windower.register_event('incoming text', function(original, new, color) - original = original:strip_format() - local name, count = original:match('Additional effect: Treasure Hunter effectiveness against[%s%a%a%a]- (.*) increases to (%d+).') - - if name and count then - name = name.gsub(name, "the ", "") - mob = name - th:text(' '..name..'\n TH: '..count); - th:show() - end + original = original:strip_format() + local name, count = original:match('Additional effect: Treasure Hunter effectiveness against[%s%a%a%a]- (.*) increases to (%d+).') + + if name and count then + name = name.gsub(name, "the ", "") + mob = name + th:text(' '..name..'\n TH: '..count); + th:show() + end - local deadmob = original:match('%w+ defeats[%s%a%a%a]- (.*).') - - if deadmob then - deadmob = deadmob.gsub(deadmob, "the ", "") - end - - if deadmob == mob then - - th:text('No current mob') - th:hide() - mob = nil - end + local deadmob = original:match('%w+ defeats[%s%a%a%a]- (.*).') + + if deadmob then + deadmob = deadmob.gsub(deadmob, "the ", "") + end + + if deadmob == mob then + + th:text('No current mob') + th:hide() + mob = nil + end end) windower.register_event('zone change', function() - th:text('No current mob') - th:hide() + th:text('No current mob') + th:hide() end) \ No newline at end of file From c17a66154a1a7816a4fe9f9aff5f91880f4d3185 Mon Sep 17 00:00:00 2001 From: Dean James Date: Sat, 18 Apr 2020 01:03:00 +0100 Subject: [PATCH 0399/1002] Added NoCampaignMusic addon. --- addons/NoCampaignMusic/NoCampaignMusic.lua | 162 +++++++++++++++++++++ addons/NoCampaignMusic/README.md | 30 ++++ addons/addons.xml | 9 +- 3 files changed, 200 insertions(+), 1 deletion(-) create mode 100644 addons/NoCampaignMusic/NoCampaignMusic.lua create mode 100644 addons/NoCampaignMusic/README.md diff --git a/addons/NoCampaignMusic/NoCampaignMusic.lua b/addons/NoCampaignMusic/NoCampaignMusic.lua new file mode 100644 index 0000000000..b22b2d6397 --- /dev/null +++ b/addons/NoCampaignMusic/NoCampaignMusic.lua @@ -0,0 +1,162 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 No Campaign Music 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 Dean James (Xurion of Bismarck) 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.name = 'No Campaign Music' +_addon.author = 'Dean James (Xurion of Bismarck)' +_addon.version = '2.0.0' +_addon.commands = {'nocampaignmusic', 'ncm'} + +packets = require('packets') +config = require('config') + +defaults = { + active = true +} + +settings = config.load(defaults) + +campaign_id = 247 +solo_id = 101 +party_id = 215 +solo_dungeon_id = 115 +party_dungeon_id = 216 + +campaign_active = false + +zone_music_map = {} +zone_music_map[80] = { 254, 254, solo_id, party_id } --Southern San d'Oria [S] +zone_music_map[81] = { 251, 251, solo_id, party_id } --East Ronfaure [S] +zone_music_map[82] = { 0, 0, solo_id, party_id } --Jugner Forest [S] +zone_music_map[83] = { 0, 0, solo_id, party_id } --Vunkerl Inlet [S] +zone_music_map[84] = { 252, 252, solo_id, party_id } --Batallia Downs [S] +zone_music_map[85] = { 44, 44, solo_dungeon_id, party_dungeon_id } --La Vaule [S] +zone_music_map[87] = { 180, 180, solo_id, party_id } --Bastok Markets [S] +zone_music_map[88] = { 253, 253, solo_id, party_id } --North Gustaberg [S] +zone_music_map[89] = { 0, 0, solo_id, party_id } --Grauberg [S] +zone_music_map[90] = { 0, 0, solo_id, party_id } --Pashhow Marshlands [S] +zone_music_map[91] = { 252, 252, solo_id, party_id } --Rolanberry Fields [S] +zone_music_map[92] = { 44, 44, solo_dungeon_id, party_dungeon_id } --Beadeaux [S] +zone_music_map[94] = { 182, 182, solo_id, party_id } --Windurst Waters [S] +zone_music_map[95] = { 141, 141, solo_id, party_id } --West Sarutabaruta [S] +zone_music_map[96] = { 0, 0, solo_id, party_id } --Fort Karugo-Narugo [S] +zone_music_map[97] = { 0, 0, solo_id, party_id } --Meriphataud Mountains [S] +zone_music_map[98] = { 252, 252, solo_id, party_id } --Sauromugue Champaign [S] +zone_music_map[99] = { 44, 44, solo_dungeon_id, party_dungeon_id } --Castle Oztroja [S] +zone_music_map[136] = { 0, 0, solo_id, party_id } --Beaucedine Glacier [S] +zone_music_map[137] = { 42, 42, solo_id, party_id } --Xarcabard [S] +zone_music_map[138] = { 43, 43, solo_dungeon_id, party_dungeon_id } --Castle Zvahl Baileys [S] +zone_music_map[155] = { 43, 43, solo_dungeon_id, party_dungeon_id } --Castle Zvahl Keep [S] +zone_music_map[164] = { 0, 0, solo_dungeon_id, party_dungeon_id } --Garlaige Citadel [S] +zone_music_map[171] = { 0, 0, solo_dungeon_id, party_dungeon_id } --Crawlers' Nest [S] +zone_music_map[175] = { 0, 0, solo_dungeon_id, party_dungeon_id } --The Eldieme Necropolis [S] + +windower.register_event('incoming chunk', function(id, data) + if id == 0x00A then --Zone update (zoned in) + local parsed = packets.parse('incoming', data) + if parsed['Day Music'] == campaign_id and zone_music_map[parsed.Zone] then + campaign_active = true + if not settings.active then return end + + parsed['Day Music'] = zone_music_map[parsed.Zone][1] + parsed['Night Music'] = zone_music_map[parsed.Zone][1] + parsed['Solo Combat Music'] = zone_music_map[parsed.Zone][2] + parsed['Party Combat Music'] = zone_music_map[parsed.Zone][3] + + windower.add_to_chat(8, 'Prevented campaign music.') + return packets.build(parsed) + end + elseif id == 0x05F then --Music update (campaign possibly started) + local parsed = packets.parse('incoming', data) + if parsed['Song ID'] == campaign_id then + campaign_active = true + if not settings.active then return end + + local info = windower.ffxi.get_info() + if not zone_music_map[info.zone] then return end + + if parsed['BGM Type'] == 0 then --only log to the chat once + windower.add_to_chat(8, 'Prevented campaign music.') + end + + parsed['Song ID'] = zone_music_map[info.zone][parsed['BGM Type'] + 1] + return packets.build(parsed) + end + end +end) + +commands = {} + +commands.on = function() + settings.active = true + settings:save() + windower.add_to_chat(8, 'Campaign music will now be blocked.') + local info = windower.ffxi.get_info() + + if campaign_active and zone_music_map[info.zone] then + for i = 0, 3 do + packets.inject(packets.new('incoming', 0x05F, { + ['BGM Type'] = i, + ['Song ID'] = zone_music_map[info.zone][i + 1], + })) + end + end +end + +commands.off = function() + settings.active = false + settings:save() + windower.add_to_chat(8, 'Campaign music will no longer be blocked.') + local info = windower.ffxi.get_info() + + if campaign_active and zone_music_map[info.zone] then + --Set all music to be campaign + for i = 0, 3 do + packets.inject(packets.new('incoming', 0x05F, { + ['BGM Type'] = i, + ['Song ID'] = campaign_id, + })) + end + end +end + +commands.help = function() + windower.add_to_chat(8, 'No Campaign Music:') + windower.add_to_chat(8, ' //ncm on - starts blocking campaign music (on by default)') + windower.add_to_chat(8, ' //ncm off - stops blocking campaign music') + windower.add_to_chat(8, ' //ncm help - shows this help') +end + +windower.register_event('addon command', function(command) + command = command and command:lower() or 'help' + + if commands[command] then + commands[command]() + else + commands.help() + end +end) diff --git a/addons/NoCampaignMusic/README.md b/addons/NoCampaignMusic/README.md new file mode 100644 index 0000000000..e276304297 --- /dev/null +++ b/addons/NoCampaignMusic/README.md @@ -0,0 +1,30 @@ + +# FFXI - No Campaign Music + +Prevents all campaign battle music from playing in Final Fantasy XI, so you can listen to that sweet music that is normally obnoxiously interrupted. + +## Load + +``` +//lua load ncm +``` + +## Activate/deactivate + +``` +//ncm on +``` + +``` +//ncm off +``` + +## Note + +When campaign music is prevented from playing (whether it's as you zone in, or campaign starts in the zone) a message will log to the chatlog stating "Prevented campaign music." This not only confirms the addon is working, but shows you there's a campaign active should you want to take part. + +## Contributing + +If you notice something not quite right, please [raise an issue](https://github.com/xurion/ffxi-no-campaign-music/issues). + +Or better yet, [pull requests](https://github.com/xurion/ffxi-no-campaign-music/pulls) are welcome! diff --git a/addons/addons.xml b/addons/addons.xml index ed64f3a4f9..6286a66f41 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -370,6 +370,13 @@ https://github.com/Windower/Lua/issues https://discord.gg/b275nMv + + NoCampaignMusic + Prevents campaign battle music from playing in Shadowreign areas. + Dean James (Xurion of Bismarck) + https://github.com/xurion/ffxi-no-campaign-music/issues + https://www.ffxiah.com/forum/topic/52507/sick-of-campaign-music-prevent-it-with-this-addon/ + Nostrum Creates a click-able on-screen macro to help avoid targeting problems while curing. @@ -815,5 +822,5 @@ Block graphical effects from Geomancer's Indi- spells. https://github.com/Windower/Lua/issues https://github.com/lili-ffxi - + From b6ede104421c9669d45f46671e9a3cad865b0ff3 Mon Sep 17 00:00:00 2001 From: Dean James Date: Sat, 18 Apr 2020 16:45:54 +0100 Subject: [PATCH 0400/1002] NCM: Added toggle for notifications. Fixed issue where addon would perma think campaign was active. PR comments. --- addons/NoCampaignMusic/NoCampaignMusic.lua | 20 +++++++++++++------- addons/NoCampaignMusic/README.md | 9 ++++++++- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/addons/NoCampaignMusic/NoCampaignMusic.lua b/addons/NoCampaignMusic/NoCampaignMusic.lua index b22b2d6397..63f5217e25 100644 --- a/addons/NoCampaignMusic/NoCampaignMusic.lua +++ b/addons/NoCampaignMusic/NoCampaignMusic.lua @@ -35,7 +35,8 @@ packets = require('packets') config = require('config') defaults = { - active = true + active = true, + notifications = false, } settings = config.load(defaults) @@ -87,24 +88,23 @@ windower.register_event('incoming chunk', function(id, data) parsed['Solo Combat Music'] = zone_music_map[parsed.Zone][2] parsed['Party Combat Music'] = zone_music_map[parsed.Zone][3] - windower.add_to_chat(8, 'Prevented campaign music.') return packets.build(parsed) end elseif id == 0x05F then --Music update (campaign possibly started) local parsed = packets.parse('incoming', data) + local info = windower.ffxi.get_info() if parsed['Song ID'] == campaign_id then campaign_active = true - if not settings.active then return end - - local info = windower.ffxi.get_info() - if not zone_music_map[info.zone] then return end + if not settings.active or not zone_music_map[info.zone] then return end - if parsed['BGM Type'] == 0 then --only log to the chat once + if settings.notifications and parsed['BGM Type'] == 0 then --only log to the chat once windower.add_to_chat(8, 'Prevented campaign music.') end parsed['Song ID'] = zone_music_map[info.zone][parsed['BGM Type'] + 1] return packets.build(parsed) + elseif parsed['Song ID'] == zone_music_map[info.zone][parsed['BGM Type'] + 1] then + campaign_active = false end end end) @@ -144,6 +144,12 @@ commands.off = function() end end +commands.notify = function() + settings.notifications = not settings.notifications + settings:save() + windower.add_to_chat(8, 'Campaign notifications: ' .. tostring(settings.notifications)) +end + commands.help = function() windower.add_to_chat(8, 'No Campaign Music:') windower.add_to_chat(8, ' //ncm on - starts blocking campaign music (on by default)') diff --git a/addons/NoCampaignMusic/README.md b/addons/NoCampaignMusic/README.md index e276304297..ff60c9b850 100644 --- a/addons/NoCampaignMusic/README.md +++ b/addons/NoCampaignMusic/README.md @@ -1,4 +1,3 @@ - # FFXI - No Campaign Music Prevents all campaign battle music from playing in Final Fantasy XI, so you can listen to that sweet music that is normally obnoxiously interrupted. @@ -19,6 +18,14 @@ Prevents all campaign battle music from playing in Final Fantasy XI, so you can //ncm off ``` +## Campaign notifications + +If you want to know when campaign is happening, you can toggle notifications: + +``` +//ncm notify +``` + ## Note When campaign music is prevented from playing (whether it's as you zone in, or campaign starts in the zone) a message will log to the chatlog stating "Prevented campaign music." This not only confirms the addon is working, but shows you there's a campaign active should you want to take part. From af2a94b052c92254e137bf5e512d36113feee368 Mon Sep 17 00:00:00 2001 From: Dean James Date: Sat, 18 Apr 2020 18:47:51 +0100 Subject: [PATCH 0401/1002] NCM: Optimised incoming chunk logic. Removed on/off commands. Converted settings to CamelCase. Fixed incorrect asignment of music for solo/party battle on zone update. PR comments. --- addons/NoCampaignMusic/NoCampaignMusic.lua | 73 ++++++---------------- 1 file changed, 20 insertions(+), 53 deletions(-) diff --git a/addons/NoCampaignMusic/NoCampaignMusic.lua b/addons/NoCampaignMusic/NoCampaignMusic.lua index 63f5217e25..73706ceb1a 100644 --- a/addons/NoCampaignMusic/NoCampaignMusic.lua +++ b/addons/NoCampaignMusic/NoCampaignMusic.lua @@ -35,8 +35,7 @@ packets = require('packets') config = require('config') defaults = { - active = true, - notifications = false, + Notifications = false, } settings = config.load(defaults) @@ -77,33 +76,35 @@ zone_music_map[171] = { 0, 0, solo_dungeon_id, party_dungeon_id } --Crawlers' Ne zone_music_map[175] = { 0, 0, solo_dungeon_id, party_dungeon_id } --The Eldieme Necropolis [S] windower.register_event('incoming chunk', function(id, data) - if id == 0x00A then --Zone update (zoned in) - local parsed = packets.parse('incoming', data) - if parsed['Day Music'] == campaign_id and zone_music_map[parsed.Zone] then + if id ~= 0x00A and id ~= 0x05F then return end + + local parsed = packets.parse('incoming', data) + local zone_music = zone_music_map[parsed['Zone'] or windower.ffxi.get_info().zone] + + if id == 0x00A then --Zone update (zoned in) + if parsed['Day Music'] == campaign_id and zone_music then campaign_active = true - if not settings.active then return end - parsed['Day Music'] = zone_music_map[parsed.Zone][1] - parsed['Night Music'] = zone_music_map[parsed.Zone][1] - parsed['Solo Combat Music'] = zone_music_map[parsed.Zone][2] - parsed['Party Combat Music'] = zone_music_map[parsed.Zone][3] + parsed['Day Music'] = zone_music[1] + parsed['Night Music'] = zone_music[2] + parsed['Solo Combat Music'] = zone_music[3] + parsed['Party Combat Music'] = zone_music[4] return packets.build(parsed) end - elseif id == 0x05F then --Music update (campaign possibly started) - local parsed = packets.parse('incoming', data) + else --Music update (campaign possibly started/finished) local info = windower.ffxi.get_info() if parsed['Song ID'] == campaign_id then campaign_active = true - if not settings.active or not zone_music_map[info.zone] then return end + if not zone_music then return end - if settings.notifications and parsed['BGM Type'] == 0 then --only log to the chat once + if settings.Notifications and parsed['BGM Type'] == 0 then --only log to the chat once windower.add_to_chat(8, 'Prevented campaign music.') end - parsed['Song ID'] = zone_music_map[info.zone][parsed['BGM Type'] + 1] + parsed['Song ID'] = zone_music[parsed['BGM Type'] + 1] return packets.build(parsed) - elseif parsed['Song ID'] == zone_music_map[info.zone][parsed['BGM Type'] + 1] then + elseif parsed['Song ID'] == zone_music[parsed['BGM Type'] + 1] then campaign_active = false end end @@ -111,49 +112,15 @@ end) commands = {} -commands.on = function() - settings.active = true - settings:save() - windower.add_to_chat(8, 'Campaign music will now be blocked.') - local info = windower.ffxi.get_info() - - if campaign_active and zone_music_map[info.zone] then - for i = 0, 3 do - packets.inject(packets.new('incoming', 0x05F, { - ['BGM Type'] = i, - ['Song ID'] = zone_music_map[info.zone][i + 1], - })) - end - end -end - -commands.off = function() - settings.active = false - settings:save() - windower.add_to_chat(8, 'Campaign music will no longer be blocked.') - local info = windower.ffxi.get_info() - - if campaign_active and zone_music_map[info.zone] then - --Set all music to be campaign - for i = 0, 3 do - packets.inject(packets.new('incoming', 0x05F, { - ['BGM Type'] = i, - ['Song ID'] = campaign_id, - })) - end - end -end - commands.notify = function() - settings.notifications = not settings.notifications + settings.Notifications = not settings.Notifications settings:save() - windower.add_to_chat(8, 'Campaign notifications: ' .. tostring(settings.notifications)) + windower.add_to_chat(8, 'Campaign notifications: ' .. tostring(settings.Notifications)) end commands.help = function() windower.add_to_chat(8, 'No Campaign Music:') - windower.add_to_chat(8, ' //ncm on - starts blocking campaign music (on by default)') - windower.add_to_chat(8, ' //ncm off - stops blocking campaign music') + windower.add_to_chat(8, ' //ncm notify - toggles campaign notifications (default false)') windower.add_to_chat(8, ' //ncm help - shows this help') end From b8f21d37622254a1b4b45289bace4801da2b8e9e Mon Sep 17 00:00:00 2001 From: Unknown Date: Sat, 18 Apr 2020 18:01:06 -0500 Subject: [PATCH 0402/1002] Added buy status packet type for incoming AH confirmation packet. --- addons/libs/packets/fields.lua | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index a02f2453fb..8ca0306b05 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2377,6 +2377,7 @@ enums['ah itype'] = { [0x0A] = 'Open menu confirmation', [0x0B] = 'Sell item confirmation', [0x0D] = 'Sales item status', + [0x0E] = 'Purchase item result', } func.incoming[0x04C] = {} @@ -2425,6 +2426,11 @@ enums['sale stat'] = { [0x0B] = 'Not sold', [0x10] = 'Checking', } +enums['buy stat'] = { + [0x01] = 'Success', + [0x02] = 'Placing', + [0xC5] = 'Failed', +} -- 0x0A, 0x0B and 0x0D could probably be combined, the fields seem the same. -- However, they're populated a bit differently. Both 0x0B and 0x0D are sent twice @@ -2486,6 +2492,25 @@ func.incoming[0x04C][0x0D] = L{ {ctype='unsigned int', label='Timestamp', fn=utime}, -- 38 } +func.incoming[0x04C][0x0E] = L{ + {ctype='unsigned char', label='_unknown1'}, -- 05 + {ctype='unsigned char', label='Buy Status', fn=e+{'buy stat'}}, -- 06 + {ctype='unsigned char', label='_unknown2'}, -- 07 + {ctype='unsigned int', label='Price', fn=gil}, -- 08 + {ctype='unsigned short', label='Item ID', fn=item}, -- 0C + {ctype='unsigned short', label='_unknown3'}, -- 0E + {ctype='unsigned short', label='Count'}, -- 10 + {ctype='unsigned int', label='_unknown4'}, -- 12 + {ctype='unsigned short', label='_unknown5'}, -- 16 + {ctype='char[16]', label='Name'}, -- 18 Character name (pending buy only) + {ctype='unsigned short', label='Pending Item ID', fn=item}, -- 28 Only filled out during pending packets + {ctype='unsigned short', label='Pending Count'}, -- 2A Only filled out during pending packets + {ctype='unsigned int', label='Pending Price', fn=gil}, -- 2C Only filled out during pending packets + {ctype='unsigned int', label='_unknown6'}, -- 30 + {ctype='unsigned int', label='_unknown7'}, -- 34 + {ctype='unsigned int', label='Timestamp', fn=utime}, -- 38 Only filled out during pending packets +} + func.incoming[0x04C][0x10] = L{ {ctype='unsigned char', label='_unknown1', const=0x00}, -- 05 {ctype='unsigned char', label='Success', fn=bool}, -- 06 From 3542597b90b987ab7527e0c306d62e65b8c278bf Mon Sep 17 00:00:00 2001 From: Ivaar <7287342+Ivaar@users.noreply.github.com> Date: Sun, 19 Apr 2020 11:05:38 -0700 Subject: [PATCH 0403/1002] Porter: Add new find command and resources lib --- addons/porter/README.md | 9 ++++- addons/porter/porter.lua | 79 +++++++++++++--------------------------- 2 files changed, 34 insertions(+), 54 deletions(-) diff --git a/addons/porter/README.md b/addons/porter/README.md index 4cab50a622..4efb5ce2ae 100644 --- a/addons/porter/README.md +++ b/addons/porter/README.md @@ -14,10 +14,17 @@ porter [ []] [owned] * **_slip_:** the number of the slip you want to show. * **_page_:** the page of the slip you want to show. * **owned:** shows only the items you own. - +``` +porter find +``` +Shows storable items found in all inventory bags. ---- ##changelog## +### v1.20200419 +* **add**: New command, porter find. +* **change**: Adjusted resource handling. + ### v1.20130529 * **fix**: Fixed parameters validation. * **change**: Aligned to Windower's addon development guidelines. diff --git a/addons/porter/porter.lua b/addons/porter/porter.lua index 8481599a98..b10c2eae39 100644 --- a/addons/porter/porter.lua +++ b/addons/porter/porter.lua @@ -32,63 +32,15 @@ require 'chat' require 'logger' require 'sets' require 'strings' - +res = require 'resources' slips = require 'slips' - -_addon.name = 'porter' -_addon.version = '1.20130529' +_addon.name = 'porter' +_addon.version = '1.20200419' _addon.command = 'porter' _addon.author = 'Zohno' -item_names = T{} -resources = { - ['armor'] = '../../plugins/resources/items_armor.xml', - ['weapons'] = '../../plugins/resources/items_weapons.xml', - ['general'] = '../../plugins/resources/items_general.xml' -} - -function load_resources() - local slips_items_ids = T() - for _, slip in pairs(slips.items) do - slips_items_ids:extend(slip) - end - - slips_items_ids = S(slips_items_ids) - - for kind, resource_path in pairs(resources) do - resource = io.open(windower.addon_path..resource_path, 'r') - - if resource ~= nil then - while true do - local line = resource:read() - - if line == nil then - break - end - - local id, name = line:match('id="(%d+)".+>([^<]+)<') - - if id ~= nil then - id = tonumber(id, 10) - - if slips_items_ids:contains(id) then - item_names[id] = name:lower() - end - end - end - else - error(kind..' resource file not found') - end - - resource:close() - end -end - function show_slip(slip_number, slip_page, owned_only) - if item_names:length() == 0 then - load_resources() - end owned_only = owned_only or false @@ -137,7 +89,7 @@ function show_slip(slip_number, slip_page, owned_only) windower.add_to_chat( 55, ('slip '..printable_slip_number..'/page '..tostring(slip_page and slip_page or math.ceil(item_position / 16)):lpad('0', 2)..':'):color(259)..' '.. - item_names[item_id]:color(is_contained and 258 or 261) + res.items[item_id].name:color(is_contained and 258 or 261) ) end end @@ -145,6 +97,24 @@ function show_slip(slip_number, slip_page, owned_only) end end +function show_bags() + + local n = 0 + + for _, bag in ipairs(slips.default_storages) do + for _, item in ipairs(windower.ffxi.get_items(bag)) do + local slip_id = slips.get_slip_id_by_item_id(item.id) + + if slip_id then + n = n + 1 + windower.add_to_chat(207, 'slip %02d: %s %s':format(slips.get_slip_number_by_id(slip_id), bag, res.items[item.id].name:color(258))) + end + end + end + + windower.add_to_chat(207, 'Found %s storable items in all bags':format(n)) +end + windower.register_event('addon command',function (slip_number, slip_page, owned_only) if tonumber(slip_number) == nil then slip_page = nil @@ -152,6 +122,9 @@ windower.register_event('addon command',function (slip_number, slip_page, owned_ if slip_number == 'owned' then slip_number = nil owned_only = true + elseif slip_number == 'find' then + show_bags() + return elseif slip_number ~= nil then error('That\'s not a valid slip number, kupo!') @@ -181,4 +154,4 @@ windower.register_event('addon command',function (slip_number, slip_page, owned_ end show_slip(slip_number, slip_page, owned_only) -end) \ No newline at end of file +end) From aeda8254b6d0672284a9154cd24373d3615122f2 Mon Sep 17 00:00:00 2001 From: Dean James Date: Mon, 20 Apr 2020 15:19:52 +0100 Subject: [PATCH 0404/1002] NCM: Fix error on mount in non-campign areas. Updated stale readme. --- addons/NoCampaignMusic/NoCampaignMusic.lua | 12 +++--------- addons/NoCampaignMusic/README.md | 10 ---------- 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/addons/NoCampaignMusic/NoCampaignMusic.lua b/addons/NoCampaignMusic/NoCampaignMusic.lua index 73706ceb1a..a45e9ff281 100644 --- a/addons/NoCampaignMusic/NoCampaignMusic.lua +++ b/addons/NoCampaignMusic/NoCampaignMusic.lua @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'No Campaign Music' _addon.author = 'Dean James (Xurion of Bismarck)' -_addon.version = '2.0.0' +_addon.version = '2.0.1' _addon.commands = {'nocampaignmusic', 'ncm'} packets = require('packets') @@ -46,8 +46,6 @@ party_id = 215 solo_dungeon_id = 115 party_dungeon_id = 216 -campaign_active = false - zone_music_map = {} zone_music_map[80] = { 254, 254, solo_id, party_id } --Southern San d'Oria [S] zone_music_map[81] = { 251, 251, solo_id, party_id } --East Ronfaure [S] @@ -81,10 +79,10 @@ windower.register_event('incoming chunk', function(id, data) local parsed = packets.parse('incoming', data) local zone_music = zone_music_map[parsed['Zone'] or windower.ffxi.get_info().zone] + if not zone_music then return end + if id == 0x00A then --Zone update (zoned in) if parsed['Day Music'] == campaign_id and zone_music then - campaign_active = true - parsed['Day Music'] = zone_music[1] parsed['Night Music'] = zone_music[2] parsed['Solo Combat Music'] = zone_music[3] @@ -95,8 +93,6 @@ windower.register_event('incoming chunk', function(id, data) else --Music update (campaign possibly started/finished) local info = windower.ffxi.get_info() if parsed['Song ID'] == campaign_id then - campaign_active = true - if not zone_music then return end if settings.Notifications and parsed['BGM Type'] == 0 then --only log to the chat once windower.add_to_chat(8, 'Prevented campaign music.') @@ -104,8 +100,6 @@ windower.register_event('incoming chunk', function(id, data) parsed['Song ID'] = zone_music[parsed['BGM Type'] + 1] return packets.build(parsed) - elseif parsed['Song ID'] == zone_music[parsed['BGM Type'] + 1] then - campaign_active = false end end end) diff --git a/addons/NoCampaignMusic/README.md b/addons/NoCampaignMusic/README.md index ff60c9b850..63ec719c04 100644 --- a/addons/NoCampaignMusic/README.md +++ b/addons/NoCampaignMusic/README.md @@ -8,16 +8,6 @@ Prevents all campaign battle music from playing in Final Fantasy XI, so you can //lua load ncm ``` -## Activate/deactivate - -``` -//ncm on -``` - -``` -//ncm off -``` - ## Campaign notifications If you want to know when campaign is happening, you can toggle notifications: From 6652a86818a8eca6f777c203963e9badae965f90 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Thu, 23 Apr 2020 01:05:33 +0100 Subject: [PATCH 0405/1002] Update AutoRA.lua bug fixed: capitalization on a variable --- addons/AutoRA/AutoRA.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/AutoRA/AutoRA.lua b/addons/AutoRA/AutoRA.lua index 22d8d03d9f..49dd1bb19e 100644 --- a/addons/AutoRA/AutoRA.lua +++ b/addons/AutoRA/AutoRA.lua @@ -37,7 +37,7 @@ end local haltontp = function() settings.HaltOnTp = not settings.HaltOnTp - if settings.HaltonTp then + if settings.HaltOnTp then windower.add_to_chat(17, 'AutoRA will halt upon reaching 1000 TP') else windower.add_to_chat(17, 'AutoRA will no longer halt upon reaching 1000 TP') From ffa5a6aa478f12924b6aa2895c922d40d1ae2751 Mon Sep 17 00:00:00 2001 From: Ivaar <7287342+Ivaar@users.noreply.github.com> Date: Fri, 24 Apr 2020 09:01:06 -0700 Subject: [PATCH 0406/1002] fields: tractor enums and 0x0F9 field update --- addons/libs/packets/fields.lua | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 8ca0306b05..ced035ab2b 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -359,6 +359,7 @@ enums['action'] = { [0x0F] = 'Switch target', [0x10] = 'Ranged attack', [0x12] = 'Dismount Chocobo', + [0x13] = 'Tractor Dialogue' [0x14] = 'Zoning/Appear', -- I think, the resource for this is ambiguous. [0x19] = 'Monsterskill', [0x1A] = 'Mount', @@ -3462,12 +3463,17 @@ fields.incoming[0x0F6] = L{ {ctype='unsigned int', label='Type', fn=e+{'ws mark'}}, -- 04 } +enums['reraise'] = { + [0x01] = 'Raise dialogue', + [0x02] = 'Tractor dialogue', +} + -- Reraise Activation fields.incoming[0x0F9] = L{ {ctype='unsigned int', label='ID', fn=id}, -- 04 {ctype='unsigned short', label='Index', fn=index}, -- 08 - {ctype='unsigned char', label='_unknown1'}, -- 0A - {ctype='unsigned char', label='_unknown2'}, -- 0B + {ctype='unsigned char', label='Category', fn=e+{'reraise'}}, -- 0A + {ctype='unsigned char', label='_unknown1'}, -- 0B } -- Furniture Interaction From 61788a80766b19690ee6fcb6ed81d75738270e9a Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sat, 25 Apr 2020 13:11:44 +0100 Subject: [PATCH 0407/1002] Update fields.lua missing comma --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index ced035ab2b..4149475199 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -359,7 +359,7 @@ enums['action'] = { [0x0F] = 'Switch target', [0x10] = 'Ranged attack', [0x12] = 'Dismount Chocobo', - [0x13] = 'Tractor Dialogue' + [0x13] = 'Tractor Dialogue', [0x14] = 'Zoning/Appear', -- I think, the resource for this is ambiguous. [0x19] = 'Monsterskill', [0x1A] = 'Mount', From cd778206c5cf8cd4be4cb1f27fcd9b17b8cbb2a4 Mon Sep 17 00:00:00 2001 From: Unknown Date: Wed, 29 Apr 2020 22:36:27 -0500 Subject: [PATCH 0408/1002] Added command to change both jobs at once and prefer dw subjobs on reset --- addons/JobChange/README.md | 5 +- addons/JobChange/jobchange.lua | 214 +++++++++++++++++++++------------ 2 files changed, 141 insertions(+), 78 deletions(-) diff --git a/addons/JobChange/README.md b/addons/JobChange/README.md index cbb0ec450b..369c22a70e 100644 --- a/addons/JobChange/README.md +++ b/addons/JobChange/README.md @@ -3,8 +3,9 @@ Job Change AddOn. Allows command line job change as long as you're within 6 yalms of a Job Change NPC. Usage: -* //jc main job -* //jc sub job +* //jc main job - change just main job +* //jc sub job - change just sub job +* //jc main/sub - change both jobs at the same time. * //jc reset (Resets JA's by changing your sub job off and back) diff --git a/addons/JobChange/jobchange.lua b/addons/JobChange/jobchange.lua index 461328815f..7b8d41930e 100644 --- a/addons/JobChange/jobchange.lua +++ b/addons/JobChange/jobchange.lua @@ -27,92 +27,48 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] _addon.name = 'Job Change' -_addon.author = 'Sammeh' -_addon.version = '1.0.3' +_addon.author = 'Sammeh; Akaden' +_addon.version = '1.0.4' _addon.command = 'jc' -- 1.0.1 first release -- 1.0.2 added 'reset' command to simply reset to existing job. Changes sub job to a random starting job and back. -- 1.0.3 Code clean-up +-- 1.0.4 Added /jc main/sub command and organized solve for fewest changes. require('tables') packets = require('packets') res = require ('resources') -function jobchange(job,main_sub) - windower.add_to_chat(4,"JobChange: Changing "..main_sub.." job to:"..res.jobs[job].ens) - if job and main_sub then - local packet = packets.new('outgoing', 0x100, { - [main_sub:sub(1,1):upper()..main_sub:sub(2)..' Job'] = job, - }) - packets.inject(packet) - coroutine.sleep(0.5) - end +local temp_jobs = T { 'NIN', 'DNC', 'WAR', 'MNK', 'WHM', 'BLM', 'RDM', 'THF' } +local mog_zones = S { 'Selbina', 'Mhaura', 'Tavnazian Safehold', 'Nashmau', 'Rabao', 'Kazham', 'Norg'} +local moogles = S { 'Moogle', 'Nomad Moogle', 'Green Thumb Moogle' } + +local log = function(msg) + windower.add_to_chat(4,'JobChange: '..msg) end -windower.register_event('addon command', function(command, ...) - local self = windower.ffxi.get_player() - local args = L{...} - local job = '' - if args[1] then - job = args[1]:lower() - end - local main_sub = '' - if command:lower() == 'main' then - main_sub = 'main' - elseif command:lower() == 'sub' then - main_sub = 'sub' - elseif command:lower() == 'reset' then - windower.add_to_chat(4,"JobChange: Resetting Job") - main_sub = 'sub' - job = windower.ffxi.get_player().sub_job:lower() - else - windower.add_to_chat(4,"JobChange Syntax: //jc main|sub JOB -- Chnages main or sub to target JOB") - windower.add_to_chat(4,"JobChange Syntax: //jc reset -- Resets Current Job") - return - end - local conflict = find_conflict(job,self) - local jobid = find_job(job,self) - if jobid then - local npc = find_job_change_npc() - if npc then - if not conflict then - jobchange(jobid,main_sub) - else - local temp_job = find_temp_job(self) - windower.add_to_chat(4,"JobChange: Conflict with "..conflict) - if main_sub == conflict then - jobchange(temp_job,main_sub) - jobchange(jobid,main_sub) - else - jobchange(temp_job,conflict) - jobchange(jobid,main_sub) - end - end - else - windower.add_to_chat(4,"JobChange: Not close enough to a Moogle!") - end - else - windower.add_to_chat(4,"JobChange: Could not change "..command.." to "..job:upper().." ---Mistype|NotUnlocked") - end - -end) +local jobchange = function(job, main) + local packet = packets.new('outgoing', 0x100, { + [(main and 'Main' or 'Sub')..' Job'] = job, + }) + packets.inject(packet) +end -function find_conflict(job,self) - if self.main_job == job:upper() then - return "main" +local find_conflict = function(job_name, p) + if p.main_job == job_name:upper() then + return 'main' end - if self.sub_job == job:upper() then - return "sub" + if p.sub_job == job_name:upper() then + return 'sub' end end -function find_temp_job(self) - local starting_jobs = S { 'WAR', 'MNK', 'WHM', 'BLM', 'RDM', 'THF' } - for i in pairs(starting_jobs) do - if not find_conflict(i,self) then +local find_temp_job = function(p) + for _, job_name in ipairs(temp_jobs) do + if not find_conflict(job_name, p) and p.jobs[job_name:upper()] > 0 then for index,value in pairs(res.jobs) do - if value.ens == i then + if value.ens == job_name then return index end end @@ -120,8 +76,9 @@ function find_temp_job(self) end end -function find_job(job,self) - local jobLevel = self.jobs[job:upper()] +local find_job = function(job,p) + if job == nil then return nil end + local jobLevel = p.jobs[job:upper()] for index,value in pairs(res.jobs) do if value.ens:lower() == job and jobLevel > 0 then return index @@ -129,17 +86,122 @@ function find_job(job,self) end end - -function find_job_change_npc() +local find_job_change_npc = function() local info = windower.ffxi.get_info() - if not (info.mog_house or S{'Selbina', 'Mhaura', 'Tavnazian Safehold', 'Nashmau', 'Rabao', 'Kazham', 'Norg'}:contains(res.zones[info.zone].english)) then - windower.add_to_chat(4,'JobChange: Not in a zone with a Change NPC') + if not (info.mog_house or mog_zones:contains(res.zones[info.zone].english)) then + log('Not in a zone with a Change NPC') return end - for i, v in pairs(windower.ffxi.get_mob_array()) do - if v.distance < 36 and S{'Moogle', 'Nomad Moogle', 'Green Thumb Moogle'}:contains(v.name) then + for _, v in pairs(windower.ffxi.get_mob_array()) do + if v.distance < 36 and v.valid_target and moogles:contains(v.name) then return v end end end + +windower.register_event('addon command', function(command, ...) + local p = windower.ffxi.get_player() + local args = L{...} + local job = '' + if args[1] then + job = args[1]:lower() + end + local main = nil + local sub = nil + if command:lower() == 'main' then + main = job + if main and main:upper() == p.main_job then main = nil end + elseif command:lower() == 'sub' then + sub = job + if sub and sub:upper() == p.sub_job then main = nil end + elseif command:lower() == 'reset' then + log('Resetting Job') + sub = p.sub_job:lower() + elseif command:contains('/') or command:contains('\\') then + command = command:gsub('\\','/') + local js = command:split('/') + main = (js[1] ~= '' and js[1] or nil) + sub = (js[2] ~= '' and js[2] or nil) + -- remove identicals. + if main and main:upper() == p.main_job then main = nil end + if sub and sub:upper() == p.sub_job then sub = nil end + elseif command ~= nil and command ~= '' then + main = command:lower() + if main and main:upper() == p.main_job then main = nil end + else + log('Syntax: //jc main|sub JOB -- Chnages main or sub to target JOB') + log('Syntax: //jc main/sub -- Changes main and sub') + log('Syntax: //jc reset -- Resets Current Job') + return + end + + local changes = T{} + + local main_id = find_job(main, p) + if main ~= nil and main_id == nil then + log('Could not change main job to to '..main:upper()..' ---Mistype|NotUnlocked') + return + end + local sub_id = find_job(sub, p) + if sub ~= nil and sub_id == nil then + log('Could not change sub job to to '..sub:upper()..' ---Mistype|NotUnlocked') + return + end + + if main_id == nil and sub_id == nil then + log('No change required.') + return + end + + if main_id ~= nil and main:upper() == p.sub_job then + if sub_id ~= nil and sub:upper() == p.main_job then + changes:append({job_id=find_temp_job(p), is_conflict=true, is_main=false}) + changes:append({job_id=main_id, is_main=true}) + changes:append({job_id=sub_id, is_main=false}) + else + if sub_id ~= nil then + changes:append({job_id=sub_id, is_main=false}) + else + changes:append({job_id=find_temp_job(p), is_conflict=true, is_main=false}) + end + changes:append({job_id=main_id, is_main=true}) + end + elseif sub_id ~= nil and sub:upper() == p.main_job then + if main_id ~= nil then + changes:append({job_id=main_id, is_main=true}) + else + changes:append({job_id=find_temp_job(p), is_conflict=true, is_main=true}) + end + changes:append({job_id=sub_id, is_main=false}) + else + if main_id ~= nil then + if main:upper() == p.main_job then + changes:append({job_id=find_temp_job(p), is_conflict=true, is_main=true}) + end + changes:append({job_id=main_id, is_main=true}) + end + if sub_id ~= nil then + if sub:upper() == p.sub_job then + changes:append({job_id=find_temp_job(p), is_conflict=true, is_main=false}) + end + changes:append({job_id=sub_id, is_main=false}) + end + end + + local npc = find_job_change_npc() + if npc then + for _, change in ipairs(changes) do + if change.is_conflict then + log('Conflict with '..(change.is_main and 'main' or 'sub')..' job. Changing to: '..res.jobs[change.job_id].ens) + else + log('Changing '..(change.is_main and 'main' or 'sub')..' job to: '..res.jobs[change.job_id].ens) + end + jobchange(change.job_id, change.is_main) + + coroutine.sleep(0.5) + end + else + log('Not close enough to a Moogle!') + end +end) From 614d2fd8a66781407609c60facf983c71cdc9895 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Thu, 30 Apr 2020 17:02:01 +0100 Subject: [PATCH 0409/1002] Update checkparam.lua --- addons/checkparam/checkparam.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua index 5b61cfa81f..e195a74c27 100644 --- a/addons/checkparam/checkparam.lua +++ b/addons/checkparam/checkparam.lua @@ -356,8 +356,9 @@ caps={ ['cure potency']=50, ['potency of cure effects received']=30, ['quick cast']=10, - ['physical damage taken']=-25, - ['magic damage taken']=-25, + ['physical damage taken']=-50, + ['magic damage taken']=-50, + ['breath damage taken']=-50, ['pet: physical damage taken']=-87.5, ['pet: magic damage taken']=-87.5, ['pet: haste']=25, @@ -367,4 +368,4 @@ caps={ ['save tp']=500, ['fast cast']=80, ['reward']=50 -} \ No newline at end of file +} From 6136e8b3f3a2dff5c0ba04e3bf0fcf1b49df7811 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Thu, 30 Apr 2020 17:04:42 +0100 Subject: [PATCH 0410/1002] Update checkparam.lua --- addons/checkparam/checkparam.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua index e195a74c27..b0c7ceb0a9 100644 --- a/addons/checkparam/checkparam.lua +++ b/addons/checkparam/checkparam.lua @@ -221,7 +221,7 @@ integrate = { ['enhancing magic duration'] = 'enhancing magic effect duration', ['eva'] = 'evasion', ['indicolure spell duration'] = 'indicolure effect duration', - ['indi eff dur'] = 'indicolure effect duration', + ['indi eff dur'] = 'indicolure effect duration', ['mag eva'] = 'magic evasion', ['magic atk bonus'] = 'magic attack bonus', ['magatkbns'] = 'magic attack bonus', From ed205ee3ec1ac337ace3f1c7429cce269371fc1c Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Thu, 30 Apr 2020 17:17:42 +0100 Subject: [PATCH 0411/1002] Update checkparam.lua --- addons/checkparam/checkparam.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua index b0c7ceb0a9..7f31a57d0c 100644 --- a/addons/checkparam/checkparam.lua +++ b/addons/checkparam/checkparam.lua @@ -156,6 +156,7 @@ function split_text(id,text,arg) elseif key == "damage taken" then tbl['physical damage taken'] = tonumber(value)+(tbl['physical damage taken'] or 0) tbl['magic damage taken'] = tonumber(value)+(tbl['magic damage taken'] or 0) + tbl['breath damage taken'] = tonumber(value)+(tbl['breath damage taken'] or 0) else tbl[key] = tonumber(value)+(tbl[key] or 0) end From a1ddd3d91277f156d1a81023d2b8643cb536a67a Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Thu, 30 Apr 2020 12:23:48 -0600 Subject: [PATCH 0412/1002] Check Packet [0x0C9] -- corrected missing padding latest change to make the linkshell name the right data length failed to insert padding and resulted in incorrect parsing of job levels --- addons/libs/packets/fields.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 4149475199..f7426569a7 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -3281,6 +3281,7 @@ func.incoming[0x0C9][0x01] = L{ {ctype='unsigned char', label='Main Job', fn=job}, -- 12 {ctype='unsigned char', label='Sub Job', fn=job}, -- 13 {ctype='data[15]', label='Linkshell', enc=ls_enc}, -- 14 6-bit packed + {ctype='unsigned char', label='_padding1'}, -- 23 {ctype='unsigned char', label='Main Job Level'}, -- 24 {ctype='unsigned char', label='Sub Job Level'}, -- 25 {ctype='data[42]', label='_unknown5'}, -- 26 At least the first two bytes and the last twelve bytes are junk, possibly more From e79b6e6fc822ed1e654c648393f886365bfd1cde Mon Sep 17 00:00:00 2001 From: Lowclock Date: Sat, 9 May 2020 01:57:27 -0700 Subject: [PATCH 0413/1002] Correcting incoming 0x05A _unknown1 Whatever it is, it's not a constant 2 anymore. Appears to be job -1 for /jobemotes (presumably -1 because there is no None), but for other emotes it seems to vary somewhere between 0 and 2. Possibly race/model related? --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index f7426569a7..97f4b6ae1e 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2714,7 +2714,7 @@ fields.incoming[0x05A] = L{ {ctype='unsigned short', label='Player Index', fn=index}, -- 0C {ctype='unsigned short', label='Target Index', fn=index}, -- 0E {ctype='unsigned short', label='Emote', fn=emote}, -- 10 - {ctype='unsigned short', label='_unknown1', const=2}, -- 12 + {ctype='unsigned short', label='_unknown1'}, -- 12 {ctype='unsigned short', label='_unknown2'}, -- 14 {ctype='unsigned char', label='Type'}, -- 16 2 for motion, 0 otherwise {ctype='unsigned char', label='_unknown3'}, -- 17 From c0a60d712868e0eded111913995caa97091a90a5 Mon Sep 17 00:00:00 2001 From: Tylas <61948311+Tylas11@users.noreply.github.com> Date: Sat, 9 May 2020 12:58:58 +0200 Subject: [PATCH 0414/1002] fixed images.hover --- addons/libs/images.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/addons/libs/images.lua b/addons/libs/images.lua index e85d707b48..f36afa0250 100644 --- a/addons/libs/images.lua +++ b/addons/libs/images.lua @@ -351,12 +351,12 @@ function images.hover(t, x, y) local pos_x, pos_y = t:pos() local off_x, off_y = t:get_extents() - -- print(pos_x, pos_y, off_x, off_y) + -- print(x, y, pos_x, pos_y, off_x, off_y) - return (pos_x <= x and x <= pos_x + off_x - or pos_x >= x and x >= pos_x + off_x) - and (pos_y <= y and y <= pos_y + off_y - or pos_y >= y and y >= pos_y + off_y) + return (pos_x <= x and x <= off_x + or pos_x >= x and x >= off_x) + and (pos_y <= y and y <= off_y + or pos_y >= y and y >= off_y) end function images.destroy(t) From 87eedcabe843946c1b6aa652e949c489c76cc385 Mon Sep 17 00:00:00 2001 From: Tylas <61948311+Tylas11@users.noreply.github.com> Date: Sat, 9 May 2020 13:59:39 +0200 Subject: [PATCH 0415/1002] renamed local variables in images.hover --- addons/libs/images.lua | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/addons/libs/images.lua b/addons/libs/images.lua index f36afa0250..b540210254 100644 --- a/addons/libs/images.lua +++ b/addons/libs/images.lua @@ -348,15 +348,13 @@ function images.hover(t, x, y) return false end - local pos_x, pos_y = t:pos() - local off_x, off_y = t:get_extents() - - -- print(x, y, pos_x, pos_y, off_x, off_y) + local start_pos_x, start_pos_y = t:pos() + local end_pos_x, end_pos_y = t:get_extents() - return (pos_x <= x and x <= off_x - or pos_x >= x and x >= off_x) - and (pos_y <= y and y <= off_y - or pos_y >= y and y >= off_y) + return (start_pos_x <= x and x <= end_pos_x + or start_pos_x >= x and x >= end_pos_x) + and (start_pos_y <= y and y <= end_pos_y + or start_pos_y >= y and y >= end_pos_y) end function images.destroy(t) From 8bc85bd3e26c31c3949cff476b3bea922abcc28c Mon Sep 17 00:00:00 2001 From: Ivaar <7287342+Ivaar@users.noreply.github.com> Date: Wed, 20 May 2020 01:53:32 -0700 Subject: [PATCH 0416/1002] Fields: incoming 0x056 Type is a short --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index ced035ab2b..357aae839b 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2641,7 +2641,7 @@ fields.incoming[0x056] = function (data, type) end func.incoming[0x056].type = L{ - {ctype='int', label='Type', fn=e+{'quest_mission_log'}} -- 24 + {ctype='short', label='Type', fn=e+{'quest_mission_log'}} -- 24 } func.incoming[0x056][0x0080] = L{ From 04f7b0be996f57df6b2471460b2f59effc879749 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Thu, 21 May 2020 19:39:11 +0200 Subject: [PATCH 0417/1002] ConsoleBG: Whatever --- addons/ConsoleBG/ConsoleBG.lua | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/addons/ConsoleBG/ConsoleBG.lua b/addons/ConsoleBG/ConsoleBG.lua index 3c7b886061..db6ed5c5a9 100644 --- a/addons/ConsoleBG/ConsoleBG.lua +++ b/addons/ConsoleBG/ConsoleBG.lua @@ -8,16 +8,16 @@ require('logger') defaults = {} defaults.bg = {} -defaults.bg.alpha = 255 +defaults.bg.alpha = 192 defaults.bg.red = 0 defaults.bg.green = 0 defaults.bg.blue = 0 defaults.pos = {} -defaults.pos.x = 1 -defaults.pos.y = 25 +defaults.pos.x = 0 +defaults.pos.y = 0 defaults.extents = {} -defaults.extents.x = 600 -defaults.extents.y = 314 +defaults.extents.x = 7680 +defaults.extents.y = 360 settings = config.load(defaults) @@ -76,11 +76,11 @@ windower.register_event('addon command', function(command1, ...) end elseif (command1 == 'Position' or command1 == 'Size') then if ((2 > argcount) or (argcount > 2)) then - error('Invalid syntax. Check the "help" command.') + error('Invalid syntax. Check the "help" command.') else consolesettings(command1, ...) end - + end elseif command1 == 'help' then @@ -94,7 +94,7 @@ windower.register_event('addon command', function(command1, ...) else error('Unknown command! Use the "help" command for a list of commands.') - + end end) From 6b3288a922139db56e18992a233d92e310f029c1 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Mon, 1 Jun 2020 18:32:11 +0100 Subject: [PATCH 0418/1002] Update fields.lua fix in length of incoming 0x0E1 --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 28270db232..f58c76eb0a 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -3408,7 +3408,7 @@ fields.incoming[0x0E0] = L{ -- Party Member List fields.incoming[0x0E1] = L{ {ctype='unsigned short', label='Party ID'}, -- 04 For whatever reason, this is always valid ASCII in my captured packets. - {ctype='unsigned short', label='_unknown1', const=0x0080}, -- 06 Likely contains information about the current chat mode and vote count + {ctype='unsigned short', label='_unknown1', const=0x8000}, -- 06 Likely contains information about the current chat mode and vote count } -- Char Info From f6b7a95935b8defd6b5aef09d957b45a16a23d55 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Mon, 1 Jun 2020 18:32:53 +0100 Subject: [PATCH 0419/1002] Update xml.lua removed redundant newline --- addons/libs/xml.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/xml.lua b/addons/libs/xml.lua index 075b34e4c6..fc5c9bc45f 100644 --- a/addons/libs/xml.lua +++ b/addons/libs/xml.lua @@ -567,7 +567,7 @@ function table.to_xml(t, indentlevel) end if type(val) == 'table' and next(val) then str = str..indent..'<'..key..'>\n' - str = str..table.to_xml(val, indentlevel + 1)..'\n' + str = str..table.to_xml(val, indentlevel + 1) str = str..indent..'\n' else if type(val) == 'table' then From fb85ce5ed4bcae7a5abe796d5f7778a47da73b11 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Mon, 1 Jun 2020 18:37:25 +0100 Subject: [PATCH 0420/1002] Update fields.lua --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index f58c76eb0a..8f97f064e2 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -925,7 +925,7 @@ fields.outgoing[0x0C0] = L{ -- /makelinkshell fields.outgoing[0x0C3] = L{ {ctype='unsigned char', label='_unknown1'}, -- 04 - {ctype='unsigned char', label='Linkshell Numbger'}, -- 05 + {ctype='unsigned char', label='Linkshell Number'}, -- 05 {ctype='data[2]', label='_junk1'} -- 05 } From 8253e484f01f18a386bb5c8229b8a2b88a439e28 Mon Sep 17 00:00:00 2001 From: DegenerateTriangle Date: Tue, 2 Jun 2020 22:37:19 -0400 Subject: [PATCH 0421/1002] Fix merit math in pointwatch.lua. val is already being added to lp.current on line 317, so we don't need to add it again in the calculations below. --- addons/pointwatch/pointwatch.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/pointwatch/pointwatch.lua b/addons/pointwatch/pointwatch.lua index bc4f181ff0..8eac64d95c 100644 --- a/addons/pointwatch/pointwatch.lua +++ b/addons/pointwatch/pointwatch.lua @@ -315,13 +315,13 @@ function exp_msg(val,msg) elseif msg == 371 or msg == 372 then lp.registry[t] = (lp.registry[t] or 0) + val lp.current = lp.current + val - if lp.current + val >= lp.tnm and lp.number_of_merits ~= lp.maximum_merits then + if lp.current >= lp.tnm and lp.number_of_merits ~= lp.maximum_merits then -- Merit Point gained! - lp.number_of_merits = lp.number_of_merits + math.min(math.floor(lp.current/lp.tnm),lp.maximum_merits) + lp.number_of_merits = math.min(lp.number_of_merits + math.floor(lp.current/lp.tnm),lp.maximum_merits) lp.current = lp.current%lp.tnm else -- If a merit point was not gained, - lp.current = math.min(lp.current+val,lp.tnm-1) + lp.current = math.min(lp.current,lp.tnm-1) end end update_box() From 731a33c739078c8c2a7d41a2feaf5a6b1a902178 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Tue, 9 Jun 2020 20:26:34 +0200 Subject: [PATCH 0422/1002] [Battlemod] Adding dmg coloring Adding damage coloring, so the tags mydmg, partydmg, otherdmg and mobdmg on colors.xml works. --- addons/battlemod/battlemod.lua | 2 +- addons/battlemod/parse_action_packet.lua | 33 +++++++++++++++++------- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index f8d9ed3652..b5bc7ba441 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -12,7 +12,7 @@ require 'generic_helpers' require 'parse_action_packet' require 'statics' -_addon.version = '3.25' +_addon.version = '3.26' _addon.name = 'BattleMod' _addon.author = 'Byrth, maintainer: SnickySnacks' _addon.commands = {'bm','battlemod'} diff --git a/addons/battlemod/parse_action_packet.lua b/addons/battlemod/parse_action_packet.lua index a0134df87e..b0926644cd 100644 --- a/addons/battlemod/parse_action_packet.lua +++ b/addons/battlemod/parse_action_packet.lua @@ -159,8 +159,9 @@ function parse_action_packet(act) 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(res.action_messages[m.message].color,v.target[1].id==Self.id) + 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 then m.simp_name = 'hit' @@ -188,7 +189,7 @@ function parse_action_packet(act) 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}:contains(m.message) then m.simp_name = 'Magic Burst! '..act.action.name - elseif not act.action then + elseif not act.action then m.simp_name = '' act.action = {} else m.simp_name = act.action.name or '' @@ -262,7 +263,7 @@ function parse_action_packet(act) :gsub('${item2}',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 or 'ERROR 116') + :gsub('${numb}',col == 'D' and color_it(numb or 'ERROR 116', color_arr[act.actor.damage]) or (numb or 'ERROR 116')) :gsub('${actor}',color_it((act.actor.name or 'ERROR 117' ) .. (act.actor.owner_name or "") ,color_arr[act.actor.owner or act.actor.type])) :gsub('${target}',targ) :gsub('${lb}','\7') @@ -275,7 +276,8 @@ function parse_action_packet(act) 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 color = color_filt(res.action_messages[m.add_effect_message].color,v.target[1].id==Self.id) + 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] @@ -295,7 +297,7 @@ function parse_action_packet(act) :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('${numb}',col == 'D' and color_it(numb or 'ERROR 132', color_arr[act.actor.damage]) or (numb or 'ERROR 132')) :gsub('${actor}',color_it(act.actor.name,color_arr[act.actor.owner or act.actor.type])) :gsub('${target}',targ) :gsub('${lb}','\7') @@ -308,20 +310,25 @@ function parse_action_packet(act) 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 color = color_filt(res.action_messages[m.spike_effect_message].color,act.actor.id==Self.id) + 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) @@ -332,7 +339,7 @@ function parse_action_packet(act) :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('${numb}',col == 'D' and color_it(numb or 'ERROR 147', color_arr[_actor.damage]) or (numb or 'ERROR 147')) :gsub((simplify and '${target}' or '${actor}'),color_it(act.actor.name,color_arr[act.actor.owner or act.actor.type])) :gsub((simplify and '${actor}' or '${target}'),targ) :gsub('${lb}','\7') @@ -460,7 +467,7 @@ end function player_info(id) local player_table = windower.ffxi.get_mob_by_id(id) - local typ,owner,filt,owner_name + 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} @@ -471,10 +478,13 @@ function player_info(id) 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 @@ -485,11 +495,13 @@ function player_info(id) 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 '(' .. v.mob.name .. ')' @@ -498,6 +510,7 @@ function player_info(id) if i == 'p0' then typ = 'my_fellow' filt = 'my_fellow' + dmg = 'mydmg' end owner = i owner_name = showownernames and '(' .. v.mob.name .. ')' @@ -507,6 +520,7 @@ function player_info(id) else typ = 'mob' filt = 'monsters' + dmg = 'mobdmg' if filter.enemies then for i,v in pairs(Self.buffs) do @@ -531,10 +545,11 @@ function player_info(id) else typ = 'other' filt = 'others' + dmg = 'otherdmg' end end if not typ then typ = 'debug' end - return {name=player_table.name,id=id,is_npc = player_table.is_npc,type=typ,filter=filt,owner=(owner or nil), owner_name=(owner_name or nil),race = player_table.race} + return {name=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 nil),race = player_table.race} end function get_spell(act) From 53ce5484c43ab10fdc7b1feadcd5267e2a087cc2 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Tue, 9 Jun 2020 20:50:18 +0200 Subject: [PATCH 0423/1002] Update parse_action_packet.lua --- addons/battlemod/parse_action_packet.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/addons/battlemod/parse_action_packet.lua b/addons/battlemod/parse_action_packet.lua index b0926644cd..e45f9984cc 100644 --- a/addons/battlemod/parse_action_packet.lua +++ b/addons/battlemod/parse_action_packet.lua @@ -313,22 +313,22 @@ function parse_action_packet(act) local col = res.action_messages[m.spike_effect_message].color local color = color_filt(col,act.actor.id==Self.id) - local _actor = act.actor + 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 + 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 + 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 + 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) @@ -339,7 +339,7 @@ function parse_action_packet(act) :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}',col == 'D' and color_it(numb or 'ERROR 147', color_arr[_actor.damage]) or (numb or 'ERROR 147')) + :gsub('${numb}',col == 'D' and color_it(numb or 'ERROR 147', color_arr[actor.damage]) or (numb or 'ERROR 147')) :gsub((simplify and '${target}' or '${actor}'),color_it(act.actor.name,color_arr[act.actor.owner or act.actor.type])) :gsub((simplify and '${actor}' or '${target}'),targ) :gsub('${lb}','\7') From 7875f1136bdde8533183e86810274a226ca0d572 Mon Sep 17 00:00:00 2001 From: Byrth Date: Fri, 12 Jun 2020 15:49:44 -0400 Subject: [PATCH 0424/1002] switching to use a proper colors.lua path --- addons/blist/blist.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/blist/blist.lua b/addons/blist/blist.lua index a04dfd4976..509d6c1a51 100644 --- a/addons/blist/blist.lua +++ b/addons/blist/blist.lua @@ -33,7 +33,7 @@ _addon.version = '1.2.0.1' require 'tables' require 'strings' -require 'colors' +require 'chat/colors' local config = require 'config' require 'logger' From cd2b3a23dd698fe5e34f905fc65fd0e5709445ba Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 14 Jun 2020 00:17:09 +0100 Subject: [PATCH 0425/1002] Update MyHome.lua Increased cooldown tolerance --- addons/MyHome/MyHome.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/MyHome/MyHome.lua b/addons/MyHome/MyHome.lua index 46dfe658ad..5116cc3432 100644 --- a/addons/MyHome/MyHome.lua +++ b/addons/MyHome/MyHome.lua @@ -74,7 +74,7 @@ function search_item() log_flag = false log('Item use within 3 seconds..') end - until ext.usable or delay > 10 + until ext.usable or delay > 30 end windower.chat.input('/item '..windower.to_shift_jis(stats[lang])..' ') break; From 2c8fe96e9dc073a5d534d1aa3a7c57449655a250 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 14 Jun 2020 00:17:29 +0100 Subject: [PATCH 0426/1002] Update Dimmer.lua Increased cooldown tolerance --- addons/Dimmer/Dimmer.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/Dimmer/Dimmer.lua b/addons/Dimmer/Dimmer.lua index 6520909b0d..bf64f9bfba 100644 --- a/addons/Dimmer/Dimmer.lua +++ b/addons/Dimmer/Dimmer.lua @@ -75,7 +75,7 @@ function search_item() log_flag = false log('Item use within 3 seconds..') end - until ext.usable or delay > 10 + until ext.usable or delay > 30 end windower.chat.input('/item '..windower.to_shift_jis(stats[lang])..' ') break; @@ -101,4 +101,4 @@ windower.register_event('ipc message',function (msg) if msg == 'dimmer' then windower.chat.input('//dimmer') end -end) \ No newline at end of file +end) From d5ceed8ebb5493ad0a73a9f0c1c9a2df43db1eba Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 14 Jun 2020 15:00:37 +0100 Subject: [PATCH 0427/1002] Create position_manager.lua --- addons/position_manager/position_manager.lua | 83 ++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 addons/position_manager/position_manager.lua diff --git a/addons/position_manager/position_manager.lua b/addons/position_manager/position_manager.lua new file mode 100644 index 0000000000..f9ee5f4b3d --- /dev/null +++ b/addons/position_manager/position_manager.lua @@ -0,0 +1,83 @@ +--Copyright (c) 2020, Lili +--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 position_manager 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 Lili 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.name = 'position_manager' +_addon.author = 'Lili' +_addon.version = '1.0.0' +_addon.command = 'pm' + +if not windower.file_exists(windower.windower_path .. '\\plugins\\WinControl.dll') then + print('position_manager: error - Please install the WinControl plugin in the launcher.') + windower.send_command('lua u position_manager') + return +end + +config = require 'config' + +default = { + x = 0, + y = 0, +} + +settings = config.load(default) + +function move(settings) + windower.send_command('load wincontrol') + coroutine.sleep(0.5) + windower.send_command('wincontrol move %s %s':format(settings.x,settings.y)) + coroutine.sleep(0.5) + windower.send_command('unload wincontrol') +end + +function handle_commands(cmd,name,pos_x,pos_y) + local cmd = cmd or 'help' + + if cmd == 'r' then + windower.send_command('lua r position_manager') + elseif cmd == 'set' then + if name and pos_x and pos_y then + settings.x = tonumber(pos_x) + settings.y = tonumber(pos_y) + config.save(settings,name) + + if windower.ffxi.get_info().logged_in then + player_name = windower.ffxi.get_player().name + if name:lower() == player_name:lower() then + move(settings) + end + -- TODO: add IPC + end + end + elseif cmd == 'help' then + windower.add_to_chat(207,'position_manager: Usage: //pm set ') + else + windower.add_to_chat(207,'position_manager: %s command not found.':format(cmd)) + windower.send_command('pm help') + end +end + +config.register(settings,move) +windower.register_event('addon command',handle_commands) From 36195509ad1feb72bc688854711b9491e82983e4 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 14 Jun 2020 15:02:51 +0100 Subject: [PATCH 0428/1002] Create README.md --- addons/position_manager/README.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 addons/position_manager/README.md diff --git a/addons/position_manager/README.md b/addons/position_manager/README.md new file mode 100644 index 0000000000..1dc1dda645 --- /dev/null +++ b/addons/position_manager/README.md @@ -0,0 +1,24 @@ +# Position Manager + +Set and save screen position per-character. + +Command: //pm set pos_x pos_y + +### Examples: +`//pm set all 0 60` +Will set the default positioning for all characters to X: 0 and Y: 60 (the height of the Windows 10 taskbar with 150% UI scaling.) + +`//pm set Yourname 1920 0` +Will set the default position for the character called "Yourname" to X: 1920 and Y: 0. +This will make the character appear on the secondary screen that is to the right of the main screen - useful for multi-screen setups. + +`//pm set Yourmain 0 40` +`//pm set Youralt 800 40` +Will set your main to X: 0, Y: 40, and your alt to the X: 800, Y: 40. +If your laptop screen is 1600px wide, and your instances are both set at 800x600, this will put them side by side. + +Note: Characters are only moved after they're logged in. The position will be used for the character login screen as well. + +**Warning:** the `all` name will delete every other character-specific settings that are already saved! It's best to use it only once after you install the addon, to set default position for non-specified characters. + +Enjoy. From 8645df2d0ee31cfee4c7d457e7f00d60485d4c2c Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 14 Jun 2020 16:28:23 +0100 Subject: [PATCH 0429/1002] Update position_manager.lua --- addons/position_manager/position_manager.lua | 31 ++++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/addons/position_manager/position_manager.lua b/addons/position_manager/position_manager.lua index f9ee5f4b3d..f313d8d10f 100644 --- a/addons/position_manager/position_manager.lua +++ b/addons/position_manager/position_manager.lua @@ -1,4 +1,4 @@ ---Copyright (c) 2020, Lili +--Copyright © 2020, Lili --All rights reserved. --Redistribution and use in source and binary forms, with or without @@ -33,9 +33,11 @@ if not windower.file_exists(windower.windower_path .. '\\plugins\\WinControl.dll print('position_manager: error - Please install the WinControl plugin in the launcher.') windower.send_command('lua u position_manager') return +else + windower.send_command('load wincontrol') end -config = require 'config' +config = require('config') default = { x = 0, @@ -45,24 +47,26 @@ default = { settings = config.load(default) function move(settings) - windower.send_command('load wincontrol') - coroutine.sleep(0.5) windower.send_command('wincontrol move %s %s':format(settings.x,settings.y)) - coroutine.sleep(0.5) - windower.send_command('unload wincontrol') end -function handle_commands(cmd,name,pos_x,pos_y) - local cmd = cmd or 'help' - +function handle_commands(cmd,pos_x,pos_y,name) + cmd = cmd:lower() or 'help' + if cmd == 'r' then windower.send_command('lua r position_manager') elseif cmd == 'set' then + if not name or name == ':current' then + name = windower.ffxi.get_player().name + elseif name == ':all' then + name = 'all' + end + if name and pos_x and pos_y then settings.x = tonumber(pos_x) settings.y = tonumber(pos_y) config.save(settings,name) - + if windower.ffxi.get_info().logged_in then player_name = windower.ffxi.get_player().name if name:lower() == player_name:lower() then @@ -72,11 +76,12 @@ function handle_commands(cmd,name,pos_x,pos_y) end end elseif cmd == 'help' then - windower.add_to_chat(207,'position_manager: Usage: //pm set ') - else + windower.add_to_chat(207,'position_manager: Usage: //pm set [Charactername|:all|:current]') + windower.add_to_chat(207,'position_manager: See the readme for details.') + else windower.add_to_chat(207,'position_manager: %s command not found.':format(cmd)) windower.send_command('pm help') - end + end end config.register(settings,move) From ca8715d6b20febb7dfc1b872ff67ba8ef6cbc94c Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 14 Jun 2020 16:29:21 +0100 Subject: [PATCH 0430/1002] Update position_manager.lua --- addons/position_manager/position_manager.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/position_manager/position_manager.lua b/addons/position_manager/position_manager.lua index f313d8d10f..0ea5da0585 100644 --- a/addons/position_manager/position_manager.lua +++ b/addons/position_manager/position_manager.lua @@ -34,6 +34,7 @@ if not windower.file_exists(windower.windower_path .. '\\plugins\\WinControl.dll windower.send_command('lua u position_manager') return else + print('position_manager: loading WinControl...') windower.send_command('load wincontrol') end From fa3dc0ef125b06e61dcea8c2eb82032edd75970a Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 14 Jun 2020 16:38:19 +0100 Subject: [PATCH 0431/1002] Update README.md --- addons/position_manager/README.md | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/addons/position_manager/README.md b/addons/position_manager/README.md index 1dc1dda645..d1e197a85e 100644 --- a/addons/position_manager/README.md +++ b/addons/position_manager/README.md @@ -2,13 +2,22 @@ Set and save screen position per-character. -Command: //pm set pos_x pos_y +Command: `//pm set pos_x pos_y [name]` + +`pos_x` and `pos_y` are obligatory and must be numbers. +The `name` parameter is optional. If no name is provided, settings will be saved for the current character. +`:all` is a special name that can be used to set the default position. + +**Note**: Characters are only moved after they're logged in. The `:all` position will be used for the character login screen as well. ### Examples: -`//pm set all 0 60` -Will set the default positioning for all characters to X: 0 and Y: 60 (the height of the Windows 10 taskbar with 150% UI scaling.) +`//pm set 0 0` +Will set your _current_ character to the position X: 0, Y: 0. -`//pm set Yourname 1920 0` +`//pm set 0 60 :all` +Will set the default positioning for all characters to X: 0 and Y: 60 (the height of the Windows 10 taskbar with 150% UI scaling.), and delete all other character-specific settings. + +`//pm set 1920 0 Yourname` Will set the default position for the character called "Yourname" to X: 1920 and Y: 0. This will make the character appear on the secondary screen that is to the right of the main screen - useful for multi-screen setups. @@ -17,8 +26,6 @@ This will make the character appear on the secondary screen that is to the right Will set your main to X: 0, Y: 40, and your alt to the X: 800, Y: 40. If your laptop screen is 1600px wide, and your instances are both set at 800x600, this will put them side by side. -Note: Characters are only moved after they're logged in. The position will be used for the character login screen as well. - **Warning:** the `all` name will delete every other character-specific settings that are already saved! It's best to use it only once after you install the addon, to set default position for non-specified characters. Enjoy. From 0d2751cc90bcb4235ab283a03c03a34d45a027ef Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 14 Jun 2020 16:39:45 +0100 Subject: [PATCH 0432/1002] Update README.md --- addons/position_manager/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/position_manager/README.md b/addons/position_manager/README.md index d1e197a85e..7d99c83e42 100644 --- a/addons/position_manager/README.md +++ b/addons/position_manager/README.md @@ -5,7 +5,7 @@ Set and save screen position per-character. Command: `//pm set pos_x pos_y [name]` `pos_x` and `pos_y` are obligatory and must be numbers. -The `name` parameter is optional. If no name is provided, settings will be saved for the current character. +`name` is optional. If no name is provided, settings will be saved for the current character. `:all` is a special name that can be used to set the default position. **Note**: Characters are only moved after they're logged in. The `:all` position will be used for the character login screen as well. From 2f5f5f84fa7445d8bd62d99f76d751c2e0943f0a Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 14 Jun 2020 16:40:00 +0100 Subject: [PATCH 0433/1002] Update README.md --- addons/position_manager/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/position_manager/README.md b/addons/position_manager/README.md index 7d99c83e42..541d0c4e4e 100644 --- a/addons/position_manager/README.md +++ b/addons/position_manager/README.md @@ -2,7 +2,7 @@ Set and save screen position per-character. -Command: `//pm set pos_x pos_y [name]` +Command: `//pm set [name]` `pos_x` and `pos_y` are obligatory and must be numbers. `name` is optional. If no name is provided, settings will be saved for the current character. From 27344f544328d9e2685b5f0c3a5b31da5fa8f487 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 14 Jun 2020 16:47:15 +0100 Subject: [PATCH 0434/1002] Update position_manager.lua --- addons/position_manager/position_manager.lua | 28 +++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/addons/position_manager/position_manager.lua b/addons/position_manager/position_manager.lua index 0ea5da0585..ccfe9d3569 100644 --- a/addons/position_manager/position_manager.lua +++ b/addons/position_manager/position_manager.lua @@ -56,28 +56,30 @@ function handle_commands(cmd,pos_x,pos_y,name) if cmd == 'r' then windower.send_command('lua r position_manager') - elseif cmd == 'set' then - if not name or name == ':current' then + elseif cmd == 'set' and type(pos_x) == 'number' and type(pos_y) == 'number' then + if name ~= nil and type(name) ~= 'string' then + windower.add_to_chat(207,'plugin_manager: ERROR - invalid name provided.') + windower.send_command('pm help') + return + elseif not name then name = windower.ffxi.get_player().name elseif name == ':all' then name = 'all' end - if name and pos_x and pos_y then - settings.x = tonumber(pos_x) - settings.y = tonumber(pos_y) - config.save(settings,name) + settings.x = tonumber(pos_x) + settings.y = tonumber(pos_y) + config.save(settings,name) - if windower.ffxi.get_info().logged_in then - player_name = windower.ffxi.get_player().name - if name:lower() == player_name:lower() then - move(settings) - end - -- TODO: add IPC + -- TODO: possibly add IPC + if windower.ffxi.get_info().logged_in then + player_name = windower.ffxi.get_player().name + if name:lower() == player_name:lower() then + move(settings) end end elseif cmd == 'help' then - windower.add_to_chat(207,'position_manager: Usage: //pm set [Charactername|:all|:current]') + windower.add_to_chat(207,'position_manager: Usage: //pm set [name]') windower.add_to_chat(207,'position_manager: See the readme for details.') else windower.add_to_chat(207,'position_manager: %s command not found.':format(cmd)) From 13ed86f7e9d2527b4f49c0fab3d202a1cec180b9 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 14 Jun 2020 16:51:40 +0100 Subject: [PATCH 0435/1002] Space after commas --- addons/position_manager/position_manager.lua | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/addons/position_manager/position_manager.lua b/addons/position_manager/position_manager.lua index ccfe9d3569..3aa3d2b270 100644 --- a/addons/position_manager/position_manager.lua +++ b/addons/position_manager/position_manager.lua @@ -48,17 +48,17 @@ default = { settings = config.load(default) function move(settings) - windower.send_command('wincontrol move %s %s':format(settings.x,settings.y)) + windower.send_command('wincontrol move %s %s':format(settings.x, settings.y)) end -function handle_commands(cmd,pos_x,pos_y,name) +function handle_commands(cmd, pos_x, pos_y, name) cmd = cmd:lower() or 'help' if cmd == 'r' then windower.send_command('lua r position_manager') elseif cmd == 'set' and type(pos_x) == 'number' and type(pos_y) == 'number' then if name ~= nil and type(name) ~= 'string' then - windower.add_to_chat(207,'plugin_manager: ERROR - invalid name provided.') + windower.add_to_chat(207, 'plugin_manager: ERROR - invalid name provided.') windower.send_command('pm help') return elseif not name then @@ -69,7 +69,7 @@ function handle_commands(cmd,pos_x,pos_y,name) settings.x = tonumber(pos_x) settings.y = tonumber(pos_y) - config.save(settings,name) + config.save(settings, name) -- TODO: possibly add IPC if windower.ffxi.get_info().logged_in then @@ -79,13 +79,13 @@ function handle_commands(cmd,pos_x,pos_y,name) end end elseif cmd == 'help' then - windower.add_to_chat(207,'position_manager: Usage: //pm set [name]') - windower.add_to_chat(207,'position_manager: See the readme for details.') + windower.add_to_chat(207, 'position_manager: Usage: //pm set [name]') + windower.add_to_chat(207, 'position_manager: See the readme for details.') else - windower.add_to_chat(207,'position_manager: %s command not found.':format(cmd)) + windower.add_to_chat(207, 'position_manager: %s command not found.':format(cmd)) windower.send_command('pm help') end end -config.register(settings,move) -windower.register_event('addon command',handle_commands) +config.register(settings, move) +windower.register_event('addon command', handle_commands) From 6ca7e33b5fb529f579a031e9ecd72d0245ffdcd8 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 14 Jun 2020 16:54:59 +0100 Subject: [PATCH 0436/1002] Update addons.xml --- addons/addons.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/addons/addons.xml b/addons/addons.xml index 6286a66f41..bee570b840 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -819,8 +819,15 @@ IndiNope Lili - Block graphical effects from Geomancer's Indi- spells. + Blocks graphical effects from Geomancer's Indi- spells. https://github.com/Windower/Lua/issues https://github.com/lili-ffxi + + position_manager + Lili + Allows you to set a screen position per character name. Each character will be moved to that screen position on login. Requires the WinControl plugin to be installed. + https://github.com/Windower/Lua/issues + https://github.com/lili-ffxi + From 6e9fc1bd66d0db4e35838a3ea11cbc651e005c54 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 21 Jun 2020 13:31:41 +0100 Subject: [PATCH 0437/1002] Update position_manager.lua --- addons/position_manager/position_manager.lua | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/addons/position_manager/position_manager.lua b/addons/position_manager/position_manager.lua index 3aa3d2b270..bdc2899307 100644 --- a/addons/position_manager/position_manager.lua +++ b/addons/position_manager/position_manager.lua @@ -26,7 +26,7 @@ _addon.name = 'position_manager' _addon.author = 'Lili' -_addon.version = '1.0.0' +_addon.version = '1.0.1' _addon.command = 'pm' if not windower.file_exists(windower.windower_path .. '\\plugins\\WinControl.dll') then @@ -56,7 +56,7 @@ function handle_commands(cmd, pos_x, pos_y, name) if cmd == 'r' then windower.send_command('lua r position_manager') - elseif cmd == 'set' and type(pos_x) == 'number' and type(pos_y) == 'number' then + elseif cmd == 'set' and pos_x and pos_y then if name ~= nil and type(name) ~= 'string' then windower.add_to_chat(207, 'plugin_manager: ERROR - invalid name provided.') windower.send_command('pm help') @@ -69,7 +69,13 @@ function handle_commands(cmd, pos_x, pos_y, name) settings.x = tonumber(pos_x) settings.y = tonumber(pos_y) - config.save(settings, name) + if settings.x and settings.y then + config.save(settings, name) + else + windower.add_to_chat(207, 'plugin_manager: ERROR - invalid position provided.') + windower.send_command('pm help') + return + end -- TODO: possibly add IPC if windower.ffxi.get_info().logged_in then From d3ad7380a5152ed078aa7a437630fa2ec96fcef0 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 21 Jun 2020 14:30:43 +0100 Subject: [PATCH 0438/1002] Increased delay Under certain circumstances, sending `/macro book` and `/macro set` too fast can cause the loss of all macros contained in that book. Increasing the delay fixes that. --- addons/macrochanger/macrochanger.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/macrochanger/macrochanger.lua b/addons/macrochanger/macrochanger.lua index 727f592dd3..51954d8b5f 100644 --- a/addons/macrochanger/macrochanger.lua +++ b/addons/macrochanger/macrochanger.lua @@ -26,7 +26,7 @@ _addon.name = 'MacroChanger' _addon.author = 'Banggugyangu' -_addon.version = '1.0.0.1' +_addon.version = '1.0.0.2' _addon.commands = {'mc','macrochanger'} require('strings') @@ -138,7 +138,7 @@ windower.register_event('job change',function () windower.add_to_chat(17, ' Auto Macro Switching Disabled for ' .. job ..'.') else windower.add_to_chat(17, ' Changing macros to Book: ' .. book .. ' and Page: ' .. page .. '. Job Changed to ' .. job) - windower.send_command('input /macro book '..book..';wait 0.2;input /macro set '..page..';') + windower.send_command('wait 1;input /macro book '..book..';wait 1.2;input /macro set '..page..';') end elseif globaldisable == 1 then From 27666bfb6542ac27348d2bbbc61ce40efee5cbcd Mon Sep 17 00:00:00 2001 From: Byrth Date: Wed, 1 Jul 2020 07:19:14 -0400 Subject: [PATCH 0439/1002] add _unknown0 to 0x00E --- addons/libs/packets/fields.lua | 1 + addons/organizer/items.lua | 4 ++-- addons/organizer/organizer.lua | 8 +++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 8f97f064e2..7616945766 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1429,6 +1429,7 @@ fields.incoming[0x00E] = L{ {ctype='float', label='Y'}, -- 14 {ctype='unsigned int', label='Walk Count'}, -- 18 Steadily increases until rotation changes. Does not reset while the mob isn't walking. Only goes until 0xFF1F. {ctype='unsigned short', label='_unknown1', fn=bin+{2}}, -- 1A + {ctype='unsigned short', label='_unknown0', fn=bin+{2}}, -- 1C {ctype='unsigned char', label='HP %', fn=percent}, -- 1E {ctype='unsigned char', label='Status', fn=statuses}, -- 1F Status used to be 0x20 {ctype='unsigned int', label='_unknown2', fn=bin+{4}}, -- 20 diff --git a/addons/organizer/items.lua b/addons/organizer/items.lua index 9fe25746f9..b64a264455 100644 --- a/addons/organizer/items.lua +++ b/addons/organizer/items.lua @@ -42,7 +42,7 @@ local function validate_id(id) end local function wardrobecheck(bag_id,id) - return bag_id~=8 or (bag_id == 8 and res.items[id] and (res.items[id].type == 4 or res.items[id].type == 5) ) + return _static.wardrobe_ids[bag_id]==nil or ( res.items[id] and (res.items[id].type == 4 or res.items[id].type == 5) ) end function Items.new(loc_items,bool) @@ -351,7 +351,7 @@ end function item_tab:put_away(usable_bags) org_debug("move", "Putting away "..res.items[self.id].english) local current_items = self._parent._parent - usable_bags = usable_bags or {1,9,4,2,5,6,7,8} + usable_bags = usable_bags or _static.usable_bags local bag_free for _,v in ipairs(usable_bags) do local bag_max = windower.ffxi.get_bag_info(v).max diff --git a/addons/organizer/organizer.lua b/addons/organizer/organizer.lua index a4b3b774fb..a8b7bf6515 100644 --- a/addons/organizer/organizer.lua +++ b/addons/organizer/organizer.lua @@ -34,6 +34,7 @@ require 'tables' require 'lists' require 'functions' config = require 'config' +slips = require 'slips' _addon.name = 'Organizer' _addon.author = 'Byrth, maintainer: Rooks' @@ -55,7 +56,9 @@ _static = { wardrobe2=10, wardrobe3=11, wardrobe4=12, - } + }, + wardrobe_ids = {[8]=true,[10]=true,[11]=true,[12]=true}, + usable_bags = {1,9,4,2,5,6,7,8,10,11,12} } _global = { @@ -204,8 +207,7 @@ function options_load( ) if(settings.retain.slips == true) then org_verbose("Slips set to retain") - slips = {29312,29313,29314,29315,29316,29317,29318,29319,29320,29321,29322,29323,29324,29325,29326,29327,29328,29329,29330,29331,29332,29333,29334,29335,29336,29337,29338,29339} - for _,slips_id in pairs(slips) do + for _,slips_id in slips.storages:it() do _retain[slips_id] = "slips" org_debug("settings", "Adding ("..res.items[slips_id].english..') to slip retain list') end From ff86d0e30783e638a0f2062ae3ed059a21e5a2ad Mon Sep 17 00:00:00 2001 From: Byrth Date: Wed, 1 Jul 2020 07:44:42 -0400 Subject: [PATCH 0440/1002] manual reversion --- addons/libs/packets/fields.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 7616945766..8f97f064e2 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1429,7 +1429,6 @@ fields.incoming[0x00E] = L{ {ctype='float', label='Y'}, -- 14 {ctype='unsigned int', label='Walk Count'}, -- 18 Steadily increases until rotation changes. Does not reset while the mob isn't walking. Only goes until 0xFF1F. {ctype='unsigned short', label='_unknown1', fn=bin+{2}}, -- 1A - {ctype='unsigned short', label='_unknown0', fn=bin+{2}}, -- 1C {ctype='unsigned char', label='HP %', fn=percent}, -- 1E {ctype='unsigned char', label='Status', fn=statuses}, -- 1F Status used to be 0x20 {ctype='unsigned int', label='_unknown2', fn=bin+{4}}, -- 20 From 3d03918ad7d366ffd8d8444419d68d0760be6c7a Mon Sep 17 00:00:00 2001 From: Ian Anderson Date: Mon, 6 Jul 2020 01:44:42 -0700 Subject: [PATCH 0441/1002] Update roe.lua In the readme he says the command is "settings", but the handler is actually "setting" --- addons/roe/roe.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/roe/roe.lua b/addons/roe/roe.lua index a2fc4f9297..6202066ad8 100644 --- a/addons/roe/roe.lua +++ b/addons/roe/roe.lua @@ -242,7 +242,7 @@ local cmd_handlers = { list = list, set = set, unset = unset, - setting = handle_setting, + settings = handle_setting, blacklist = blacklist, help = help, } From 166314910c6697acbf0a276f6c63f31735a9cf17 Mon Sep 17 00:00:00 2001 From: Byrth Date: Sat, 11 Jul 2020 07:02:42 -0400 Subject: [PATCH 0442/1002] Slips.lua update --- addons/libs/slips.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 74480b33c7..e295ea4ad8 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,8 +34,8 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757}, -- 191 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453,}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454,}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 26545, 21977, 21978}, -- 115 - [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005}, --170 + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743}, -- 120 + [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745}, --171 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330,}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665,}, --115 [slips.storages[26]] = L{23063, 23130, 23197, 23264, 23331, 23064, 23131, 23198, 23265, 23332, 23065, 23132, 23199, 23266, 23333, 23066, 23133, 23200, 23267, 23334, 23067, 23134, 23201, 23268, 23335, 23068, 23135, 23202, 23269, 23336, 23069, 23136, 23203, 23270, 23337, 23070, 23137, 23204, 23271, 23338, 23071, 23138, 23205, 23272, 23339, 23072, 23139, 23206, 23273, 23340, 23073, 23140, 23207, 23274, 23341, 23074, 23141, 23208, 23275, 23342, 23075, 23142, 23209, 23276, 23343, 23076, 23143, 23210, 23277, 23344, 23077, 23144, 23211, 23278, 23345, 23078, 23145, 23212, 23279, 23346, 23079, 23146, 23213, 23280, 23347, 23080, 23147, 23214, 23281, 23348, 23081, 23148, 23215, 23282, 23349, 23082, 23149, 23216, 23283, 23350, 23083, 23150, 23217, 23284, 23351, 23084, 23151, 23218, 23285, 23352,}, --110 From c172496034f6add26a4a1814f3cfcc2f8586f734 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Tue, 14 Jul 2020 03:50:49 -0400 Subject: [PATCH 0443/1002] Retain Slips Fix --- addons/organizer/organizer.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/organizer/organizer.lua b/addons/organizer/organizer.lua index a8b7bf6515..92d0853dea 100644 --- a/addons/organizer/organizer.lua +++ b/addons/organizer/organizer.lua @@ -38,7 +38,7 @@ slips = require 'slips' _addon.name = 'Organizer' _addon.author = 'Byrth, maintainer: Rooks' -_addon.version = 0.20200328 +_addon.version = 0.20200714 _addon.commands = {'organizer','org'} _static = { @@ -207,7 +207,7 @@ function options_load( ) if(settings.retain.slips == true) then org_verbose("Slips set to retain") - for _,slips_id in slips.storages:it() do + for _,slips_id in pairs(slips.storages) do _retain[slips_id] = "slips" org_debug("settings", "Adding ("..res.items[slips_id].english..') to slip retain list') end From 7c69a2a27ab1e6d8b325f80d3674cf7af83021b6 Mon Sep 17 00:00:00 2001 From: Ivaar <7287342+Ivaar@users.noreply.github.com> Date: Wed, 15 Jul 2020 16:11:33 -0700 Subject: [PATCH 0444/1002] Actions lib: update for pet/trust skillchain animations --- addons/libs/actions.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/addons/libs/actions.lua b/addons/libs/actions.lua index 1dbffddc90..f55053ef6b 100644 --- a/addons/libs/actions.lua +++ b/addons/libs/actions.lua @@ -518,12 +518,16 @@ add_effect_animation_strings['weaponskill_finish'] = { [12] = 'scission', [13] = 'detonation', [14] = 'impaction', + [15] = 'radiance', + [16] = 'umbra', } add_effect_animation_strings['spell_finish'] = add_effect_animation_strings['weaponskill_finish'] +add_effect_animation_strings['mob_tp_finish'] = add_effect_animation_strings['weaponskill_finish'] +add_effect_animation_strings['avatar_tp_finish'] = add_effect_animation_strings['weaponskill_finish'] + +local add_effect_effect_strings = {} -local add_effect_effect_strings = { - } function action:get_add_effect() if not rawget(rawget(self,'raw'),'has_add_effect') then return false end local animation = self:get_add_effect_animation_string() From 50533ff3037e28e31b5ea7ac4dea600ffc951e5b Mon Sep 17 00:00:00 2001 From: Warren Ferrell Date: Thu, 16 Jul 2020 19:39:51 -0600 Subject: [PATCH 0445/1002] fix round function. Current implementation prevents the returned number from having any fractional value. source is from http://lua-users.org/wiki/SimpleRound --- addons/libs/maths.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/maths.lua b/addons/libs/maths.lua index 1119251ff7..732f8bdeb5 100644 --- a/addons/libs/maths.lua +++ b/addons/libs/maths.lua @@ -33,7 +33,7 @@ math.phi = (1 + 5:sqrt())/2 -- Rounds to prec decimal digits. Accepts negative numbers for precision. function math.round(num, prec) local mult = 10^(prec or 0) - return ((num * mult + 0.5) / mult):floor() + return (num * mult + 0.5):floor() / mult end -- Returns the sign of num, -1 for a negative number, +1 for a positive number and 0 for 0. From 6b166f6778ee9de0f9ddc011998d748dc6c35ac0 Mon Sep 17 00:00:00 2001 From: Warren Ferrell Date: Thu, 16 Jul 2020 19:26:59 -0600 Subject: [PATCH 0446/1002] return the value from the function created by prepare. --- addons/libs/functions.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/functions.lua b/addons/libs/functions.lua index 26357793c5..eaefbd7fb7 100644 --- a/addons/libs/functions.lua +++ b/addons/libs/functions.lua @@ -72,7 +72,7 @@ end function functions.prepare(fn, ...) local args = {...} return function() - fn(unpack(args)) + return fn(unpack(args)) end end From 54d90302c840883e462bb0e77d82329ffe70255e Mon Sep 17 00:00:00 2001 From: Ivaar <7287342+Ivaar@users.noreply.github.com> Date: Wed, 22 Jul 2020 08:53:32 -0700 Subject: [PATCH 0447/1002] fields.lua: add incoming 0x52 --- addons/libs/packets/fields.lua | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 8f97f064e2..6086db1249 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2579,6 +2579,28 @@ fields.incoming[0x051] = L{ {ctype='unsigned short', label='_unknown1'}, -- 16 May varying meaningfully, but it's unclear } +enums[0x052] = { + [0x00] = 'Standard', + [0x01] = 'Event', + [0x02] = 'Event Skipped', + [0x03] = 'String Event', + [0x04] = 'Fishing', +} + +func.incoming[0x052] = {} +func.incoming[0x052].base = L{ + {ctype='unsigned char', label='Type', fn=e+{0x052}}, -- 04 +} + +func.incoming[0x052][0x02] = L{ + {ctype='unsigned short', label='Menu ID'}, -- 05 +} + +-- NPC Release +fields.incoming[0x052] = function(data, type) + return func.incoming[0x052].base + (func.incoming[0x052][type or data:byte(5)] or L{}) +end + -- Logout Time -- This packet is likely used for an entire class of system messages, -- but the only one commonly encountered is the logout counter. From 043f54c7a82914410c9a782fa09690b73f7f9e15 Mon Sep 17 00:00:00 2001 From: Ivaar <7287342+Ivaar@users.noreply.github.com> Date: Thu, 23 Jul 2020 01:16:32 -0700 Subject: [PATCH 0448/1002] Treasury: add item status checks --- addons/Treasury/Treasury.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/Treasury/Treasury.lua b/addons/Treasury/Treasury.lua index 6ed443debc..028297b25e 100644 --- a/addons/Treasury/Treasury.lua +++ b/addons/Treasury/Treasury.lua @@ -1,6 +1,6 @@ _addon.name = 'Treasury' _addon.author = 'Ihina' -_addon.version = '1.2.1.0' +_addon.version = '1.2.1.1' _addon.commands = {'treasury', 'tr'} res = require('resources') @@ -122,7 +122,7 @@ function force_check() -- Check inventory for unwanted items if settings.AutoDrop then for index, item in pairs(items.inventory) do - if type(item) == 'table' and code.drop:contains(item.id) then + if type(item) == 'table' and code.drop:contains(item.id) and item.status == 0 then drop(item.id, index, item.count) end end @@ -201,7 +201,7 @@ windower.register_event('incoming chunk', function(id, data) return end - if id == 0x020 and settings.AutoDrop and code.drop:contains(chunk.Item) then + if id == 0x020 and settings.AutoDrop and code.drop:contains(chunk.Item) and chunk.Status == 0 then drop(chunk.Item, chunk.Index, chunk.Count) else -- Don't need to stack in the other case, as a new inventory packet will come in after the drop anyway From 52fcf404ad0a2cc7035dd7350fc4a00c64d18345 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Fri, 24 Jul 2020 02:14:01 +0200 Subject: [PATCH 0449/1002] Infobar fix for arithmetic on nil error Infobar fix for arithmetic on nil error --- addons/InfoBar/InfoBar.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/InfoBar/InfoBar.lua b/addons/InfoBar/InfoBar.lua index cf71358b52..8b03d0ef92 100644 --- a/addons/InfoBar/InfoBar.lua +++ b/addons/InfoBar/InfoBar.lua @@ -107,7 +107,7 @@ function get_db(target, zones, level) MOB_infobar.spawntime = spawntime or '' if isaggressive == 1 then MOB_infobar.isagressive = 'A' - if levelmax and levelmax ~= '???' and (level - tonumber(levelmax)) <= 10 then + if type(levelmax) == 'number' and (level - levelmax) <= 10 then box:bold(true) end else From 35fae6a7760e7b6c102c9ead63e6a7e031bd5662 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Mon, 27 Jul 2020 17:51:36 +0200 Subject: [PATCH 0450/1002] [Gearswap] fixed 2 bugs Fixed a bug when getting charmed and the charming mob dying very soon after and adding more sittuations where you can't summon trust and gs was not calling aftercast. --- addons/GearSwap/packet_parsing.lua | 4 ++-- addons/GearSwap/triggers.lua | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/GearSwap/packet_parsing.lua b/addons/GearSwap/packet_parsing.lua index 75c97315fd..60b71e0a0a 100644 --- a/addons/GearSwap/packet_parsing.lua +++ b/addons/GearSwap/packet_parsing.lua @@ -334,8 +334,8 @@ parse.i[0x117] = function (data) end parse.i[0x053] = function (data) - if data:unpack('H',0xD) == 0x12D and player then - -- You're unable to use trust magic if you're not the party leader or solo + if (data:unpack('H',0xD) == 0x12D or data:unpack('H',0xD) == 0x12A or data:unpack('H',0xD) == 0x12B or data:unpack('H',0xD) == 0x12C) and player then + -- You're unable to use trust magic if you're not the party leader, solo, pt full or trying to summon an already summoned trust local ts,tab = command_registry:find_by_time() if tab and tab.spell and tab.spell.prefix ~= '/pet' and not gearswap_disabled then tab.spell.action_type = 'Interruption' diff --git a/addons/GearSwap/triggers.lua b/addons/GearSwap/triggers.lua index be7f213538..5a1ca8d8fd 100644 --- a/addons/GearSwap/triggers.lua +++ b/addons/GearSwap/triggers.lua @@ -186,7 +186,7 @@ parse.i[0x028] = function (data) --print(((res[unpackedaction.resource] or {})[unpackedaction.spell_id] or {}).english,unpackedaction.type,unpackedaction.value,unpackedaction.interruption) local temp_player_mob_table,temp_pet,pet_id = windower.ffxi.get_mob_by_index(player.index) - if temp_player_mob_table.pet_index then + if temp_player_mob_table and temp_player_mob_table.pet_index then temp_pet = windower.ffxi.get_mob_by_index(temp_player_mob_table.pet_index) if temp_pet then pet_id = temp_pet.id From b0cdc1267367c2282e483c8c03d323daa5f1c1b7 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Mon, 27 Jul 2020 18:16:34 +0200 Subject: [PATCH 0451/1002] Update packet_parsing.lua unpacking before comparing --- addons/GearSwap/packet_parsing.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/GearSwap/packet_parsing.lua b/addons/GearSwap/packet_parsing.lua index 60b71e0a0a..a9e80567c5 100644 --- a/addons/GearSwap/packet_parsing.lua +++ b/addons/GearSwap/packet_parsing.lua @@ -334,7 +334,8 @@ parse.i[0x117] = function (data) end parse.i[0x053] = function (data) - if (data:unpack('H',0xD) == 0x12D or data:unpack('H',0xD) == 0x12A or data:unpack('H',0xD) == 0x12B or data:unpack('H',0xD) == 0x12C) and player then + local message = data:unpack('H',0xD) + if (message == 0x12D or message == 0x12A or message == 0x12B or message == 0x12C) and player then -- You're unable to use trust magic if you're not the party leader, solo, pt full or trying to summon an already summoned trust local ts,tab = command_registry:find_by_time() if tab and tab.spell and tab.spell.prefix ~= '/pet' and not gearswap_disabled then From c266901746e2d802bcb5163d13add03a9f694477 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Wed, 5 Aug 2020 20:29:23 +0200 Subject: [PATCH 0452/1002] [battlemod] fix and enhancements Fixed a few issues and changed a little how it displays shield block messages while also adding guarding and shield blocks to ws's. (parrying seems to not be used but leaving just in case) --- addons/battlemod/battlemod.lua | 2 +- addons/battlemod/parse_action_packet.lua | 39 ++++++++++++++++++------ addons/battlemod/statics.lua | 11 +++++++ 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index b5bc7ba441..a802e39e0e 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -12,7 +12,7 @@ require 'generic_helpers' require 'parse_action_packet' require 'statics' -_addon.version = '3.26' +_addon.version = '3.27' _addon.name = 'BattleMod' _addon.author = 'Byrth, maintainer: SnickySnacks' _addon.commands = {'bm','battlemod'} diff --git a/addons/battlemod/parse_action_packet.lua b/addons/battlemod/parse_action_packet.lua index e45f9984cc..7837addf92 100644 --- a/addons/battlemod/parse_action_packet.lua +++ b/addons/battlemod/parse_action_packet.lua @@ -53,7 +53,7 @@ function parse_action_packet(act) 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,2,4}:contains(m.effect) and S{0,2,4}:contains(r.effect)) then -- combine kicks and crits - if m.reaction == r.reaction or (S{8,10}:contains(m.reaction) and S{8,10}:contains(r.reaction)) then -- combine hits and guards + 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 @@ -163,14 +163,14 @@ function parse_action_packet(act) 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 then m.simp_name = 'hit' + --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 then m.simp_name = 'critical hit' + 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' @@ -230,7 +230,11 @@ function parse_action_packet(act) 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 - m.status = color_it('Resists',color_arr['statuscol']) + 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']) @@ -255,7 +259,24 @@ function parse_action_packet(act) msg = msg:gsub(' his ',' her ') end end - local prefix = (bit.band(m.unknown,1)==1 and "Cover! " or "")..(bit.band(m.unknown,2)==1 and "Resist! " or "")..(bit.band(m.unknown,4)==1 and "Magic Burst! " or "")..(bit.band(m.unknown,8)==1 and "Immunobreak! " or "")..(bit.band(m.unknown,16)==1 and "Critical Hit! " 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 S{1,3,4,6,11,13,14,15}:contains(act.category) and (bit.band(m.unknown,1)==1 and "Cover! " or "") + ..(bit.band(m.unknown,4)==4 and "Magic Burst! " or "") --Used on Swipe/Lunge MB + ..(bit.band(m.unknown,8)==8 and "Immunobreak! " or "") --Unused? Displayed directly on message + ..(bit.band(m.unknown,16)==16 and "Critical Hit! " or "") --Unused? Crits have their own message + ..(reaction_lookup == 4 and "Blocked! " or "") + ..(reaction_lookup == 2 and "Guarded! " or "") + ..(reaction_lookup == 3 and S{3,4,6,11,13,14,15}:contains(act.category) and "Parried! " or "") or "" --Unused? They are send the same as missed + local prefix2 = has_line_break and S{1,3,4,6,11,13,14,15}:contains(act.category) and (bit.band(m.unknown,1)==1 and "Cover! " or "") + ..(bit.band(m.unknown,2)==2 and "Resist! " or "") + ..(bit.band(m.unknown,4)==4 and "Magic Burst! " or "") --Used on Swipe/Lunge MB + ..(bit.band(m.unknown,8)==8 and "Immunobreak! " or "") --Unused? Displayed directly on message + ..(bit.band(m.unknown,16)==16 and "Critical Hit! " or "") --Unused? Crits have their own message + ..(reaction_lookup == 4 and "Blocked! " or "") + ..(reaction_lookup == 2 and "Guarded! " or "") + ..(reaction_lookup == 3 and S{3,4,6,11,13,14,15}:contains(act.category) and "Parried! " or "") or "" --Unused? They are send the same as missed windower.add_to_chat(color,prefix..make_condensedamage_number(m.number)..( (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)) @@ -266,7 +287,7 @@ function parse_action_packet(act) :gsub('${numb}',col == 'D' and color_it(numb or 'ERROR 116', color_arr[act.actor.damage]) or (numb or 'ERROR 116')) :gsub('${actor}',color_it((act.actor.name or 'ERROR 117' ) .. (act.actor.owner_name or "") ,color_arr[act.actor.owner or act.actor.type])) :gsub('${target}',targ) - :gsub('${lb}','\7') + :gsub('${lb}','\7'..prefix2) :gsub('${number}',act.action.number or m.param) :gsub('${status}',m.status or 'ERROR 120') :gsub('${gil}',m.param..' gil'))) @@ -504,7 +525,7 @@ function player_info(id) dmg = 'mydmg' end owner = i - owner_name = showownernames and '(' .. v.mob.name .. ')' + owner_name = showownernames and ' (' .. v.mob.name .. ')' 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 @@ -513,7 +534,7 @@ function player_info(id) dmg = 'mydmg' end owner = i - owner_name = showownernames and '(' .. v.mob.name .. ')' + owner_name = showownernames and ' (' .. v.mob.name .. ')' break end end diff --git a/addons/battlemod/statics.lua b/addons/battlemod/statics.lua index 01e9ddd463..c6872d9373 100644 --- a/addons/battlemod/statics.lua +++ b/addons/battlemod/statics.lua @@ -59,6 +59,17 @@ 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} From 110ccde7b272e6b7dcb7eeddbbf81d01fd3a3e5d Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Wed, 5 Aug 2020 22:41:38 +0200 Subject: [PATCH 0453/1002] Adding HQ desynth support Adding HQ desynth support --- addons/battlemod/battlemod.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index a802e39e0e..7a1e277a15 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -397,7 +397,7 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec end end elseif id == 0x06F then - if original:byte(5) == 0 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! --------------') From 31cc2780aeac8ef8c0655ef833eca65181c6839e Mon Sep 17 00:00:00 2001 From: Chiaia Date: Thu, 6 Aug 2020 01:02:03 -0400 Subject: [PATCH 0454/1002] Version Bumb for Kenshi's Changes --- addons/battlemod/battlemod.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index b5bc7ba441..a802e39e0e 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -12,7 +12,7 @@ require 'generic_helpers' require 'parse_action_packet' require 'statics' -_addon.version = '3.26' +_addon.version = '3.27' _addon.name = 'BattleMod' _addon.author = 'Byrth, maintainer: SnickySnacks' _addon.commands = {'bm','battlemod'} From c67aa225fe6a98d89f7e4b78a36a090b19499dee Mon Sep 17 00:00:00 2001 From: funkworkz Date: Thu, 6 Aug 2020 20:41:26 -0500 Subject: [PATCH 0455/1002] Voracious Resurgence songs 25 and 27 are the same song and the same file size. They might overwrite it in the future, so i left the file in this commit. --- addons/setbgm/setbgm.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/setbgm/setbgm.lua b/addons/setbgm/setbgm.lua index 045b65d79b..f3e95b0966 100644 --- a/addons/setbgm/setbgm.lua +++ b/addons/setbgm/setbgm.lua @@ -50,6 +50,7 @@ music_types = { } songs = { + [25]='Voracious Resurgence Unknown 1', [26]='Voracious Resurgence Unknown 2', [27]='Voracious Resurgence Unknown 3', [28]='Voracious Resurgence Unknown 4', [40]='Cloister of Time and Souls', [41]='Royal Wanderlust', [42]='Snowdrift Waltz', [43]='Troubled Shadows', [44]='Where Lords Rule Not', [45]='Summers Lost', [46]='Goddess Divine', [47]='Echoes of Creation', [48]='Main Theme', [49]='Luck of the Mog', [50]='Feast of the Ladies', [51]='Abyssea - Scarlet Skies, Shadowed Plains', [52]='Melodies Errant', [53]='Shinryu', [54]='Everlasting Bonds', [55]='Provenance Watcher', [56]='Where it All Begins', [57]='Steel Sings, Blades Dance', [58]='A New Direction', [59]='The Pioneers', [60]='Into Lands Primeval - Ulbuka', [61]="Water's Umbral Knell", [62]='Keepers of the Wild', [63]='The Sacred City of Adoulin', [64]='Breaking Ground', [65]='Hades', [66]='Arciela', [67]='Mog Resort', [68]='Worlds Away', [69]="Distant Worlds (Nanaa Mihgo's version)", From 33d8e1d87cc2d2ce9edfa4dd3d13a1d377c48b01 Mon Sep 17 00:00:00 2001 From: Dean James Date: Sun, 9 Aug 2020 19:21:36 +0100 Subject: [PATCH 0456/1002] Added MountRoulette addon. --- addons/MountRoulette/MountRoulette.lua | 79 ++++++++++++++++++++++++++ addons/MountRoulette/README.md | 17 ++++++ addons/addons.xml | 9 ++- 3 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 addons/MountRoulette/MountRoulette.lua create mode 100644 addons/MountRoulette/README.md diff --git a/addons/MountRoulette/MountRoulette.lua b/addons/MountRoulette/MountRoulette.lua new file mode 100644 index 0000000000..a704fd6d01 --- /dev/null +++ b/addons/MountRoulette/MountRoulette.lua @@ -0,0 +1,79 @@ +_addon.name = 'Mount Roulette' +_addon.author = 'Dean James (Xurion of Bismarck)' +_addon.version = '3.0.0' +_addon.commands = {'mountroulette', 'mr'} + +require('lists') +resources = require('resources') + +math.randomseed(os.time()) + +allowed_mounts = L{} +possible_mounts = L{} +for _, mount in ipairs(resources.mounts) do + possible_mounts:append(mount.name:lower()) +end + +function update_allowed_mounts() + local kis = windower.ffxi.get_key_items() + + for _, id in ipairs(kis) do + local ki = resources.key_items[id] + if ki.category == 'Mounts' and ki.name ~= "trainer's whistle" then -- Don't care about the quest KI + local mount_index = possible_mounts:find(function(possible_mount) + return windower.wc_match(ki.name:lower(), '♪' .. possible_mount .. '*') + end) + local mount = possible_mounts[mount_index] + + -- Add this to allowed mounts if it is not already there + if not allowed_mounts:contains(mount) then + allowed_mounts:append(mount) + end + end + end +end + +windower.register_event('load', function() + update_allowed_mounts() +end) + +windower.register_event('incoming chunk', function(id) + if id == 0x055 then --ki update + update_allowed_mounts() + end +end) + +windower.register_event('addon command', function(command) + command = command and command:lower() or 'mount' + + if commands[command] then + commands[command]() + else + commands.help() + end +end) + +commands = {} + +commands.mount = function() + local player = windower.ffxi.get_player() + + -- If the player is mounted, dismount now + for _, buff in pairs(player.buffs) do + if buff == 252 then --mounted buff + windower.send_command('input /dismount') + return + end + end + + -- Generate random number and use it to choose a mount + local mount_index = math.ceil(math.random() * #allowed_mounts) + windower.send_command('input /mount ' .. allowed_mounts[mount_index]) +end + +commands.help = function() + windower.add_to_chat(8, '---Mount Roulette---') + windower.add_to_chat(8, 'Available commands:') + windower.add_to_chat(8, '//mr mount (or just //mr) - Selects a mount at random, or dismounts if mounted') + windower.add_to_chat(8, '//mr help - displays this help') +end diff --git a/addons/MountRoulette/README.md b/addons/MountRoulette/README.md new file mode 100644 index 0000000000..5072d4ae26 --- /dev/null +++ b/addons/MountRoulette/README.md @@ -0,0 +1,17 @@ +# Final Fantasy XI Mount Roulette + +A Lua addon to summon a mount at random for Windower 4. Mimics the FFXIV Mount Roulette function. + +## Usage + +Get the addon from the addon section of the Windower launcher. + +### Summon a mount + +`//mr` + +This will also dismount you if you're currently mounted. + +## Mount music + +In an earlier version, this addon disabled mount music. This is now removed in favour of the MountMuzzle addon. diff --git a/addons/addons.xml b/addons/addons.xml index bee570b840..8fb2a71ad6 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -370,6 +370,13 @@ https://github.com/Windower/Lua/issues https://discord.gg/b275nMv + + MountRoulette + Dean James (Xurion of Bismarck) + Summon a mount at random, similar to Mount Roulette in FFXIV. + https://github.com/xurion/ffxi-mount-roulette/issues + https://www.ffxiah.com/forum/topic/52094/randommount-a-random-mount-selector-for-windower/ + NoCampaignMusic Prevents campaign battle music from playing in Shadowreign areas. @@ -829,5 +836,5 @@ Allows you to set a screen position per character name. Each character will be moved to that screen position on login. Requires the WinControl plugin to be installed. https://github.com/Windower/Lua/issues https://github.com/lili-ffxi - + From a06f84a1fe055f0fc24d325549df0006bffdff7d Mon Sep 17 00:00:00 2001 From: Dean James Date: Sun, 9 Aug 2020 20:31:18 +0100 Subject: [PATCH 0457/1002] Switched update function to use sets instead. Removed unnecessary load event. Removed unnecessary command complexity. PR comments. --- addons/MountRoulette/MountRoulette.lua | 36 ++++++-------------------- 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/addons/MountRoulette/MountRoulette.lua b/addons/MountRoulette/MountRoulette.lua index a704fd6d01..b8f86b8db9 100644 --- a/addons/MountRoulette/MountRoulette.lua +++ b/addons/MountRoulette/MountRoulette.lua @@ -4,6 +4,7 @@ _addon.version = '3.0.0' _addon.commands = {'mountroulette', 'mr'} require('lists') +require('sets') resources = require('resources') math.randomseed(os.time()) @@ -15,6 +16,7 @@ for _, mount in ipairs(resources.mounts) do end function update_allowed_mounts() + local allowed_mounts_set = S{} local kis = windower.ffxi.get_key_items() for _, id in ipairs(kis) do @@ -25,17 +27,14 @@ function update_allowed_mounts() end) local mount = possible_mounts[mount_index] - -- Add this to allowed mounts if it is not already there - if not allowed_mounts:contains(mount) then - allowed_mounts:append(mount) - end + allowed_mounts_set:add(mount) end end + + allowed_mounts = L(allowed_mounts_set) end -windower.register_event('load', function() - update_allowed_mounts() -end) +update_allowed_mounts() windower.register_event('incoming chunk', function(id) if id == 0x055 then --ki update @@ -43,19 +42,7 @@ windower.register_event('incoming chunk', function(id) end end) -windower.register_event('addon command', function(command) - command = command and command:lower() or 'mount' - - if commands[command] then - commands[command]() - else - commands.help() - end -end) - -commands = {} - -commands.mount = function() +windower.register_event('addon command', function() local player = windower.ffxi.get_player() -- If the player is mounted, dismount now @@ -69,11 +56,4 @@ commands.mount = function() -- Generate random number and use it to choose a mount local mount_index = math.ceil(math.random() * #allowed_mounts) windower.send_command('input /mount ' .. allowed_mounts[mount_index]) -end - -commands.help = function() - windower.add_to_chat(8, '---Mount Roulette---') - windower.add_to_chat(8, 'Available commands:') - windower.add_to_chat(8, '//mr mount (or just //mr) - Selects a mount at random, or dismounts if mounted') - windower.add_to_chat(8, '//mr help - displays this help') -end +end) From 8d9467d7afedf312199fd735edd06fd562f51bfa Mon Sep 17 00:00:00 2001 From: Dean James Date: Sun, 9 Aug 2020 21:56:11 +0100 Subject: [PATCH 0458/1002] Handle case where character has no mounts. --- addons/MountRoulette/MountRoulette.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/MountRoulette/MountRoulette.lua b/addons/MountRoulette/MountRoulette.lua index b8f86b8db9..355f74574f 100644 --- a/addons/MountRoulette/MountRoulette.lua +++ b/addons/MountRoulette/MountRoulette.lua @@ -53,6 +53,8 @@ windower.register_event('addon command', function() end end + if #allowed_mounts == 0 then return end + -- Generate random number and use it to choose a mount local mount_index = math.ceil(math.random() * #allowed_mounts) windower.send_command('input /mount ' .. allowed_mounts[mount_index]) From c59eface16d7e80b99f31efd06f287fc31c7450d Mon Sep 17 00:00:00 2001 From: Dean James Date: Sun, 9 Aug 2020 22:07:48 +0100 Subject: [PATCH 0459/1002] MountRoulette: Added copyright notice. --- addons/MountRoulette/MountRoulette.lua | 28 ++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/addons/MountRoulette/MountRoulette.lua b/addons/MountRoulette/MountRoulette.lua index 355f74574f..095410d409 100644 --- a/addons/MountRoulette/MountRoulette.lua +++ b/addons/MountRoulette/MountRoulette.lua @@ -1,3 +1,31 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Mount Roulette 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 Dean James (Xurion of Bismarck) 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.name = 'Mount Roulette' _addon.author = 'Dean James (Xurion of Bismarck)' _addon.version = '3.0.0' From ed24daec01f9b3c64167055ad75f53c9423a480b Mon Sep 17 00:00:00 2001 From: joshk6656 Date: Wed, 19 Aug 2020 12:06:47 -0500 Subject: [PATCH 0460/1002] Support NPC click was allowing clicking npc when out of range Support NPC click was allowing clicking npc when out of range --- addons/craft/craft.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/craft/craft.lua b/addons/craft/craft.lua index ef8922d570..c2436096db 100644 --- a/addons/craft/craft.lua +++ b/addons/craft/craft.lua @@ -231,7 +231,7 @@ end local function get_support(id, data) if (id == 0x34) and conditions['support'] then - local mob, npc = validate(support_npcs, true) + local mob, npc = validate(support_npcs, false) local p = packets.new('outgoing', 0x5b, { ["Target"] = mob.id, ["Option Index"] = 1, From 77d698189bf2f404216b22333d9185f2605c92a7 Mon Sep 17 00:00:00 2001 From: joshk6656 Date: Wed, 19 Aug 2020 12:07:12 -0500 Subject: [PATCH 0461/1002] Update README.md --- addons/craft/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/craft/README.md b/addons/craft/README.md index 4229117374..ed054005cb 100644 --- a/addons/craft/README.md +++ b/addons/craft/README.md @@ -4,7 +4,7 @@ # craft # -* A Final Fantasxy XI Crafting Addon +* A Final Fantasy XI Crafting Addon #### Commands: #### 1. help - Shows a menu of commands in game. From 5c6d29c58bd5921474b4ecdcdb107d8c8aa4d648 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Thu, 20 Aug 2020 01:39:26 -0400 Subject: [PATCH 0462/1002] Update craft.lua --- addons/craft/craft.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/craft/craft.lua b/addons/craft/craft.lua index c2436096db..079aefe21a 100644 --- a/addons/craft/craft.lua +++ b/addons/craft/craft.lua @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'craft' _addon.author = 'Mojo' -_addon.version = '1.1.0' +_addon.version = '1.1.1' _addon.commands = {'craft'} require('chat') @@ -210,7 +210,7 @@ Notes: displayed on FFXIAH. ]] -local function validate(npcs, bypass_distance) +local function validate(npcs) zone = windower.ffxi.get_info()['zone'] local valid = false for _, npc in pairs(npcs) do @@ -218,7 +218,7 @@ local function validate(npcs, bypass_distance) valid = true local mob = windower.ffxi.get_mob_by_name(npc.name) if mob then - if (math.sqrt(mob.distance) < 6) or bypass_distance then + if (math.sqrt(mob.distance) < 6) then return mob, npc end end @@ -231,7 +231,7 @@ end local function get_support(id, data) if (id == 0x34) and conditions['support'] then - local mob, npc = validate(support_npcs, false) + local mob, npc = validate(support_npcs) local p = packets.new('outgoing', 0x5b, { ["Target"] = mob.id, ["Option Index"] = 1, From 323686c20aa92d06d009a2bf747e02ffe4944b0a Mon Sep 17 00:00:00 2001 From: Dean James Date: Thu, 20 Aug 2020 09:59:18 +0100 Subject: [PATCH 0463/1002] Added item of interest tracking. --- addons/EmpyPopTracker/EmpyPopTracker.lua | 29 +++++++++++++++++++++- addons/EmpyPopTracker/nms/README.md | 8 +++++- addons/EmpyPopTracker/nms/alfard.lua | 2 ++ addons/EmpyPopTracker/nms/apademak.lua | 2 ++ addons/EmpyPopTracker/nms/azdaja.lua | 2 ++ addons/EmpyPopTracker/nms/briareus.lua | 2 ++ addons/EmpyPopTracker/nms/brulo.lua | 2 ++ addons/EmpyPopTracker/nms/bukhis.lua | 2 ++ addons/EmpyPopTracker/nms/carabosse.lua | 2 ++ addons/EmpyPopTracker/nms/chloris.lua | 2 ++ addons/EmpyPopTracker/nms/cirein-croin.lua | 2 ++ addons/EmpyPopTracker/nms/dragua.lua | 2 ++ addons/EmpyPopTracker/nms/glavoid.lua | 2 ++ addons/EmpyPopTracker/nms/isgebind.lua | 2 ++ addons/EmpyPopTracker/nms/itzpapalotl.lua | 2 ++ addons/EmpyPopTracker/nms/kukulkan.lua | 2 ++ addons/EmpyPopTracker/nms/maere.lua | 2 ++ addons/EmpyPopTracker/nms/ogopogo.lua | 2 ++ addons/EmpyPopTracker/nms/orthrus.lua | 2 ++ addons/EmpyPopTracker/nms/sedna.lua | 2 ++ addons/EmpyPopTracker/nms/sobek.lua | 2 ++ addons/EmpyPopTracker/nms/ulhuadshi.lua | 2 ++ 22 files changed, 75 insertions(+), 2 deletions(-) diff --git a/addons/EmpyPopTracker/EmpyPopTracker.lua b/addons/EmpyPopTracker/EmpyPopTracker.lua index cf178946e8..ba341cc1e7 100644 --- a/addons/EmpyPopTracker/EmpyPopTracker.lua +++ b/addons/EmpyPopTracker/EmpyPopTracker.lua @@ -29,7 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'Empy Pop Tracker' _addon.author = 'Dean James (Xurion of Bismarck)' _addon.commands = { 'ept', 'empypoptracker' } -_addon.version = '2.3.0' +_addon.version = '2.4.0' config = require('config') res = require('resources') @@ -100,6 +100,21 @@ function owns_item(id, items) return false end +function get_item_count(id, items) + local count = 0 + for _, bag in pairs(items) do + if type(bag) == 'table' then + for _, item in ipairs(bag) do + if item.id == id then + count = count + 1 + end + end + end + end + + return count +end + function owns_key_item(id, items) local owned = false @@ -183,6 +198,18 @@ function generate_text(data, key_items, items, depth) end end + if data.item then + local count = get_item_count(data.item, items) + local start = '' + local finish = '' + if count >= data.item_target_count then + start = start_color('obtained') + finish = '\\cr' + end + + text = text .. '\n\n' .. start .. res.items[data.item].name .. ': ' .. count .. '/' .. data.item_target_count .. finish + end + return text end diff --git a/addons/EmpyPopTracker/nms/README.md b/addons/EmpyPopTracker/nms/README.md index d9e9278bd9..7833e7e3bd 100644 --- a/addons/EmpyPopTracker/nms/README.md +++ b/addons/EmpyPopTracker/nms/README.md @@ -5,6 +5,8 @@ The data structure for each trackable NM uses a series of nested NM entities. A | Key | Type | Required? | Description | | ------------------- | --------- | --------- | ------------------------------ | | name | String | Required | Name of the NM | +| item | Number | Optional | The ID of the wanted item | +| item_target_count | Number | Optional | The target no. of wanted items | | pops | Table | Optional | The pop information for the NM | | pops{}.id | Number | Required | The ID of the item/key item | | pops{}.type | String | Required | Either "key item" or "item" | @@ -15,6 +17,8 @@ A simple example of the above would be: ```lua { name = 'Azdaja', + item = 3292, --Azdaja's Horn + item_target_count = 75, pops = { { id = 1531, --Vacant Bugard Eye type = 'key item', @@ -23,11 +27,13 @@ A simple example of the above would be: } ``` -A larger example with multiple nested entites: +A larger example with multiple nested entities: ```lua { name = 'Bukhis', + item = 2966, --Bukhis's Wing + item_target_count = 50, pops = { { id = 1508, --Ingrown Taurus Nail type = 'key item', diff --git a/addons/EmpyPopTracker/nms/alfard.lua b/addons/EmpyPopTracker/nms/alfard.lua index ee492fd252..d1f50b404f 100644 --- a/addons/EmpyPopTracker/nms/alfard.lua +++ b/addons/EmpyPopTracker/nms/alfard.lua @@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Alfard', + item = 3291, --Alfard's Fang + item_target_count = 75, pops = { { id = 1530, --Venomous hydra fang type = 'key item', diff --git a/addons/EmpyPopTracker/nms/apademak.lua b/addons/EmpyPopTracker/nms/apademak.lua index 4ecec8aecc..51c4a6c397 100644 --- a/addons/EmpyPopTracker/nms/apademak.lua +++ b/addons/EmpyPopTracker/nms/apademak.lua @@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Apademak', + item = 3289, --Apademak Horn + item_target_count = 75, pops = { { id = 1525, --Torn Khimaira Wing type = 'key item', diff --git a/addons/EmpyPopTracker/nms/azdaja.lua b/addons/EmpyPopTracker/nms/azdaja.lua index cb06f668d9..03c72f35e7 100644 --- a/addons/EmpyPopTracker/nms/azdaja.lua +++ b/addons/EmpyPopTracker/nms/azdaja.lua @@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Azdaja', + item = 3292, --Azdaja's Horn + item_target_count = 75, pops = { { id = 1531, --Vacant Bugard Eye type = 'key item', diff --git a/addons/EmpyPopTracker/nms/briareus.lua b/addons/EmpyPopTracker/nms/briareus.lua index 7b2e68d4b7..2cf8e93ced 100644 --- a/addons/EmpyPopTracker/nms/briareus.lua +++ b/addons/EmpyPopTracker/nms/briareus.lua @@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Briareus', + item = 2929, --Helm of Briareus + item_target_count = 50, pops = { { id = 1482, --Dented Gigas Shield type = 'key item', diff --git a/addons/EmpyPopTracker/nms/brulo.lua b/addons/EmpyPopTracker/nms/brulo.lua index 1c100b4132..668fad3922 100644 --- a/addons/EmpyPopTracker/nms/brulo.lua +++ b/addons/EmpyPopTracker/nms/brulo.lua @@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Brulo', + item = 3294, --Colorless Soul + item_target_count = 75, pops = { { id = 1652, --Emerald demilune abyssite type = 'key item', diff --git a/addons/EmpyPopTracker/nms/bukhis.lua b/addons/EmpyPopTracker/nms/bukhis.lua index b1926152a3..f435901565 100644 --- a/addons/EmpyPopTracker/nms/bukhis.lua +++ b/addons/EmpyPopTracker/nms/bukhis.lua @@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Bukhis', + item = 2966, --Bukhis's Wing + item_target_count = 50, pops = { { id = 1508, --Ingrown Taurus Nail type = 'key item', diff --git a/addons/EmpyPopTracker/nms/carabosse.lua b/addons/EmpyPopTracker/nms/carabosse.lua index ad9aa0079c..d82d78d355 100644 --- a/addons/EmpyPopTracker/nms/carabosse.lua +++ b/addons/EmpyPopTracker/nms/carabosse.lua @@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Carabosse', + item = 2930, --Carabosse's Gem + item_target_count = 50, pops = { { id = 1485, --Pellucid Fly Eye type = 'key item', diff --git a/addons/EmpyPopTracker/nms/chloris.lua b/addons/EmpyPopTracker/nms/chloris.lua index 875b5bff23..1659220bd2 100644 --- a/addons/EmpyPopTracker/nms/chloris.lua +++ b/addons/EmpyPopTracker/nms/chloris.lua @@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Chloris', + item = 2928, --2Lf. Chloris Bud + item_target_count = 50, pops = { { id = 1470, --Gory Scorpion Claw type = 'key item', diff --git a/addons/EmpyPopTracker/nms/cirein-croin.lua b/addons/EmpyPopTracker/nms/cirein-croin.lua index 478c23ffea..e561612bc5 100644 --- a/addons/EmpyPopTracker/nms/cirein-croin.lua +++ b/addons/EmpyPopTracker/nms/cirein-croin.lua @@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Cirein-croin', + item = 2965, --Cirein. Lantern + item_target_count = 50, pops = { { id = 1504, --Glistening Orobon Liver type = 'key item', diff --git a/addons/EmpyPopTracker/nms/dragua.lua b/addons/EmpyPopTracker/nms/dragua.lua index 456a477b95..f56742104b 100644 --- a/addons/EmpyPopTracker/nms/dragua.lua +++ b/addons/EmpyPopTracker/nms/dragua.lua @@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Dragua', + item = 3288, --Dragua's Scale + item_target_count = 75, pops = { { id = 1521, --Bloodied Dragon Ear type = 'key item', diff --git a/addons/EmpyPopTracker/nms/glavoid.lua b/addons/EmpyPopTracker/nms/glavoid.lua index 9beca3c7d6..b9443c76e6 100644 --- a/addons/EmpyPopTracker/nms/glavoid.lua +++ b/addons/EmpyPopTracker/nms/glavoid.lua @@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Glavoid', + item = 2927, --Glavoid Shell + item_target_count = 50, pops = { { id = 1473, --Sodden Sandworm Husk type = 'key item', diff --git a/addons/EmpyPopTracker/nms/isgebind.lua b/addons/EmpyPopTracker/nms/isgebind.lua index 1fd4de0e63..7b3125fda9 100644 --- a/addons/EmpyPopTracker/nms/isgebind.lua +++ b/addons/EmpyPopTracker/nms/isgebind.lua @@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Isgebind', + item = 3290, --Isgebind's Heart + item_target_count = 75, pops = { { id = 1526, --Begrimed Dragon Hide type = 'key item', diff --git a/addons/EmpyPopTracker/nms/itzpapalotl.lua b/addons/EmpyPopTracker/nms/itzpapalotl.lua index 371d4ab8ca..a95e1cb246 100644 --- a/addons/EmpyPopTracker/nms/itzpapalotl.lua +++ b/addons/EmpyPopTracker/nms/itzpapalotl.lua @@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Itzpapalotl', + item = 2962, --Itzpapa. Scale + item_target_count = 50, pops = { { id = 1488, --Venomous Wamoura Feeler type = 'key item', diff --git a/addons/EmpyPopTracker/nms/kukulkan.lua b/addons/EmpyPopTracker/nms/kukulkan.lua index d49fbc8aca..4ec79246bd 100644 --- a/addons/EmpyPopTracker/nms/kukulkan.lua +++ b/addons/EmpyPopTracker/nms/kukulkan.lua @@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Kukulkan', + item = 2932, --Kukulkan's Fang + item_target_count = 50, pops = { { id = 1466, --Mucid Ahriman Eyeball type = 'key item', diff --git a/addons/EmpyPopTracker/nms/maere.lua b/addons/EmpyPopTracker/nms/maere.lua index cfcc572147..eeeb9086e0 100644 --- a/addons/EmpyPopTracker/nms/maere.lua +++ b/addons/EmpyPopTracker/nms/maere.lua @@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Maere', + item = 3294, --Colorless Soul + item_target_count = 75, pops = { { id = 1654, --Indigo demilune abyssite type = 'key item', diff --git a/addons/EmpyPopTracker/nms/ogopogo.lua b/addons/EmpyPopTracker/nms/ogopogo.lua index 52a64ca259..07bae75968 100644 --- a/addons/EmpyPopTracker/nms/ogopogo.lua +++ b/addons/EmpyPopTracker/nms/ogopogo.lua @@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Ogopogo', + item = 3294, --Colorless Soul + item_target_count = 75, pops = { { id = 1653, --Vermillion demilune abyssite type = 'key item', diff --git a/addons/EmpyPopTracker/nms/orthrus.lua b/addons/EmpyPopTracker/nms/orthrus.lua index 16ff706e66..d3af0165ae 100644 --- a/addons/EmpyPopTracker/nms/orthrus.lua +++ b/addons/EmpyPopTracker/nms/orthrus.lua @@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Orthrus', + item = 3287, --Orthrus's Claw + item_target_count = 75, pops = { { id = 1520, --Steaming cerberus tongue type = 'key item', diff --git a/addons/EmpyPopTracker/nms/sedna.lua b/addons/EmpyPopTracker/nms/sedna.lua index e2d95077c7..8629925af0 100644 --- a/addons/EmpyPopTracker/nms/sedna.lua +++ b/addons/EmpyPopTracker/nms/sedna.lua @@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Sedna', + item = 2967, --Sedna's Tusk + item_target_count = 50, pops = { { id = 1512, --Shimmering Pugil Scale type = 'key item', diff --git a/addons/EmpyPopTracker/nms/sobek.lua b/addons/EmpyPopTracker/nms/sobek.lua index a9dcaa033b..682fb3bef2 100644 --- a/addons/EmpyPopTracker/nms/sobek.lua +++ b/addons/EmpyPopTracker/nms/sobek.lua @@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Sobek', + item = 2964, --Sobek's Skin + item_target_count = 50, pops = { { id = 1500, --Molted Peiste Skin type = 'key item', diff --git a/addons/EmpyPopTracker/nms/ulhuadshi.lua b/addons/EmpyPopTracker/nms/ulhuadshi.lua index 38ead13799..8d6ab0a927 100644 --- a/addons/EmpyPopTracker/nms/ulhuadshi.lua +++ b/addons/EmpyPopTracker/nms/ulhuadshi.lua @@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Ulhuadshi', + item = 2963, --Ulhuadshi's Fang + item_target_count = 50, pops = { { id = 1492, --Shriveled Hecteyes Stalk type = 'key item', From 36c696733592da37aeec4b75693c78fbaef0cd5f Mon Sep 17 00:00:00 2001 From: Dean James Date: Thu, 20 Aug 2020 10:49:38 +0100 Subject: [PATCH 0464/1002] EPT: Fix incorrect item count. --- addons/EmpyPopTracker/EmpyPopTracker.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/EmpyPopTracker/EmpyPopTracker.lua b/addons/EmpyPopTracker/EmpyPopTracker.lua index ba341cc1e7..6faa40a8eb 100644 --- a/addons/EmpyPopTracker/EmpyPopTracker.lua +++ b/addons/EmpyPopTracker/EmpyPopTracker.lua @@ -106,7 +106,7 @@ function get_item_count(id, items) if type(bag) == 'table' then for _, item in ipairs(bag) do if item.id == id then - count = count + 1 + count = count + item.count end end end From 28d095e899986f0dfeee4e4072adc05a52b22cb0 Mon Sep 17 00:00:00 2001 From: joshk6656 Date: Thu, 20 Aug 2020 21:24:39 -0500 Subject: [PATCH 0465/1002] Update recipes.lua --- addons/craft/recipes.lua | 828 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 804 insertions(+), 24 deletions(-) diff --git a/addons/craft/recipes.lua b/addons/craft/recipes.lua index cc844d626c..533b324cdd 100644 --- a/addons/craft/recipes.lua +++ b/addons/craft/recipes.lua @@ -66,6 +66,29 @@ return { "Ra'Kaznar Ingot", }, }, + ["Abyss Scythe"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Dark Matter", + "Tartarian Chain", + "Cypress Log", + "Moldy Scythe", + "Ratnaraj", + "Relic Adaman", + "Relic Adaman", + "Obsidian Crystal", + }, + }, + ["Abyssal Beads"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Waktza Crest", + "Dark Matter", + "Khoma Thread", + "Obsidian Crystal", + "Moldy Necklace", + }, + }, ["Accelerator"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -772,6 +795,19 @@ return { "Dark Anima", }, }, + ["Altana's Repast"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Holy Water", + "Holy Water", + "Cursed Beverage", + "Cursed Soup", + "Orc Offering", + "Quadav Offering", + "Yagudo Offering", + "Goblin Offering", + }, + }, ["Alumine Brayettes"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -1631,7 +1667,7 @@ return { ["ingredients"] = { "Darksteel Ingot", "Adaman Ingot", - "Electrum Ingot", + "Ebony Lumber", "Bismuth Ingot", }, }, @@ -1728,6 +1764,26 @@ return { "F. Glass Sheet", }, }, + ["Arcanoclutch"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "Mythril Sheet", + "Ice Bead", + "Homncl. Nerves", + "Plasma Oil", + "High Ebonite", + }, + }, + ["Arcanoclutch II"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "Platinum Sheet", + "Ice Bead", + "Homncl. Nerves", + "Plasma Oil", + "High Ebonite", + }, + }, ["Ardent Jadeite"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { @@ -1770,6 +1826,29 @@ return { "Platinum Silk", }, }, + ["Argute Staff"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Plovid Effluvium", + "Dark Matter", + "Khoma Thread", + "Moldy Staff", + "Ratnaraj", + "Relic Adaman", + "Relic Adaman", + "Moonstone Crystal", + }, + }, + ["Argute Stole"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Yggdreant Bole", + "Dark Matter", + "Cypress Log", + "Moonstone Crystal", + "Moldy Stole", + }, + }, ["Arhat's Gi"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -2103,6 +2182,29 @@ return { "Butterfly Axe", }, }, + ["Assassin's Gorget"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Cehuetzi Pelt", + "Dark Matter", + "S. Faulpie Leather", + "Peridot Crystal", + "Moldy Gorget", + }, + }, + ["Assassin's Knife"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Macuil Horn", + "Dark Matter", + "Ruthenium Ore", + "Moldy Dagger", + "Ratnaraj", + "Relic Adaman", + "Relic Adaman", + "Peridot Crystal", + }, + }, ["Astragalos"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { @@ -2163,6 +2265,17 @@ return { "Gold Ingot", }, }, + ["Aurgelmir Orb"] = { + ["crystal"] = "Wind Crystal", + ["ingredients"] = { + "Black Ink", + "Beastman Blood", + "Cyan Coral", + "Cyan Coral", + "Cyan Coral", + "Wyrm Ash", + }, + }, ["Aurora Mantle"] = { ["crystal"] = "Ice Crystal", ["ingredients"] = { @@ -2279,6 +2392,36 @@ return { "Polyflan Paper", }, }, + ["Automaton Oil +1"] = { + ["crystal"] = "Water Crystal", + ["ingredients"] = { + "Olive Oil", + "Olive Oil", + "Plasma Oil", + "Polyflan Paper", + }, + }, + ["Automaton Oil +2"] = { + ["crystal"] = "Water Crystal", + ["ingredients"] = { + "Olive Oil", + "Olive Oil", + "Olive Oil", + "Plasma Oil", + "Polyflan Paper", + }, + }, + ["Automaton Oil +3"] = { + ["crystal"] = "Water Crystal", + ["ingredients"] = { + "Olive Oil", + "Olive Oil", + "Olive Oil", + "Olive Oil", + "Plasma Oil", + "Polyflan Paper", + }, + }, ["Awning"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -2390,6 +2533,29 @@ return { "Iron Sheet", }, }, + ["Bagua Charm"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Cehuetzi Claw", + "Dark Matter", + "Cyan Coral", + "Emerald Crystal", + "Moldy Charm", + }, + }, + ["Bagua Wand"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Dark Matter", + "Tartarian Chain", + "Cypress Log", + "Moldy Club", + "Ratnaraj", + "Relic Adaman", + "Relic Adaman", + "Emerald Crystal", + }, + }, ["Bahadur"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -2445,6 +2611,14 @@ return { "Moval. Water", }, }, + ["Balder Earring"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "Ruthenium Ingot", + "Ruthenium Ingot", + "Wyrm Ash", + }, + }, ["Balik Sandvici"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -2577,6 +2751,29 @@ return { "Gold Ingot", }, }, + ["Bard's Charm"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Cehuetzi Claw", + "Dark Matter", + "Cyan Coral", + "Alexandrite Crystal", + "Moldy Charm", + }, + }, + ["Bard's Knife"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Macuil Horn", + "Dark Matter", + "Ruthenium Ore", + "Moldy Dagger", + "Ratnaraj", + "Relic Adaman", + "Relic Adaman", + "Alexandrite Crystal", + }, + }, ["Barnacle"] = { ["crystal"] = "Lightng. Crystal", ["ingredients"] = { @@ -3098,6 +3295,16 @@ return { "Ram Horn", }, }, + ["Beastmaster Collar"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Cehuetzi Claw", + "Dark Matter", + "Cyan Coral", + "Topaz Crystal", + "Moldy Collar", + }, + }, ["Beaugreen Saute"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -7667,6 +7874,7 @@ return { ["ingredients"] = { "Selbina Butter", "Bbl. Chocolate", + "Bbl. Chocolate", "Iron Bread", "Bird Egg", }, @@ -7861,6 +8069,29 @@ return { "Gelid Aggregate", }, }, + ["Cleric's Torque"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Waktza Crest", + "Dark Matter", + "Khoma Thread", + "Seedstone Crystal", + "Moldy Torque", + }, + }, + ["Cleric's Wand"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Dark Matter", + "Tartarian Chain", + "Cypress Log", + "Moldy Club", + "Ratnaraj", + "Relic Adaman", + "Relic Adaman", + "Seedstone Crystal", + }, + }, ["Clerisy Strap"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { @@ -8342,6 +8573,29 @@ return { "Rosewood Lbr.", }, }, + ["Commodore Charm"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Cehuetzi Claw", + "Dark Matter", + "Cyan Coral", + "Jadeite Crystal", + "Moldy Charm", + }, + }, + ["Commodore's Knife"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Macuil Horn", + "Dark Matter", + "Ruthenium Ore", + "Moldy Dagger", + "Ratnaraj", + "Relic Adaman", + "Relic Adaman", + "Jadeite Crystal", + }, + }, ["Composite Bow"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { @@ -9745,13 +9999,13 @@ return { "Dk. Ixion Ferrule", }, }, - ["Dagger"] = { + ["Dagger (Weapon)"] = { ["crystal"] = "Light Crystal", ["ingredients"] = { "Rusty Dagger", }, }, - ["Dagger 2"] = { + ["Dagger (Weapon) 2"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { "Bronze Ingot", @@ -10498,6 +10752,22 @@ return { "Bone Knife", }, }, + ["Debahocho"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "Iron Ingot", + "Willow Lumber", + }, + }, + ["Decaying Broth"] = { + ["crystal"] = "Water Crystal", + ["ingredients"] = { + "Mercury", + "Flan Meat", + "Distilled Water", + "Rotten Meat", + }, + }, ["Deductive Brocade Obi"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -11121,6 +11391,16 @@ return { "D. Fruit au Lait", }, }, + ["Dragoon's Collar"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Cehuetzi Claw", + "Dark Matter", + "Cyan Coral", + "Andalusite Crystal", + "Moldy Collar", + }, + }, ["Dresser"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -11192,6 +11472,29 @@ return { "Workshop Anvil", }, }, + ["Duelist's Sword"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Plovid Flesh", + "Dark Matter", + "Khoma Thread", + "Moldy Sword", + "Ratnaraj", + "Relic Adaman", + "Relic Adaman", + "Pyrope Crystal", + }, + }, + ["Duelist's Torque"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Waktza Crest", + "Dark Matter", + "Khoma Thread", + "Pyrope Crystal", + "Moldy Torque", + }, + }, ["Dull Gold Thread"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -12389,6 +12692,29 @@ return { "Light Anima", }, }, + ["Etoile Gorget"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Cehuetzi Pelt", + "Dark Matter", + "S. Faulpie Leather", + "Sunstone Crystal", + "Moldy Gorget", + }, + }, + ["Etoile Knife"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Macuil Horn", + "Dark Matter", + "Ruthenium Ore", + "Moldy Dagger", + "Ratnaraj", + "Relic Adaman", + "Relic Adaman", + "Sunstone Crystal", + }, + }, ["Etourdissante"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -13125,6 +13451,18 @@ return { "Leath. Kit 20", }, }, + ["Fisherman's Feast"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "Tonosama R.Ball", + "Sausage", + "Sausage", + "Salmon Rice Ball", + "Apkallu Egg", + "Graubg. Lettuce", + "Winterflower", + }, + }, ["Fisherman's Gloves"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -13520,6 +13858,15 @@ return { "Dark Anima", }, }, + ["Frizzante Broth"] = { + ["crystal"] = "Water Crystal", + ["ingredients"] = { + "Gelatin", + "Hare Meat", + "Karakul Meat", + "Ziz Meat", + }, + }, ["Frog Lure"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -13572,6 +13919,29 @@ return { "Aluminum Ingot", }, }, + ["Futhark Claymore"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Defiant Scarf", + "Dark Matter", + "Niobium Ore", + "Moldy G. Sword", + "Ratnaraj", + "Relic Adaman", + "Relic Adaman", + "Apatite Crystal", + }, + }, + ["Futhark Torque"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Waktza Crest", + "Dark Matter", + "Khoma Thread", + "Apatite Crystal", + "Moldy Torque", + }, + }, ["Gaia Doublet"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -13904,6 +14274,15 @@ return { "Mercury", }, }, + ["Gerdr Belt"] = { + ["crystal"] = "Earth Crystal", + ["ingredients"] = { + "Ocl. Chain", + "Faulpie Leather", + "Faulpie Leather", + "Wyrm Ash", + }, + }, ["Ghillie Earring"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { @@ -15038,19 +15417,6 @@ return { "Distilled Water", }, }, - ["Griffon Leather 3"] = { - ["crystal"] = "Dark Crystal", - ["ingredients"] = { - "Win. Tea Leaves", - "Win. Tea Leaves", - "Win. Tea Leaves", - "Griffon Hide", - "Griffon Hide", - "Griffon Hide", - "Tanning Vat", - "Distilled Water", - }, - }, ["Grilled Hare"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -15380,6 +15746,12 @@ return { }, }, ["Hard Leather Ring"] = { + ["crystal"] = "Wind Crystal", + ["ingredients"] = { + "Leath. Kit 60", + }, + }, + ["Hard Leather Ring 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { "Tiger Leather", @@ -18579,6 +18951,16 @@ return { "Elm Lumber", }, }, + ["Knight's Beads"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Waktza Crest", + "Dark Matter", + "Khoma Thread", + "Diamond Crystal", + "Moldy Necklace", + }, + }, ["Knight's Sword"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -18656,6 +19038,19 @@ return { "Diamond Knuckles", }, }, + ["Koga Shinobi-Gatana"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Macuil Plating", + "Dark Matter", + "Ruthenium Ore", + "Moldy Katana", + "Ratnaraj", + "Relic Adaman", + "Relic Adaman", + "Tanzanite Crystal", + }, + }, ["Kohlrouladen"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -19133,12 +19528,6 @@ return { "Dhalmel Leather", }, }, - ["Leather Ring 2"] = { - ["crystal"] = "Wind Crystal", - ["ingredients"] = { - "Leath. Kit 60", - }, - }, ["Leather Shield"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -19873,6 +20262,19 @@ return { "Water Tank", }, }, + ["Loudspeaker V"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "Treant Bulb", + "Treant Bulb", + "Baking Soda", + "Colibri Beak", + "F. Glass Sheet", + "F. Glass Sheet", + "F. Glass Sheet", + "Water Tank", + }, + }, ["Love Chocolate"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -20100,6 +20502,26 @@ return { "Gabbrath Meat", }, }, + ["Magniplug"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "Mythril Sheet", + "Fire Bead", + "Homncl. Nerves", + "Plasma Oil", + "High Ebonite", + }, + }, + ["Magniplug II"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "Platinum Sheet", + "Fire Bead", + "Homncl. Nerves", + "Plasma Oil", + "High Ebonite", + }, + }, ["Maharaja's Belt"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -21050,6 +21472,19 @@ return { "Pomodoro Sauce", }, }, + ["Melee Fists"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Hades' Claw", + "Dark Matter", + "S. Faulpie Leather", + "Moldy Weapon", + "Ratnaraj", + "Relic Adaman", + "Relic Adaman", + "Sapphire Crystal", + }, + }, ["Mellow Bird Broth"] = { ["crystal"] = "Water Crystal", ["ingredients"] = { @@ -21366,6 +21801,29 @@ return { "Glass Fiber", }, }, + ["Mirage Stole"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Yggdreant Bole", + "Dark Matter", + "Cypress Log", + "Lapis Lazuli Crystal", + "Moldy Stole", + }, + }, + ["Mirage Sword"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Plovid Flesh", + "Dark Matter", + "Khoma Thread", + "Moldy Sword", + "Ratnaraj", + "Relic Adaman", + "Relic Adaman", + "Lapis Lazuli Crystal", + }, + }, ["Misericorde"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -21655,6 +22113,29 @@ return { "Molybden. Ingot", }, }, + ["Monk's Nodowa"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Yggdreant Root", + "Dark Matter", + "Azure Leaf", + "Sapphire Crystal", + "Moldy Nodowa", + }, + }, + ["Monster Axe"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Macuil Plating", + "Dark Matter", + "S. Faulpie Leather", + "Moldy Axe", + "Ratnaraj", + "Relic Adaman", + "Relic Adaman", + "Topaz Crystal", + }, + }, ["Mont Blanc"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -22638,6 +23119,16 @@ return { "Gold Earring +1", }, }, + ["Ninja Nodowa"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Yggdreant Root", + "Dark Matter", + "Azure Leaf", + "Tanzanite Crystal", + "Moldy Nodowa", + }, + }, ["Niobium Ingot"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -23730,6 +24221,19 @@ return { "H.Q. Coeurl Hide", }, }, + ["Pantin Fists"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Hades' Claw", + "Dark Matter", + "S. Faulpie Leather", + "Moldy Weapon", + "Ratnaraj", + "Relic Adaman", + "Relic Adaman", + "Sardonyx Crystal", + }, + }, ["Papillion"] = { ["crystal"] = "Light Crystal", ["ingredients"] = { @@ -25272,6 +25776,14 @@ return { "Triturator", }, }, + ["Pristine Sap"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Divine Sap", + "Holy Water", + "Holy Water", + }, + }, ["Pro-Ether"] = { ["crystal"] = "Water Crystal", ["ingredients"] = { @@ -25396,6 +25908,16 @@ return { "Distilled Water", }, }, + ["Pup. Collar"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Cehuetzi Claw", + "Dark Matter", + "Cyan Coral", + "Sardonyx Crystal", + "Moldy Collar", + }, + }, ["Purple Earring"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -25896,6 +26418,15 @@ return { "Distilled Water", }, }, + ["Rancid Broth"] = { + ["crystal"] = "Water Crystal", + ["ingredients"] = { + "Frigorifish", + "Frigorifish", + "Frigorifish", + "Frigorifish", + }, + }, ["Ranging Knife"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { @@ -26826,7 +27357,7 @@ return { "Alabaligi", }, }, - ["Roasted Almond"] = { + ["Roasted Almonds"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { "Almond", @@ -27544,6 +28075,13 @@ return { "Vongola Clam", }, }, + ["Salted Dragonfly Trout"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "Rock Salt", + "Dragonfly Trout", + }, + }, ["Salted Hare"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -27613,6 +28151,16 @@ return { "Barbarian's Belt", }, }, + ["Samurai's Nodowa"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Yggdreant Root", + "Dark Matter", + "Azure Leaf", + "Amber Crystal", + "Moldy Nodowa", + }, + }, ["San d'Orian Bandana"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -27808,6 +28356,19 @@ return { "Cotton Cloth", }, }, + ["Saotome-no-tachi"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Macuil Plating", + "Dark Matter", + "Ruthenium Ore", + "Moldy G. Katana", + "Ratnaraj", + "Relic Adaman", + "Relic Adaman", + "Amber Crystal", + }, + }, ["Sapara"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -28166,6 +28727,16 @@ return { "Platinum Gear", }, }, + ["Scope IV"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "Glass Fiber", + "Artificial Lens", + "Artificial Lens", + "A.U Brass Sheet", + "Ocl. Gearbox", + }, + }, ["Scorpion Arrow"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -28278,6 +28849,38 @@ return { "Scorpion Shell", }, }, + ["Scout's Bolt"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Dark Matter", + "Moldy Bolt", + "Relic Adaman", + "Malachite Crystal", + }, + }, + ["Scout's Crossbow"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Macuil Plating", + "Dark Matter", + "Cyan Coral", + "Moldy Crossbow", + "Ratnaraj", + "Relic Adaman", + "Relic Adaman", + "Malachite Crystal", + }, + }, + ["Scout's Gorget"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Cehuetzi Pelt", + "Dark Matter", + "S. Faulpie Leather", + "Malachite Crystal", + "Moldy Gorget", + }, + }, ["Scutum"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -29908,6 +30511,18 @@ return { "Osseous Serum", }, }, + ["Skrymir Cord"] = { + ["crystal"] = "Earth Crystal", + ["ingredients"] = { + "Silver Thread", + "Gold Thread", + "Khoma Thread", + "Khoma Thread", + "Khoma Thread", + "Khoma Thread", + "Wyrm Ash", + }, + }, ["Slacks"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -30514,6 +31129,29 @@ return { "Distilled Water", }, }, + ["Sorcerer's Staff"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Plovid Effluvium", + "Dark Matter", + "Khoma Thread", + "Moldy Staff", + "Ratnaraj", + "Relic Adaman", + "Relic Adaman", + "Iolite Crystal", + }, + }, + ["Sorcerer's Stole"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Yggdreant Bole", + "Dark Matter", + "Cypress Log", + "Iolite Crystal", + "Moldy Stole", + }, + }, ["Soshi"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -31025,6 +31663,16 @@ return { "Water Tank", }, }, + ["Stabilizer V"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "Ocl. Sheet", + "Sieglinde Putty", + "High Ebonite", + "Black Ghost", + "Water Tank", + }, + }, ["Stamina Apple"] = { ["crystal"] = "Water Crystal", ["ingredients"] = { @@ -31563,6 +32211,29 @@ return { "Koenigs Belt", }, }, + ["Summoner's Collar"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Cehuetzi Claw", + "Dark Matter", + "Cyan Coral", + "Rutile Crystal", + "Moldy Collar", + }, + }, + ["Summoner's Staff"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Plovid Effluvium", + "Dark Matter", + "Khoma Thread", + "Moldy Staff", + "Ratnaraj", + "Relic Adaman", + "Relic Adaman", + "Rutile Crystal", + }, + }, ["Sun Earring"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -32104,6 +32775,16 @@ return { "Ocl. Gearbox", }, }, + ["Tension Spring V"] = { + ["crystal"] = "Earth Crystal", + ["ingredients"] = { + "Slime Oil", + "Darksteel Ingot", + "Golden Coil", + "Golden Coil", + "Ocl. Gearbox", + }, + }, ["Tentacle Sushi"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -32830,6 +33511,16 @@ return { "F. Glass Sheet", }, }, + ["Tranquilizer IV"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "Ocl. Sheet", + "Sieglinde Putty", + "Homncl. Nerves", + "Plasma Oil", + "F. Glass Sheet", + }, + }, ["Transfixion Sphere"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { @@ -32915,6 +33606,19 @@ return { "Mohbwa Cloth", }, }, + ["Tropical Crepe"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "San d'Or. Flour", + "Selbina Butter", + "Maple Sugar", + "Kitron", + "Persikos", + "Bird Egg", + "Uleguerand Milk", + "Felicifruit", + }, + }, ["Tropical Punches"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -32938,6 +33642,16 @@ return { "Alabaligi", }, }, + ["Truesights"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "Platinum Sheet", + "Wind Bead", + "Homncl. Nerves", + "Plasma Oil", + "High Ebonite", + }, + }, ["Trumpet Ring"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { @@ -33129,6 +33843,14 @@ return { "Ruthenium Ingot", }, }, + ["Turpid Broth"] = { + ["crystal"] = "Water Crystal", + ["ingredients"] = { + "Gelatin", + "Yawning Catfish", + "Warthog Meat", + }, + }, ["Turquoise Earring"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -33531,6 +34253,19 @@ return { "Glass Sheet", }, }, + ["Valor Sword"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Plovid Flesh", + "Dark Matter", + "Khoma Thread", + "Moldy Sword", + "Ratnaraj", + "Relic Adaman", + "Relic Adaman", + "Diamond Crystal", + }, + }, ["Vampire Juice"] = { ["crystal"] = "Water Crystal", ["ingredients"] = { @@ -34830,6 +35565,16 @@ return { "Oak Cudgel", }, }, + ["Warrior's Beads"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Waktza Crest", + "Dark Matter", + "Khoma Thread", + "Ruby Crystal", + "Moldy Necklace", + }, + }, ["Warrior's Belt"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { @@ -34843,6 +35588,19 @@ return { "Leath. Kit 25", }, }, + ["Warrior's Chopper"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Plovid Flesh", + "Dark Matter", + "Khoma Thread", + "Moldy Great Axe", + "Ratnaraj", + "Relic Adaman", + "Relic Adaman", + "Ruby Crystal", + }, + }, ["Warthog Stewpot"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -35639,7 +36397,7 @@ return { "Selbina Milk", "Yagudo Cherry", "White Honey", - "Roasted Almond", + "Roasted Almonds", }, }, ["Wivre Gorget"] = { @@ -36043,6 +36801,19 @@ return { "Wyrdstrand", }, }, + ["Wyrm Lance"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Defiant Scarf", + "Dark Matter", + "Cypress Log", + "Moldy Polearm", + "Ratnaraj", + "Relic Adaman", + "Relic Adaman", + "Andalusite Crystal", + }, + }, ["Wyvern Helm"] = { ["crystal"] = "Dark Crystal", ["ingredients"] = { @@ -36529,6 +37300,15 @@ return { "Darksteel Cap", }, }, + ["Zestful Sap"] = { + ["crystal"] = "Lightng. Crystal", + ["ingredients"] = { + "Maple Sugar", + "Maple Sugar", + "Maple Sugar", + "Urunday Log", + }, + }, ["Zinc Oxide"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { From af04e547e78fa7500150ce90757a2fdc11f867d2 Mon Sep 17 00:00:00 2001 From: joshk6656 Date: Thu, 20 Aug 2020 21:34:09 -0500 Subject: [PATCH 0466/1002] Update recipes.lua --- addons/craft/recipes.lua | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/addons/craft/recipes.lua b/addons/craft/recipes.lua index 533b324cdd..7dd8b22afa 100644 --- a/addons/craft/recipes.lua +++ b/addons/craft/recipes.lua @@ -9999,13 +9999,13 @@ return { "Dk. Ixion Ferrule", }, }, - ["Dagger (Weapon)"] = { + ["Dagger"] = { ["crystal"] = "Light Crystal", ["ingredients"] = { "Rusty Dagger", }, }, - ["Dagger (Weapon) 2"] = { + ["Dagger 2"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { "Bronze Ingot", @@ -15417,6 +15417,19 @@ return { "Distilled Water", }, }, + ["Griffon Leather 3"] = { + ["crystal"] = "Dark Crystal", + ["ingredients"] = { + "Win. Tea Leaves", + "Win. Tea Leaves", + "Win. Tea Leaves", + "Griffon Hide", + "Griffon Hide", + "Griffon Hide", + "Tanning Vat", + "Distilled Water", + }, + }, ["Grilled Hare"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -15748,13 +15761,13 @@ return { ["Hard Leather Ring"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Leath. Kit 60", + "Tiger Leather", }, }, ["Hard Leather Ring 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Tiger Leather", + "Leath. Kit 60", }, }, ["Hard-boiled Egg"] = { @@ -19528,6 +19541,12 @@ return { "Dhalmel Leather", }, }, + ["Leather Ring 2"] = { + ["crystal"] = "Wind Crystal", + ["ingredients"] = { + "Leath. Kit 60", + }, + }, ["Leather Shield"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { From bb76e4d8434477a03eb9120c160fe1994b7ba16b Mon Sep 17 00:00:00 2001 From: joshk6656 Date: Thu, 20 Aug 2020 21:38:05 -0500 Subject: [PATCH 0467/1002] Update recipes.lua --- addons/craft/recipes.lua | 6 ------ 1 file changed, 6 deletions(-) diff --git a/addons/craft/recipes.lua b/addons/craft/recipes.lua index 7dd8b22afa..04b3f19dd9 100644 --- a/addons/craft/recipes.lua +++ b/addons/craft/recipes.lua @@ -19541,12 +19541,6 @@ return { "Dhalmel Leather", }, }, - ["Leather Ring 2"] = { - ["crystal"] = "Wind Crystal", - ["ingredients"] = { - "Leath. Kit 60", - }, - }, ["Leather Shield"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { From e388bf82bf436407a792c5acd5252ae823d447b0 Mon Sep 17 00:00:00 2001 From: joshk6656 Date: Fri, 21 Aug 2020 17:57:06 -0500 Subject: [PATCH 0468/1002] Update craft.lua Add lightning card --- addons/craft/craft.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/craft/craft.lua b/addons/craft/craft.lua index 079aefe21a..66717857c4 100644 --- a/addons/craft/craft.lua +++ b/addons/craft/craft.lua @@ -106,6 +106,7 @@ local exceptions = { ['Ice Card'] = 9765, ['Wind Card'] = 9766, ['Earth Card'] = 9767, + ['Lightning Card'] = 9768, ['Water Card'] = 9769, ['Light Card'] = 9770, ['Dark Card'] = 9771, From aff2c817996a809d881c0ff36bf09fec7b3a73c1 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 23 Aug 2020 14:57:48 +0100 Subject: [PATCH 0469/1002] Fixed weather_intensity bug Removed incorrect logic that made weather_intensity return 2 (double weather) if tier 1 scholar -storm buff were active while the natural weather of the same element was active. -storm spells always overwrite natural weather no matter what. --- addons/GearSwap/refresh.lua | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/addons/GearSwap/refresh.lua b/addons/GearSwap/refresh.lua index a2cfd028a6..22de974f95 100644 --- a/addons/GearSwap/refresh.lua +++ b/addons/GearSwap/refresh.lua @@ -425,30 +425,21 @@ function weather_update(id) world.real_weather = res.weather[id][language] world.real_weather_element = res.elements[res.weather[id].element][language] world.real_weather_intensity = res.weather[world.real_weather_id].intensity - local buff = false if buffactive[178] then - buff = true world.weather_id = 4 elseif buffactive[179] then - buff = true world.weather_id = 12 elseif buffactive[180] then - buff = true world.weather_id = 10 elseif buffactive[181] then - buff = true world.weather_id = 8 elseif buffactive[182] then - buff = true world.weather_id = 14 elseif buffactive[183] then - buff = true world.weather_id = 6 elseif buffactive[184] then - buff = true world.weather_id = 16 elseif buffactive[185] then - buff = true world.weather_id = 18 elseif buffactive[589] then world.weather_id = 5 @@ -467,9 +458,6 @@ function weather_update(id) elseif buffactive[596] then world.weather_id = 19 end - if buff and world.weather_id == world.real_weather_id then - world.weather_id = world.weather_id + 1 - end world.weather = res.weather[world.weather_id][language] world.weather_element = res.elements[res.weather[world.weather_id].element][language] world.weather_intensity = res.weather[world.weather_id].intensity From eaed2c287f4d40e120e0a8e29442a58c4badf585 Mon Sep 17 00:00:00 2001 From: GlarinAsura <65004070+GlarinAsura@users.noreply.github.com> Date: Sat, 29 Aug 2020 23:59:00 -0700 Subject: [PATCH 0470/1002] Adding NyzulHelper addon. Initial commit of NyzulHelper addon. --- addons/NyzulHelper/NyzulHelper.lua | 306 +++++++++++++++++++++++++++++ addons/NyzulHelper/ReadMe.md | 6 + 2 files changed, 312 insertions(+) create mode 100644 addons/NyzulHelper/NyzulHelper.lua create mode 100644 addons/NyzulHelper/ReadMe.md diff --git a/addons/NyzulHelper/NyzulHelper.lua b/addons/NyzulHelper/NyzulHelper.lua new file mode 100644 index 0000000000..e21e62440c --- /dev/null +++ b/addons/NyzulHelper/NyzulHelper.lua @@ -0,0 +1,306 @@ +--[[ +Copyright (c) 2020, Glarin of Asura +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 PartyMaster 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 Glarin 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.name = 'NyzulHelper' +_addon.author = 'Glarin' +_addon.version = '1.0' +_addon.commands = {'nh', 'nyzulhelper'} +_addon.language = 'english' + +require('logger') +require('coroutine') + +config = require('config') +packets = require('packets') +res = require('resources') +texts = require('texts') + +defaults = {} +defaults.interval = .1 + +settings = config.load(defaults) +box = texts.new('${current_string}', settings) + +pending_color = "\\cs(255,250,120)" +warning_color = "\\cs(255,165,0)" +good_color = "\\cs(0,255,0)" +bad_color = "\\cs(255,0,0)" + +frame_time = 0 +zone_timer = 0 +end_time = nil +has_armband = false +party_size = 1 +objective = '' +floor_clear = pending_color +restriction = '' +restriction_failed = warning_color +starting_floor = 0 +current_floor = 0 +completed = 0 +floor_penalities = 0 +potential_tokens = 0 + + +-- Handle addon args +windower.register_event('addon command', function(input, ...) + + local cmd = string.lower(input) + local args = {...} + + if cmd == 'reset' then + reset() + elseif cmd == 'show' then + box:show() + elseif cmd == 'hide' then + box:hide() + elseif cmd == 'reload' then + windower.send_command('lua reload nyzulhelper') + else + log(cmd..' command unknown.') + end + +end) + +-- Event Handlers +windower.register_event('load', function() + + local info = windower.ffxi.get_info() + if info.logged_in and info.zone == 77 then + box:show() + end + +end) + +windower.register_event('prerender', function() + + local curr = os.clock() + if curr > frame_time + settings.interval then + if end_time ~= nil and zone_timer >= 1 and zone_timer ~= (end_time - os.time()) then + zone_timer = end_time - os.time() + end + + frame_time = curr + update_box() + end + +end) + +windower.register_event('zone change',function(new, old) + + box:hide() + + if new == 72 and old == 77 then + zone_timer = 0 + has_armband = false + else + reset() + end + + if new == 77 then + box:show() + party_size = windower.ffxi.get_party_info().party1_count + end + +end) + +windower.register_event('incoming chunk', function(id, data, modified, injected, blocked) + + if id == 0x55 and windower.ffxi.get_info().zone == 72 and has_value(windower.ffxi.get_key_items(), 797) then + has_armband = true + end + +end) + +windower.register_event('incoming text', function(original, modified, mode, _, blocked) + + local info = windower.ffxi.get_info() + if not info.logged_in or info.zone ~= 77 or blocked or original == '' then + return + end + + if mode == 123 then + + if string.find(original, "Security field malfunction") then + restriction = string.strip_format(original) + restriction_failed = bad_color + update_box() + elseif string.find(original, "Time limit has been reduced") then + set_timer(zone_timer - tonumber(original:match("%d+")) * 60) + elseif string.find(original, "Potential token reward reduced") then + floor_penalities = floor_penalities + 1 + end + + elseif (mode == 146 or mode == 148) and string.find(original, "(Earth time)") then + + local multiplier = 1 + if string.find(original, "minute") then multiplier = 60 end + + set_timer(tonumber(original:match("%d+")) * multiplier) + + elseif mode == 146 then + + if string.find(original,"Floor %d+ objective complete. Rune of Transfer activated.") then + completed = completed + 1 + floor_clear = good_color + restriction = '' + restriction_failed = warning_color + calculate_tokens() + update_box() + end + + elseif mode == 148 then + + if string.find(original,"Objective:") then + if string.find(original,"Commencing") then + objective = "Complete on-site objectives" + else + objective = string.strip_format(original:sub(11)) + end + floor_clear = pending_color + elseif string.find(original, "archaic") then + restriction = string.strip_format(original) + elseif string.find(original,"Transfer complete. Welcome to Floor %d+.") then + current_floor = tonumber(original:match("%d+")) + resync_values() + end + + end + +end) + +function reset() + + zone_timer = 0 + end_time = nil + objective = '' + floor_clear = pending_color + restriction = '' + restriction_failed = warning_color + starting_floor = 0 + current_floor = 0 + completed = 0 + floor_penalities = 0 + potential_tokens = 0 + +end + +function has_value(list, value) + + if list ~= nil and value ~= nil then + for _, v in pairs(list) do + if v == value then + return true + end + end + end + + return false + +end + +function set_timer(remaining) + + zone_timer = remaining + end_time = os.time() + zone_timer + +end + +function get_relative_floor() + + if current_floor < starting_floor then + return current_floor + 100 + end + + return current_floor + +end + +function get_token_rate() + + local rate = 1 + if has_armband then rate = rate + .1 end + if party_size > 3 then rate = rate - ((party_size - 3 ) * .1) end + + return rate + +end + +function resync_values() + + if starting_floor == 0 then + starting_floor = current_floor + if zone_timer == 0 then set_timer(1800) end + end + + local relative_floor = get_relative_floor() + if (relative_floor - starting_floor) > completed then + completed = relative_floor - starting_floor + end + + floor_penalities = 0 + +end + +function get_token_penalty(rate) + + return math.round(117 * rate) * floor_penalities + +end + +function calculate_tokens() + + local relative_floor = get_relative_floor() + local rate = get_token_rate() + + local floor_bonus = 0 + if relative_floor > 1 then floor_bonus = (10 * math.floor((relative_floor - 1) / 5)) end + + potential_tokens = potential_tokens + ((200 + floor_bonus) * rate) - get_token_penalty(rate) + +end + +function update_box() + + local timer_color = '' + if zone_timer < 60 then timer_color = bad_color end + + local lines = L{} + lines:append(' Current Floor: '..current_floor) + lines:append('\n Time Remaining: '..timer_color..os.date('%M:%S', zone_timer).."\\cr ") + lines:append('\n Objective: '..floor_clear..objective.."\\cr ") + if restriction ~= '' then + lines:append(' Restriction: '..restriction_failed..restriction.."\\cr ") + end + lines:append('\n Floors Completed: '..completed) + lines:append(' Reward Rate: %d%%':format(get_token_rate() * 100)) + lines:append(' Potential Tokens: '..potential_tokens) + + box.current_string = lines:concat('\n') + +end \ No newline at end of file diff --git a/addons/NyzulHelper/ReadMe.md b/addons/NyzulHelper/ReadMe.md new file mode 100644 index 0000000000..d0f9f85bc4 --- /dev/null +++ b/addons/NyzulHelper/ReadMe.md @@ -0,0 +1,6 @@ +**Authors:** Glarin +**Version:** 1.0 +**Date:** 7/14/2020 + +**Description:** +NyzulHelper is an addon that tracks and displays the Current Floor, Time Remaining, Objective, Floors Completed, Reward Rate, and Potenial Tokens. \ No newline at end of file From 4587a0ecdf84fb1c25b6e7f2e64ac9c8567b9772 Mon Sep 17 00:00:00 2001 From: Dean James Date: Mon, 31 Aug 2020 22:01:24 +0100 Subject: [PATCH 0471/1002] Fixing inability to summon chocobo mount. Fixing inability to summon multi-word mounts. --- addons/MountRoulette/MountRoulette.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/MountRoulette/MountRoulette.lua b/addons/MountRoulette/MountRoulette.lua index 095410d409..0b272b70e3 100644 --- a/addons/MountRoulette/MountRoulette.lua +++ b/addons/MountRoulette/MountRoulette.lua @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'Mount Roulette' _addon.author = 'Dean James (Xurion of Bismarck)' -_addon.version = '3.0.0' +_addon.version = '3.0.1' _addon.commands = {'mountroulette', 'mr'} require('lists') @@ -39,7 +39,7 @@ math.randomseed(os.time()) allowed_mounts = L{} possible_mounts = L{} -for _, mount in ipairs(resources.mounts) do +for _, mount in pairs(resources.mounts) do possible_mounts:append(mount.name:lower()) end @@ -85,5 +85,5 @@ windower.register_event('addon command', function() -- Generate random number and use it to choose a mount local mount_index = math.ceil(math.random() * #allowed_mounts) - windower.send_command('input /mount ' .. allowed_mounts[mount_index]) + windower.send_command('input /mount "' .. allowed_mounts[mount_index] .. '"') end) From 1a93f215b3041d0a2644971405d612e55a89d6b7 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 6 Sep 2020 02:41:02 +0100 Subject: [PATCH 0472/1002] Added delay setting. --- addons/position_manager/README.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/addons/position_manager/README.md b/addons/position_manager/README.md index 541d0c4e4e..dcbfce28df 100644 --- a/addons/position_manager/README.md +++ b/addons/position_manager/README.md @@ -2,7 +2,8 @@ Set and save screen position per-character. -Command: `//pm set [name]` +Command: +`//pm set [name]` `pos_x` and `pos_y` are obligatory and must be numbers. `name` is optional. If no name is provided, settings will be saved for the current character. @@ -10,6 +11,10 @@ Command: `//pm set [name]` **Note**: Characters are only moved after they're logged in. The `:all` position will be used for the character login screen as well. +**Note**: On some systems with very fast or very slow disks, it can happen that the `WinControl` addon does not get loaded in time for `position_manager` to send the proper command. In that case, you can use this command: +`//pm set delay [name]` +(where `seconds` is obligatory and must be a positive number, and `name` follows the same rules as before), to set a delay that will hopefully let the plugin load in time. + ### Examples: `//pm set 0 0` Will set your _current_ character to the position X: 0, Y: 0. @@ -21,11 +26,12 @@ Will set the default positioning for all characters to X: 0 and Y: 60 (the heigh Will set the default position for the character called "Yourname" to X: 1920 and Y: 0. This will make the character appear on the secondary screen that is to the right of the main screen - useful for multi-screen setups. +`//pm set delay 1 all` `//pm set Yourmain 0 40` `//pm set Youralt 800 40` -Will set your main to X: 0, Y: 40, and your alt to the X: 800, Y: 40. +Will set delay to 1 for all characters, then set the position of your main to X: 0, Y: 40, and your alt to X: 800, Y: 40. If your laptop screen is 1600px wide, and your instances are both set at 800x600, this will put them side by side. -**Warning:** the `all` name will delete every other character-specific settings that are already saved! It's best to use it only once after you install the addon, to set default position for non-specified characters. +**Warning:** the `all` name will delete every other character-specific settings that are already saved! It's best to use it only once after you install the addon, to set default position and delay for non-specified characters. Enjoy. From c75a8d0f56c43313e20ec4cd67690c5d77f9c0c4 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 6 Sep 2020 02:41:48 +0100 Subject: [PATCH 0473/1002] Added delay setting. --- addons/position_manager/position_manager.lua | 75 +++++++++++++------- 1 file changed, 49 insertions(+), 26 deletions(-) diff --git a/addons/position_manager/position_manager.lua b/addons/position_manager/position_manager.lua index bdc2899307..388952bda6 100644 --- a/addons/position_manager/position_manager.lua +++ b/addons/position_manager/position_manager.lua @@ -26,7 +26,7 @@ _addon.name = 'position_manager' _addon.author = 'Lili' -_addon.version = '1.0.1' +_addon.version = '1.1' _addon.command = 'pm' if not windower.file_exists(windower.windower_path .. '\\plugins\\WinControl.dll') then @@ -43,22 +43,28 @@ config = require('config') default = { x = 0, y = 0, + delay = 0, } settings = config.load(default) function move(settings) + if settings.delay > 0 then + coroutine.sleep(settings.delay) + end windower.send_command('wincontrol move %s %s':format(settings.x, settings.y)) end -function handle_commands(cmd, pos_x, pos_y, name) - cmd = cmd:lower() or 'help' +function handle_commands(cmd, ...) + cmd = cmd:lower() if cmd == 'r' then windower.send_command('lua r position_manager') - elseif cmd == 'set' and pos_x and pos_y then + return + elseif cmd == 'set' then + local name = arg[3] if name ~= nil and type(name) ~= 'string' then - windower.add_to_chat(207, 'plugin_manager: ERROR - invalid name provided.') + windower.add_to_chat(207, 'position_manager: ERROR - invalid name provided.') windower.send_command('pm help') return elseif not name then @@ -67,31 +73,48 @@ function handle_commands(cmd, pos_x, pos_y, name) name = 'all' end - settings.x = tonumber(pos_x) - settings.y = tonumber(pos_y) - if settings.x and settings.y then - config.save(settings, name) - else - windower.add_to_chat(207, 'plugin_manager: ERROR - invalid position provided.') - windower.send_command('pm help') - return - end - - -- TODO: possibly add IPC - if windower.ffxi.get_info().logged_in then - player_name = windower.ffxi.get_player().name - if name:lower() == player_name:lower() then - move(settings) + if arg[1] == 'delay' then + settings.delay = tonumber(arg[2]) + if settings.delay > 0 then + config.save(settings, name) + windower.add_to_chat(207, 'position_manager: Delay set to %s for %s.':format(settings.delay, name)) + else + windower.add_to_chat(207, 'position_manager: ERROR - invalid delay provided.') + windower.send_command('pm help') + return + end + elseif tonumber(arg[1]) and tonumber(arg[2]) then + settings.x = tonumber(arg[1]) + settings.y = tonumber(arg[2]) + + if settings.x and settings.y then + config.save(settings, name) + + if windower.ffxi.get_info().logged_in then + player_name = windower.ffxi.get_player().name + if name:lower() == player_name:lower() then + move(settings) + end + end + windower.add_to_chat(207, 'position_manager: Position set to %s,%s for %s.':format(settings.x, settings.y, name)) + else + windower.add_to_chat(207, 'position_manager: ERROR - invalid position provided.') + windower.send_command('pm help') + return end end - elseif cmd == 'help' then - windower.add_to_chat(207, 'position_manager: Usage: //pm set [name]') - windower.add_to_chat(207, 'position_manager: See the readme for details.') - else + -- TODO: possibly add IPC + return + elseif cmd ~= 'help' then windower.add_to_chat(207, 'position_manager: %s command not found.':format(cmd)) - windower.send_command('pm help') - end + end + + windower.add_to_chat(207, 'position_manager: Commands:') + windower.add_to_chat(207, ' //pm set [name]') + windower.add_to_chat(207, ' //pm set delay [name]') + windower.add_to_chat(207, 'position_manager: See the readme for details.') end config.register(settings, move) + windower.register_event('addon command', handle_commands) From a2c7ce910b97a8cf2121d33bbfa7897369e6435d Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 6 Sep 2020 02:43:33 +0100 Subject: [PATCH 0474/1002] Update README.md --- addons/position_manager/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/position_manager/README.md b/addons/position_manager/README.md index dcbfce28df..de6d19153a 100644 --- a/addons/position_manager/README.md +++ b/addons/position_manager/README.md @@ -1,6 +1,6 @@ # Position Manager -Set and save screen position per-character. +Set and save screen position per-character. Requires the WinControl addon. Command: `//pm set [name]` From 1a7c3ba772bcbac5987cb1d3da3fa2a76380d276 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 6 Sep 2020 12:32:41 +0100 Subject: [PATCH 0475/1002] Update position_manager.lua --- addons/position_manager/position_manager.lua | 24 ++++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/addons/position_manager/position_manager.lua b/addons/position_manager/position_manager.lua index 388952bda6..5a06701b59 100644 --- a/addons/position_manager/position_manager.lua +++ b/addons/position_manager/position_manager.lua @@ -26,7 +26,7 @@ _addon.name = 'position_manager' _addon.author = 'Lili' -_addon.version = '1.1' +_addon.version = '1.1.1' _addon.command = 'pm' if not windower.file_exists(windower.windower_path .. '\\plugins\\WinControl.dll') then @@ -55,13 +55,21 @@ function move(settings) windower.send_command('wincontrol move %s %s':format(settings.x, settings.y)) end +function show_help() + windower.add_to_chat(207, 'position_manager: Commands:') + windower.add_to_chat(207, ' //pm set [name]') + windower.add_to_chat(207, ' //pm set delay [name]') + windower.add_to_chat(207, 'position_manager: See the readme for details.') +end + function handle_commands(cmd, ...) - cmd = cmd:lower() + cmd = cmd or cmd:lower() if cmd == 'r' then windower.send_command('lua r position_manager') return elseif cmd == 'set' then + local arg = {...} local name = arg[3] if name ~= nil and type(name) ~= 'string' then windower.add_to_chat(207, 'position_manager: ERROR - invalid name provided.') @@ -80,7 +88,7 @@ function handle_commands(cmd, ...) windower.add_to_chat(207, 'position_manager: Delay set to %s for %s.':format(settings.delay, name)) else windower.add_to_chat(207, 'position_manager: ERROR - invalid delay provided.') - windower.send_command('pm help') + show_help() return end elseif tonumber(arg[1]) and tonumber(arg[2]) then @@ -96,10 +104,10 @@ function handle_commands(cmd, ...) move(settings) end end - windower.add_to_chat(207, 'position_manager: Position set to %s,%s for %s.':format(settings.x, settings.y, name)) + windower.add_to_chat(207, 'position_manager: Position set to %s, %s for %s.':format(settings.x, settings.y, name)) else windower.add_to_chat(207, 'position_manager: ERROR - invalid position provided.') - windower.send_command('pm help') + show_help() return end end @@ -108,11 +116,7 @@ function handle_commands(cmd, ...) elseif cmd ~= 'help' then windower.add_to_chat(207, 'position_manager: %s command not found.':format(cmd)) end - - windower.add_to_chat(207, 'position_manager: Commands:') - windower.add_to_chat(207, ' //pm set [name]') - windower.add_to_chat(207, ' //pm set delay [name]') - windower.add_to_chat(207, 'position_manager: See the readme for details.') + show_help() end config.register(settings, move) From 7d24e519bed03cd8e31f856df2a6adc81813a954 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 6 Sep 2020 12:39:11 +0100 Subject: [PATCH 0476/1002] Update position_manager.lua --- addons/position_manager/position_manager.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/addons/position_manager/position_manager.lua b/addons/position_manager/position_manager.lua index 5a06701b59..fde82695fa 100644 --- a/addons/position_manager/position_manager.lua +++ b/addons/position_manager/position_manager.lua @@ -73,7 +73,7 @@ function handle_commands(cmd, ...) local name = arg[3] if name ~= nil and type(name) ~= 'string' then windower.add_to_chat(207, 'position_manager: ERROR - invalid name provided.') - windower.send_command('pm help') + show_help() return elseif not name then name = windower.ffxi.get_player().name @@ -91,7 +91,7 @@ function handle_commands(cmd, ...) show_help() return end - elseif tonumber(arg[1]) and tonumber(arg[2]) then + elseif arg[1] and arg[2] then settings.x = tonumber(arg[1]) settings.y = tonumber(arg[2]) @@ -110,6 +110,10 @@ function handle_commands(cmd, ...) show_help() return end + else + windower.add_to_chat(207, 'position_manager: ERROR - invalid arguments provided.') + show_help() + return end -- TODO: possibly add IPC return From 37be7ab965dbaf38a2aeb2dba31700eb4b36aef7 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 6 Sep 2020 12:50:45 +0100 Subject: [PATCH 0477/1002] Trim trailing spaces. --- addons/position_manager/position_manager.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/position_manager/position_manager.lua b/addons/position_manager/position_manager.lua index fde82695fa..8671aaad42 100644 --- a/addons/position_manager/position_manager.lua +++ b/addons/position_manager/position_manager.lua @@ -94,16 +94,16 @@ function handle_commands(cmd, ...) elseif arg[1] and arg[2] then settings.x = tonumber(arg[1]) settings.y = tonumber(arg[2]) - + if settings.x and settings.y then config.save(settings, name) - + if windower.ffxi.get_info().logged_in then player_name = windower.ffxi.get_player().name if name:lower() == player_name:lower() then move(settings) end - end + end windower.add_to_chat(207, 'position_manager: Position set to %s, %s for %s.':format(settings.x, settings.y, name)) else windower.add_to_chat(207, 'position_manager: ERROR - invalid position provided.') @@ -119,7 +119,7 @@ function handle_commands(cmd, ...) return elseif cmd ~= 'help' then windower.add_to_chat(207, 'position_manager: %s command not found.':format(cmd)) - end + end show_help() end From 60f3e5b14026818e9fe0212569f0be17ca107ea0 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 6 Sep 2020 12:52:38 +0100 Subject: [PATCH 0478/1002] Update README.md --- addons/position_manager/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/position_manager/README.md b/addons/position_manager/README.md index de6d19153a..53c3637aee 100644 --- a/addons/position_manager/README.md +++ b/addons/position_manager/README.md @@ -26,7 +26,7 @@ Will set the default positioning for all characters to X: 0 and Y: 60 (the heigh Will set the default position for the character called "Yourname" to X: 1920 and Y: 0. This will make the character appear on the secondary screen that is to the right of the main screen - useful for multi-screen setups. -`//pm set delay 1 all` +`//pm set delay 1 all` `//pm set Yourmain 0 40` `//pm set Youralt 800 40` Will set delay to 1 for all characters, then set the position of your main to X: 0, Y: 40, and your alt to X: 800, Y: 40. From 56459805e9e6f785c5fe10f978c9dd0729f2a3ac Mon Sep 17 00:00:00 2001 From: GlarinAsura <65004070+GlarinAsura@users.noreply.github.com> Date: Sun, 6 Sep 2020 11:22:52 -0700 Subject: [PATCH 0479/1002] Made requested code and styling changes. Fixed incorrect text in disclaimer. Made indentation uniform. Switched all string literals to use single qoutes. Made suggested help command change. --- addons/NyzulHelper/NyzulHelper.lua | 351 +++++++++++++++-------------- 1 file changed, 184 insertions(+), 167 deletions(-) diff --git a/addons/NyzulHelper/NyzulHelper.lua b/addons/NyzulHelper/NyzulHelper.lua index e21e62440c..b39e2353fe 100644 --- a/addons/NyzulHelper/NyzulHelper.lua +++ b/addons/NyzulHelper/NyzulHelper.lua @@ -1,5 +1,5 @@ --[[ -Copyright (c) 2020, Glarin of Asura +Copyright © 2020, Glarin of Asura All rights reserved. Redistribution and use in source and binary forms, with or without @@ -10,7 +10,7 @@ modification, are permitted provided that the following conditions are met: * 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 PartyMaster nor the + * Neither the name of NyzulHelper nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. @@ -46,10 +46,10 @@ defaults.interval = .1 settings = config.load(defaults) box = texts.new('${current_string}', settings) -pending_color = "\\cs(255,250,120)" -warning_color = "\\cs(255,165,0)" -good_color = "\\cs(0,255,0)" -bad_color = "\\cs(255,0,0)" +pending_color = '\\cs(255,250,120)' +warning_color = '\\cs(255,165,0)' +good_color = '\\cs(0,255,0)' +bad_color = '\\cs(255,0,0)' frame_time = 0 zone_timer = 0 @@ -70,41 +70,47 @@ potential_tokens = 0 -- Handle addon args windower.register_event('addon command', function(input, ...) - local cmd = string.lower(input) - local args = {...} - - if cmd == 'reset' then - reset() - elseif cmd == 'show' then - box:show() - elseif cmd == 'hide' then - box:hide() - elseif cmd == 'reload' then - windower.send_command('lua reload nyzulhelper') - else - log(cmd..' command unknown.') + local cmd = input and input:lower() or 'help' + local args = {...} + + if cmd == 'reset' then + reset() + elseif cmd == 'show' then + box:show() + elseif cmd == 'hide' then + box:hide() + elseif cmd == 'reload' then + windower.send_command('lua reload nyzulhelper') + elseif cmd == 'help' then + windower.add_to_chat(167, 'Commands:') + windower.add_to_chat(167, ' nyzulhelper reset') + windower.add_to_chat(167, ' nyzulhelper show') + windower.add_to_chat(167, ' nyzulhelper hide') + windower.add_to_chat(167, ' nyzulhelper reload') + else + log(cmd..' command unknown.') end - + end) -- Event Handlers windower.register_event('load', function() - - local info = windower.ffxi.get_info() - if info.logged_in and info.zone == 77 then - box:show() - end - + + local info = windower.ffxi.get_info() + if info.logged_in and info.zone == 77 then + box:show() + end + end) windower.register_event('prerender', function() local curr = os.clock() if curr > frame_time + settings.interval then - if end_time ~= nil and zone_timer >= 1 and zone_timer ~= (end_time - os.time()) then - zone_timer = end_time - os.time() - end - + if end_time ~= nil and zone_timer >= 1 and zone_timer ~= (end_time - os.time()) then + zone_timer = end_time - os.time() + end + frame_time = curr update_box() end @@ -113,194 +119,205 @@ end) windower.register_event('zone change',function(new, old) - box:hide() - - if new == 72 and old == 77 then - zone_timer = 0 - has_armband = false - else - reset() - end - - if new == 77 then - box:show() - party_size = windower.ffxi.get_party_info().party1_count - end - + box:hide() + + if new == 72 and old == 77 then + zone_timer = 0 + has_armband = false + else + reset() + end + + if new == 77 then + box:show() + party_size = windower.ffxi.get_party_info().party1_count + end + end) windower.register_event('incoming chunk', function(id, data, modified, injected, blocked) if id == 0x55 and windower.ffxi.get_info().zone == 72 and has_value(windower.ffxi.get_key_items(), 797) then - has_armband = true + has_armband = true end - + end) windower.register_event('incoming text', function(original, modified, mode, _, blocked) - local info = windower.ffxi.get_info() + local info = windower.ffxi.get_info() if not info.logged_in or info.zone ~= 77 or blocked or original == '' then return end - if mode == 123 then - - if string.find(original, "Security field malfunction") then - restriction = string.strip_format(original) - restriction_failed = bad_color - update_box() - elseif string.find(original, "Time limit has been reduced") then - set_timer(zone_timer - tonumber(original:match("%d+")) * 60) - elseif string.find(original, "Potential token reward reduced") then - floor_penalities = floor_penalities + 1 - end - - elseif (mode == 146 or mode == 148) and string.find(original, "(Earth time)") then - - local multiplier = 1 - if string.find(original, "minute") then multiplier = 60 end - - set_timer(tonumber(original:match("%d+")) * multiplier) - - elseif mode == 146 then - - if string.find(original,"Floor %d+ objective complete. Rune of Transfer activated.") then - completed = completed + 1 - floor_clear = good_color - restriction = '' - restriction_failed = warning_color - calculate_tokens() - update_box() - end - - elseif mode == 148 then - - if string.find(original,"Objective:") then - if string.find(original,"Commencing") then - objective = "Complete on-site objectives" - else - objective = string.strip_format(original:sub(11)) - end - floor_clear = pending_color - elseif string.find(original, "archaic") then - restriction = string.strip_format(original) - elseif string.find(original,"Transfer complete. Welcome to Floor %d+.") then - current_floor = tonumber(original:match("%d+")) - resync_values() - end - - end - + if mode == 123 then + + if string.find(original, 'Security field malfunction') then + restriction = string.strip_format(original) + restriction_failed = bad_color + update_box() + elseif string.find(original, 'Time limit has been reduced') then + set_timer(zone_timer - tonumber(original:match('%d+')) * 60) + elseif string.find(original, 'Potential token reward reduced') then + floor_penalities = floor_penalities + 1 + end + + elseif (mode == 146 or mode == 148) and string.find(original, '(Earth time)') then + + local multiplier = 1 + if string.find(original, 'minute') then multiplier = 60 end + + set_timer(tonumber(original:match('%d+')) * multiplier) + + elseif mode == 146 then + + if string.find(original,'Floor %d+ objective complete. Rune of Transfer activated.') then + completed = completed + 1 + floor_clear = good_color + restriction = '' + restriction_failed = warning_color + calculate_tokens() + update_box() + end + + elseif mode == 148 then + + if string.find(original,'Objective:') then + if string.find(original,'Commencing') then + objective = 'Complete on-site objectives' + else + objective = string.strip_format(original:sub(11)) + end + floor_clear = pending_color + elseif string.find(original, 'archaic') then + restriction = string.strip_format(original) + elseif string.find(original,'Transfer complete. Welcome to Floor %d+.') then + current_floor = tonumber(original:match('%d+')) + resync_values() + end + + end + end) function reset() - zone_timer = 0 - end_time = nil - objective = '' - floor_clear = pending_color - restriction = '' - restriction_failed = warning_color - starting_floor = 0 - current_floor = 0 - completed = 0 - floor_penalities = 0 - potential_tokens = 0 + zone_timer = 0 + end_time = nil + objective = '' + floor_clear = pending_color + restriction = '' + restriction_failed = warning_color + starting_floor = 0 + current_floor = 0 + completed = 0 + floor_penalities = 0 + potential_tokens = 0 end function has_value(list, value) - if list ~= nil and value ~= nil then - for _, v in pairs(list) do - if v == value then - return true - end - end - end + if list ~= nil and value ~= nil then + for _, v in pairs(list) do + if v == value then + return true + end + end + end - return false + return false end function set_timer(remaining) - zone_timer = remaining - end_time = os.time() + zone_timer - + zone_timer = remaining + end_time = os.time() + zone_timer + end function get_relative_floor() - if current_floor < starting_floor then - return current_floor + 100 - end - - return current_floor + if current_floor < starting_floor then + return current_floor + 100 + end + + return current_floor end function get_token_rate() - - local rate = 1 - if has_armband then rate = rate + .1 end - if party_size > 3 then rate = rate - ((party_size - 3 ) * .1) end - - return rate - + + local rate = 1 + if has_armband then + rate = rate + .1 + end + + if party_size > 3 then + rate = rate - ((party_size - 3 ) * .1) + end + + return rate + end function resync_values() - if starting_floor == 0 then - starting_floor = current_floor - if zone_timer == 0 then set_timer(1800) end - end - - local relative_floor = get_relative_floor() - if (relative_floor - starting_floor) > completed then - completed = relative_floor - starting_floor - end - - floor_penalities = 0 + if starting_floor == 0 then + starting_floor = current_floor + if zone_timer == 0 then + set_timer(1800) + end + end + + local relative_floor = get_relative_floor() + if (relative_floor - starting_floor) > completed then + completed = relative_floor - starting_floor + end + + floor_penalities = 0 end function get_token_penalty(rate) - return math.round(117 * rate) * floor_penalities + return math.round(117 * rate) * floor_penalities end function calculate_tokens() - - local relative_floor = get_relative_floor() - local rate = get_token_rate() - - local floor_bonus = 0 - if relative_floor > 1 then floor_bonus = (10 * math.floor((relative_floor - 1) / 5)) end - - potential_tokens = potential_tokens + ((200 + floor_bonus) * rate) - get_token_penalty(rate) - + + local relative_floor = get_relative_floor() + local rate = get_token_rate() + + local floor_bonus = 0 + if relative_floor > 1 then + floor_bonus = (10 * math.floor((relative_floor - 1) / 5)) + end + + potential_tokens = potential_tokens + ((200 + floor_bonus) * rate) - get_token_penalty(rate) + end function update_box() - local timer_color = '' - if zone_timer < 60 then timer_color = bad_color end - - local lines = L{} - lines:append(' Current Floor: '..current_floor) - lines:append('\n Time Remaining: '..timer_color..os.date('%M:%S', zone_timer).."\\cr ") - lines:append('\n Objective: '..floor_clear..objective.."\\cr ") - if restriction ~= '' then - lines:append(' Restriction: '..restriction_failed..restriction.."\\cr ") - end - lines:append('\n Floors Completed: '..completed) - lines:append(' Reward Rate: %d%%':format(get_token_rate() * 100)) - lines:append(' Potential Tokens: '..potential_tokens) - - box.current_string = lines:concat('\n') - -end \ No newline at end of file + local timer_color = '' + if zone_timer < 60 then + timer_color = bad_color + end + + local lines = L{} + lines:append(' Current Floor: '..current_floor) + lines:append('\n Time Remaining: '..timer_color..os.date('%M:%S', zone_timer)..'\\cr ') + lines:append('\n Objective: '..floor_clear..objective..'\\cr ') + if restriction ~= '' then + lines:append(' Restriction: '..restriction_failed..restriction..'\\cr ') + end + lines:append('\n Floors Completed: '..completed) + lines:append(' Reward Rate: %d%%':format(get_token_rate() * 100)) + lines:append(' Potential Tokens: '..potential_tokens) + + box.current_string = lines:concat('\n') + +end From 8a874e5fdea14d9a41bd1143c2a1d6846e3a1d79 Mon Sep 17 00:00:00 2001 From: GlarinAsura <65004070+GlarinAsura@users.noreply.github.com> Date: Sun, 6 Sep 2020 11:31:00 -0700 Subject: [PATCH 0480/1002] Added enty to addons.xml --- addons/addons.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/addons/addons.xml b/addons/addons.xml index 8fb2a71ad6..45a72c7519 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -391,6 +391,13 @@ https://discord.gg/b275nMv https://github.com/trv6/Lua/issues + + NyzulHelper + Glarin of Asura + Tracks and displays the Current Floor, Time Remaining, Objective, Floors Completed, Reward Rate, and Potenial Tokens. + https://github.com/Windower/Lua/issues + https://github.com/GlarinAsura/Lua/issues + obiaway Automatically collect and remove elemental obi based on day/weather/storm conditions. From 8c08b8d439bb9de33ee1ab59931149d78bc3864a Mon Sep 17 00:00:00 2001 From: GlarinAsura <65004070+GlarinAsura@users.noreply.github.com> Date: Sun, 6 Sep 2020 11:57:24 -0700 Subject: [PATCH 0481/1002] Fixed incorrect links, --- addons/addons.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/addons.xml b/addons/addons.xml index 45a72c7519..e28a2d6b5a 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -395,8 +395,8 @@ NyzulHelper Glarin of Asura Tracks and displays the Current Floor, Time Remaining, Objective, Floors Completed, Reward Rate, and Potenial Tokens. - https://github.com/Windower/Lua/issues - https://github.com/GlarinAsura/Lua/issues + https://github.com/GlarinAsura/Lua/issues + https://discord.gg/b275nMv obiaway From 534f9a517c8c8da99a7eab56ceece906be2272b8 Mon Sep 17 00:00:00 2001 From: Chris Fein <56209868+Chris-Fein@users.noreply.github.com> Date: Mon, 7 Sep 2020 05:35:19 -0500 Subject: [PATCH 0482/1002] Updated fIelds.lua --- addons/libs/packets/fields.lua | 51 ++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 8ca0306b05..26e67a2857 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -359,6 +359,7 @@ enums['action'] = { [0x0F] = 'Switch target', [0x10] = 'Ranged attack', [0x12] = 'Dismount Chocobo', + [0x13] = 'Tractor Dialogue', [0x14] = 'Zoning/Appear', -- I think, the resource for this is ambiguous. [0x19] = 'Monsterskill', [0x1A] = 'Mount', @@ -924,7 +925,7 @@ fields.outgoing[0x0C0] = L{ -- /makelinkshell fields.outgoing[0x0C3] = L{ {ctype='unsigned char', label='_unknown1'}, -- 04 - {ctype='unsigned char', label='Linkshell Numbger'}, -- 05 + {ctype='unsigned char', label='Linkshell Number'}, -- 05 {ctype='data[2]', label='_junk1'} -- 05 } @@ -2578,6 +2579,28 @@ fields.incoming[0x051] = L{ {ctype='unsigned short', label='_unknown1'}, -- 16 May varying meaningfully, but it's unclear } +enums[0x052] = { + [0x00] = 'Standard', + [0x01] = 'Event', + [0x02] = 'Event Skipped', + [0x03] = 'String Event', + [0x04] = 'Fishing', +} + +func.incoming[0x052] = {} +func.incoming[0x052].base = L{ + {ctype='unsigned char', label='Type', fn=e+{0x052}}, -- 04 +} + +func.incoming[0x052][0x02] = L{ + {ctype='unsigned short', label='Menu ID'}, -- 05 +} + +-- NPC Release +fields.incoming[0x052] = function(data, type) + return func.incoming[0x052].base + (func.incoming[0x052][type or data:byte(5)] or L{}) +end + -- Logout Time -- This packet is likely used for an entire class of system messages, -- but the only one commonly encountered is the logout counter. @@ -2640,7 +2663,7 @@ fields.incoming[0x056] = function (data, type) end func.incoming[0x056].type = L{ - {ctype='int', label='Type', fn=e+{'quest_mission_log'}} -- 24 + {ctype='short', label='Type', fn=e+{'quest_mission_log'}} -- 24 } func.incoming[0x056][0x0080] = L{ @@ -2713,7 +2736,7 @@ fields.incoming[0x05A] = L{ {ctype='unsigned short', label='Player Index', fn=index}, -- 0C {ctype='unsigned short', label='Target Index', fn=index}, -- 0E {ctype='unsigned short', label='Emote', fn=emote}, -- 10 - {ctype='unsigned short', label='_unknown1', const=2}, -- 12 + {ctype='unsigned short', label='_unknown1'}, -- 12 {ctype='unsigned short', label='_unknown2'}, -- 14 {ctype='unsigned char', label='Type'}, -- 16 2 for motion, 0 otherwise {ctype='unsigned char', label='_unknown3'}, -- 17 @@ -3043,15 +3066,21 @@ fields.incoming[0x068] = L{ {ctype='char*', label='Pet Name'}, -- 18 } +types.synth_skills = L{ + {ctype='bit[6]', label='Skill'}, -- 1A - 1D:0 + {ctype='boolbit', label='Skillup Allowed'}, -- 1A - 1D:6 + {ctype='boolbit', label='Desynth'}, -- 1A - 1D:7 +} + -- Self Synth Result -fields.incoming[0x06F] = L{ +fields.incoming[0x06F] = L{ {ctype='unsigned char', label='Result', fn=e+{'synth'}}, -- 04 {ctype='signed char', label='Quality'}, -- 05 {ctype='unsigned char', label='Count'}, -- 06 Even set for fail (set as the NQ amount in that case) {ctype='unsigned char', label='_junk1'}, -- 07 {ctype='unsigned short', label='Item', fn=item}, -- 08 {ctype='unsigned short[8]', label='Lost Item', fn=item}, -- 0A - {ctype='unsigned char[4]', label='Skill', fn=skill}, -- 1A + {ref=types.synth_skills, count=4}, {ctype='unsigned char[4]', label='Skillup', fn=div+{10}}, -- 1E {ctype='unsigned short', label='Crystal', fn=item}, -- 22 } @@ -3280,6 +3309,7 @@ func.incoming[0x0C9][0x01] = L{ {ctype='unsigned char', label='Main Job', fn=job}, -- 12 {ctype='unsigned char', label='Sub Job', fn=job}, -- 13 {ctype='data[15]', label='Linkshell', enc=ls_enc}, -- 14 6-bit packed + {ctype='unsigned char', label='_padding1'}, -- 23 {ctype='unsigned char', label='Main Job Level'}, -- 24 {ctype='unsigned char', label='Sub Job Level'}, -- 25 {ctype='data[42]', label='_unknown5'}, -- 26 At least the first two bytes and the last twelve bytes are junk, possibly more @@ -3406,7 +3436,7 @@ fields.incoming[0x0E0] = L{ -- Party Member List fields.incoming[0x0E1] = L{ {ctype='unsigned short', label='Party ID'}, -- 04 For whatever reason, this is always valid ASCII in my captured packets. - {ctype='unsigned short', label='_unknown1', const=0x0080}, -- 06 Likely contains information about the current chat mode and vote count + {ctype='unsigned short', label='_unknown1', const=0x8000}, -- 06 Likely contains information about the current chat mode and vote count } -- Char Info @@ -3462,12 +3492,17 @@ fields.incoming[0x0F6] = L{ {ctype='unsigned int', label='Type', fn=e+{'ws mark'}}, -- 04 } +enums['reraise'] = { + [0x01] = 'Raise dialogue', + [0x02] = 'Tractor dialogue', +} + -- Reraise Activation fields.incoming[0x0F9] = L{ {ctype='unsigned int', label='ID', fn=id}, -- 04 {ctype='unsigned short', label='Index', fn=index}, -- 08 - {ctype='unsigned char', label='_unknown1'}, -- 0A - {ctype='unsigned char', label='_unknown2'}, -- 0B + {ctype='unsigned char', label='Category', fn=e+{'reraise'}}, -- 0A + {ctype='unsigned char', label='_unknown1'}, -- 0B } -- Furniture Interaction From 3cd29847e4d78be1968423aa77c81ba12737efd5 Mon Sep 17 00:00:00 2001 From: Chris Fein <56209868+Chris-Fein@users.noreply.github.com> Date: Mon, 7 Sep 2020 05:48:00 -0500 Subject: [PATCH 0483/1002] Updated fields.lua --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 26e67a2857..689573f0d7 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -3093,7 +3093,7 @@ fields.incoming[0x070] = L{ {ctype='unsigned char', label='_junk1'}, -- 07 {ctype='unsigned short', label='Item', fn=item}, -- 08 {ctype='unsigned short[8]', label='Lost Item', fn=item}, -- 0A - {ctype='unsigned char[4]', label='Skill', fn=skill}, -- 1A Unsure about this + {ref=types.synth_skills, count=4}, {ctype='char*', label='Player Name'}, -- 1E Name of the player } From ffe14ba353ee89caf00f7b3872f55c3bae41e02f Mon Sep 17 00:00:00 2001 From: Chris Fein <56209868+Chris-Fein@users.noreply.github.com> Date: Mon, 7 Sep 2020 05:53:45 -0500 Subject: [PATCH 0484/1002] Updated fields.lua --- addons/libs/packets/fields.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 689573f0d7..d1c6530fc9 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2736,7 +2736,7 @@ fields.incoming[0x05A] = L{ {ctype='unsigned short', label='Player Index', fn=index}, -- 0C {ctype='unsigned short', label='Target Index', fn=index}, -- 0E {ctype='unsigned short', label='Emote', fn=emote}, -- 10 - {ctype='unsigned short', label='_unknown1'}, -- 12 + {ctype='unsigned short', label='_unknown1', const=2}, -- 12 {ctype='unsigned short', label='_unknown2'}, -- 14 {ctype='unsigned char', label='Type'}, -- 16 2 for motion, 0 otherwise {ctype='unsigned char', label='_unknown3'}, -- 17 @@ -3073,7 +3073,7 @@ types.synth_skills = L{ } -- Self Synth Result -fields.incoming[0x06F] = L{ +fields.incoming[0x06F] = L{ {ctype='unsigned char', label='Result', fn=e+{'synth'}}, -- 04 {ctype='signed char', label='Quality'}, -- 05 {ctype='unsigned char', label='Count'}, -- 06 Even set for fail (set as the NQ amount in that case) @@ -3436,7 +3436,7 @@ fields.incoming[0x0E0] = L{ -- Party Member List fields.incoming[0x0E1] = L{ {ctype='unsigned short', label='Party ID'}, -- 04 For whatever reason, this is always valid ASCII in my captured packets. - {ctype='unsigned short', label='_unknown1', const=0x8000}, -- 06 Likely contains information about the current chat mode and vote count + {ctype='unsigned short', label='_unknown1', const=0x0080}, -- 06 Likely contains information about the current chat mode and vote count } -- Char Info From cdc527a97b635c6531b14a57d1c2829f34a46deb Mon Sep 17 00:00:00 2001 From: yyoshisaur Date: Wed, 9 Sep 2020 01:09:18 +0900 Subject: [PATCH 0485/1002] fix calling aftercast() when execute 'Double-up' in JP environment --- addons/GearSwap/helper_functions.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/GearSwap/helper_functions.lua b/addons/GearSwap/helper_functions.lua index 88de35e8c5..d15bae3301 100644 --- a/addons/GearSwap/helper_functions.lua +++ b/addons/GearSwap/helper_functions.lua @@ -852,7 +852,7 @@ function cmd_reg:find_by_spell(value) for i,v in pairs(self) do if type(v) == 'table' and v.spell and v.spell.prefix == value.prefix and v.spell.name == value.name then potential_entries[i] = v.timestamp or 0 - elseif type(v) == 'table' and v.spell and v.spell.name == 'Double-Up' and value.type == 'CorsairRoll' then + elseif type(v) == 'table' and v.spell and v.spell.english == 'Double-Up' and value.type == 'CorsairRoll' then -- Double Up ability uses will return action packets that match Corsair Rolls rather than Double Up potential_entries[i] = v.timestamp or 0 end From d46f97821c225123e67882e47d58e225c66bbd22 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Thu, 10 Sep 2020 13:32:58 -0600 Subject: [PATCH 0486/1002] Incoming Chat fix Square removed one byte from end of character name (max character name length is 15 anyway so, not sure why it was ever 16, but there you go) --- addons/libs/packets/fields.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 2c0e66e6d0..f5a34ab9e1 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1445,8 +1445,8 @@ fields.incoming[0x017] = L{ {ctype='unsigned char', label='Mode', fn=chat}, -- 04 {ctype='bool', label='GM'}, -- 05 {ctype='unsigned short', label='Zone', fn=zone}, -- 06 Set only for Yell - {ctype='char[0x10]', label='Sender Name'}, -- 08 - {ctype='char*', label='Message'}, -- 18 Max of 150 characters + {ctype='char[0xF]', label='Sender Name'}, -- 08 + {ctype='char*', label='Message'}, -- 17 Max of 150 characters } -- Job Info From b5ba45c4ba2787508c5eb4197edf53b14957f4a0 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Sat, 12 Sep 2020 21:52:07 +0200 Subject: [PATCH 0487/1002] [battlmod] Update new ambu message Updated for new battle message when the boss uses Imperfect Defense shell, this will require an update of resources before pushing to live. --- addons/battlemod/parse_action_packet.lua | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/addons/battlemod/parse_action_packet.lua b/addons/battlemod/parse_action_packet.lua index 7837addf92..c39e7f855d 100644 --- a/addons/battlemod/parse_action_packet.lua +++ b/addons/battlemod/parse_action_packet.lua @@ -222,6 +222,8 @@ function parse_action_packet(act) m.status=color_it('Vanish',color_arr['statuscol']) elseif m.message == 522 and simplify then targ = targ..' (stunned)' + elseif m.message == 1023 then + m.status = color_it('attacks and defenses enhanced',color_arr['statuscol']) 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. @@ -392,14 +394,14 @@ function simplify_message(msg_ID) local fields = fieldsearch(msg) if simplify and not T{23,64,133,139,140,204,210,211,212,213,214,350,442,516,531,557,565,582,674}: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 + 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,1023}: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 + T{129,152,161,162,163,165,229,384,453,603,652,798,1023}:contains(msg_ID) then fields.ability = true end @@ -408,7 +410,7 @@ function simplify_message(msg_ID) 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 + if T{129,152,153,160,161,162,163,164,165,166,167,168,229,244,652,1023}:contains(msg_ID) then fields.actor = true fields.target = true end From 3d6731eec348e5c030e2fe4da29f6e9421f1bc10 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Sat, 12 Sep 2020 15:20:20 -0600 Subject: [PATCH 0488/1002] Let's report errors Report file load error instead of erroneously saying "can't find the file". Also brought default "binds" file into the loop --- addons/Yush/Yush.lua | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/addons/Yush/Yush.lua b/addons/Yush/Yush.lua index a4329dd087..32cf38fd1b 100644 --- a/addons/Yush/Yush.lua +++ b/addons/Yush/Yush.lua @@ -1,5 +1,5 @@ _addon.author = 'Arcon' -_addon.version = '2.1.1.1' +_addon.version = '2.1.2.0' _addon.language = 'English' _addon.command = 'yush' @@ -138,29 +138,26 @@ end windower.register_event('load', 'login', 'job change', 'logout', function() local player = windower.ffxi.get_player() - local file, path + local file, path, filename, filepath, err local basepath = windower.addon_path .. 'data/' if player then - for filepath in L{ + for filepath_template in L{ {path = 'name_main_sub.lua', format = '%s\'s %s/%s'}, {path = 'name_main.lua', format = '%s\'s %s'}, {path = 'name.lua', format = '%s\'s'}, + {path = 'binds.lua', format = '"binds"'}, }:it() do - path = filepath.format:format(player.name, player.main_job, player.sub_job or '') - file = loadfile(basepath .. filepath.path:gsub('name', player.name):gsub('main', player.main_job):gsub('sub', player.sub_job or '')) - - if file then + path = filepath_template.format:format(player.name, player.main_job, player.sub_job or '') + filename = filepath_template.path:gsub('name', player.name):gsub('main', player.main_job):gsub('sub', player.sub_job or '') + filepath = basepath .. filename + if windower.file_exists(filepath) then + file, err = loadfile(filepath) break end end end - if not file then - path = 'binds.lua' - file = loadfile(basepath .. path) - end - - if file then + if file and not err then _innerG._names = {} _innerG._binds = {} binds = {} @@ -181,8 +178,11 @@ windower.register_event('load', 'login', 'job change', 'logout', function() reset() print('Yush: Loaded %s Lua file':format(path)) + elseif err then + print('\nYush: Error loading file: '..err:gsub('\\','/')) elseif player then print('Yush: No matching file found for %s (%s%s)':format(player.name, player.main_job, player.sub_job and '/' .. player.sub_job or '')) + end end) From 7cd1d7154f25bfbebe4f2ee0cb61d0dd74005238 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Mon, 14 Sep 2020 17:29:48 +0200 Subject: [PATCH 0489/1002] Libs/Packets: Added proper variable length string support --- addons/libs/packets.lua | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/addons/libs/packets.lua b/addons/libs/packets.lua index 4b61df1849..d717b13031 100644 --- a/addons/libs/packets.lua +++ b/addons/libs/packets.lua @@ -1,5 +1,5 @@ --[[ -A library to facilitate packet usage +A library to facilitate packet usage ]] _libs = _libs or {} @@ -164,6 +164,7 @@ parse = function(fields, data, index, max, lookup, depth) bits = sizes[type] * type_count field.ctype = '%s[%u]':format(type, type_count) + field.vlstring = type == 'char' count = max end @@ -264,6 +265,10 @@ local make_pack_string = function(field) return pack_ids[ctype] end + if field.vlstring then + return 'z' + end + local type_name, number = ctype:match(array_pattern) if type_name then number = tonumber(number) @@ -296,7 +301,7 @@ end -- If data is a string it parses an existing packet, otherwise it will create -- a new packet table for injection. In that case, data can ba an optional -- table containing values to initialize the packet to. --- +-- -- Example usage -- Injection: -- local packet = packets.new('outgoing', 0x050, { @@ -310,7 +315,7 @@ end -- packet['Inventory Index'] = 27 -- 27th item in the inventory -- packet['Equipment Slot'] = 15 -- 15th slot, left ring -- packets.inject(packet) --- +-- -- Parsing: -- windower.register_event('outgoing chunk', function(id, data) -- if id == 0x0B6 then -- outgoing /tell @@ -454,3 +459,4 @@ Redistribution and use in source and binary forms, with or without modification, 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 Windower 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. ]] + From b7bddecb246445e7fb88b43014ed9dab99521a10 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Mon, 14 Sep 2020 17:51:34 +0200 Subject: [PATCH 0490/1002] [translate] Update to use the packets lib Updated to use the packets lib and cleared some gearswap code that was left on the addon. --- addons/translate/translate.lua | 65 ++++++---------------------------- 1 file changed, 11 insertions(+), 54 deletions(-) diff --git a/addons/translate/translate.lua b/addons/translate/translate.lua index 22d9ed11fa..f036e92976 100644 --- a/addons/translate/translate.lua +++ b/addons/translate/translate.lua @@ -1,4 +1,4 @@ ---Copyright (c) 2014~2015, Byrthnoth +--Copyright (c) 2014~2020, Byrthnoth --All rights reserved. --Redistribution and use in source and binary forms, with or without @@ -25,7 +25,7 @@ --SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'Translate' -_addon.version = '0.150811' +_addon.version = '2.0.0.0' _addon.author = 'Byrth' _addon.commands = {'trans','translate'} @@ -33,6 +33,7 @@ _addon.commands = {'trans','translate'} language = 'english' trans_list = {} res = require 'resources' +packets = require('packets') require 'sets' require 'lists' require 'pack' @@ -196,26 +197,18 @@ trans_list['\.'] = nil windower.register_event('incoming chunk',function(id,orgi,modi,is_injected,is_blocked) if id == 0x17 and not is_injected and not is_blocked then - local out_text = modi:unpack('z',0x19) + local packet = packets.parse('incoming', modi) + local out_text = packet.Message out_text = translate_phrase(out_text) if not out_text then return end - if show_original then windower.add_to_chat(8,modi:sub(9,0x18):unpack('z',1)..'[Original]: '..modi:unpack('z',0x19)) end - while #out_text > 0 do - local boundary = get_boundary_length(out_text,150) - local len = math.ceil((boundary+1+24)/2) -- Make sure there is at least one nul after the string - local out_pack = string.char(0x17,len)..modi:sub(3,0x18)..out_text:sub(1,boundary) - - -- zero pad it - while #out_pack < len*2 do - out_pack = out_pack..string.char(0) - end - windower.packets.inject_incoming(0x17,out_pack) - out_text = out_text:sub(boundary+1) - end - return true + if show_original then windower.add_to_chat(8, '[Original]: '..packet.Message) end + + packet.Message = out_text + local rebuilt = packets.build(packet) + return rebuilt end end) @@ -351,42 +344,6 @@ windower.register_event('incoming text',function(org,mod,ocol,mcol,blk) end end) - -function print_set(set,title) - if not set then - if title then - windower.add_to_chat(123,'GearSwap: print_set error '..title..' set is nil.') - else - windower.add_to_chat(123,'GearSwap: print_set error, set is nil.') - end - return - end - if title then - windower.add_to_chat(1,'------------------------- '..tostring(title)..' -------------------------') - else - windower.add_to_chat(1,'----------------------------------------------------------------') - end - if #set == table.length(set) then - for i,v in ipairs(set) do - if type(v) == 'table' and v.name then - windower.add_to_chat(8,tostring(i)..' '..tostring(v)) - else - windower.add_to_chat(8,tostring(i)..' '..tostring(v)) - end - end - else - for i,v in pairs(set) do - if type(v) == 'table' and v.name then - windower.add_to_chat(8,tostring(i)..' '..tostring(v)) - else - windower.add_to_chat(8,tostring(i)..' '..tostring(v)) - end - end - end - windower.add_to_chat(1,'----------------------------------------------------------------') -end - - function unescape(str) return (str:gsub('%%([%%%%^%$%*%(%)%.%+%?%-%]%[])','%1')) end @@ -442,4 +399,4 @@ function sjis_gsub(str,pattern,rep) end end return ret_str -end \ No newline at end of file +end From 845a4e854bf43ca966eac490f345d4785c96b298 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Wed, 16 Sep 2020 15:10:38 +0200 Subject: [PATCH 0491/1002] [fields.lua] Wardrobes and Safe2 fixes fix for inventories that contains a space on their names. --- addons/libs/packets/fields.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index f5a34ab9e1..a5c8e1985e 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -193,8 +193,8 @@ local function inv(bag, val) if val == 0 or not res.bags[bag] then return '-' end - - local items = windower.ffxi.get_items()[res.bags[bag].english:lower()] + + local items = windower.ffxi.get_items(bag) if not items[val] then return '-' end From 32563d575bcc68b1e5cb3d216ebd6528e51a5be5 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Wed, 16 Sep 2020 16:33:21 +0200 Subject: [PATCH 0492/1002] Update fields.lua --- addons/libs/packets/fields.lua | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index a5c8e1985e..18a1698cb6 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -128,9 +128,7 @@ local function zone(val) end local function item(val) - return val ~= 0 and res.items[val] - and res.items[val].name - or '-' + return val ~= 0 and res.items[val] and res.items[val].name or '-' end local function server(val) @@ -193,13 +191,8 @@ local function inv(bag, val) if val == 0 or not res.bags[bag] then return '-' end - - local items = windower.ffxi.get_items(bag) - if not items[val] then - return '-' - end - return item(items[val].id) + return item(windower.ffxi.get_items(bag, val).id) end local function invp(index, val, data) From bdaabf732929a7cdb02a798cd6abb38006a64cb6 Mon Sep 17 00:00:00 2001 From: funkworkz Date: Wed, 16 Sep 2020 12:20:52 -0500 Subject: [PATCH 0493/1002] Update setbgm.lua Made this change so list command shows TVR songs. --- addons/setbgm/setbgm.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/setbgm/setbgm.lua b/addons/setbgm/setbgm.lua index f3e95b0966..ad7033706b 100644 --- a/addons/setbgm/setbgm.lua +++ b/addons/setbgm/setbgm.lua @@ -104,7 +104,7 @@ end function display_songs() windower.add_to_chat(207, 'Available songs:') - for id=40,900,5 do + for id=25,900,5 do local output = ' ' for i=0,4 do if songs[id+i] then From f5350f3175843351c0e18ff3fc174ce6d5c190b4 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Fri, 18 Sep 2020 19:02:31 -0400 Subject: [PATCH 0494/1002] Update packets.lua --- addons/libs/packets.lua | 6 ------ 1 file changed, 6 deletions(-) diff --git a/addons/libs/packets.lua b/addons/libs/packets.lua index d717b13031..f3ab5b096d 100644 --- a/addons/libs/packets.lua +++ b/addons/libs/packets.lua @@ -164,7 +164,6 @@ parse = function(fields, data, index, max, lookup, depth) bits = sizes[type] * type_count field.ctype = '%s[%u]':format(type, type_count) - field.vlstring = type == 'char' count = max end @@ -265,10 +264,6 @@ local make_pack_string = function(field) return pack_ids[ctype] end - if field.vlstring then - return 'z' - end - local type_name, number = ctype:match(array_pattern) if type_name then number = tonumber(number) @@ -459,4 +454,3 @@ Redistribution and use in source and binary forms, with or without modification, 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 Windower 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. ]] - From 64336a7d3e3634c2d899644828c32e0788686e16 Mon Sep 17 00:00:00 2001 From: Dean James Date: Sun, 20 Sep 2020 00:00:30 +0100 Subject: [PATCH 0495/1002] Upgrade EPT to 2.5.0. Added mini mode. Added collectables toggle. --- addons/EmpyPopTracker/EmpyPopTracker.lua | 52 +++++++++++++++------- addons/EmpyPopTracker/README.md | 8 ++++ addons/EmpyPopTracker/nms/README.md | 26 +++++------ addons/EmpyPopTracker/nms/alfard.lua | 4 +- addons/EmpyPopTracker/nms/apademak.lua | 4 +- addons/EmpyPopTracker/nms/azdaja.lua | 4 +- addons/EmpyPopTracker/nms/briareus.lua | 4 +- addons/EmpyPopTracker/nms/brulo.lua | 4 +- addons/EmpyPopTracker/nms/bukhis.lua | 4 +- addons/EmpyPopTracker/nms/carabosse.lua | 4 +- addons/EmpyPopTracker/nms/chloris.lua | 4 +- addons/EmpyPopTracker/nms/cirein-croin.lua | 4 +- addons/EmpyPopTracker/nms/dragua.lua | 4 +- addons/EmpyPopTracker/nms/glavoid.lua | 4 +- addons/EmpyPopTracker/nms/isgebind.lua | 4 +- addons/EmpyPopTracker/nms/itzpapalotl.lua | 4 +- addons/EmpyPopTracker/nms/kukulkan.lua | 4 +- addons/EmpyPopTracker/nms/maere.lua | 4 +- addons/EmpyPopTracker/nms/ogopogo.lua | 4 +- addons/EmpyPopTracker/nms/orthrus.lua | 4 +- addons/EmpyPopTracker/nms/sedna.lua | 4 +- addons/EmpyPopTracker/nms/sobek.lua | 4 +- addons/EmpyPopTracker/nms/ulhuadshi.lua | 4 +- 23 files changed, 98 insertions(+), 68 deletions(-) diff --git a/addons/EmpyPopTracker/EmpyPopTracker.lua b/addons/EmpyPopTracker/EmpyPopTracker.lua index 6faa40a8eb..a6ae2aa549 100644 --- a/addons/EmpyPopTracker/EmpyPopTracker.lua +++ b/addons/EmpyPopTracker/EmpyPopTracker.lua @@ -29,7 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'Empy Pop Tracker' _addon.author = 'Dean James (Xurion of Bismarck)' _addon.commands = { 'ept', 'empypoptracker' } -_addon.version = '2.4.0' +_addon.version = '2.5.0' config = require('config') res = require('resources') @@ -78,6 +78,8 @@ defaults.colors.bgall = {} defaults.colors.bgall.red = 0 defaults.colors.bgall.green = 75 defaults.colors.bgall.blue = 0 +defaults.collectables = true +defaults.expanded = true EmpyPopTracker.settings = config.load(defaults) EmpyPopTracker.text = require('texts').new(EmpyPopTracker.settings.text, EmpyPopTracker.settings) @@ -176,38 +178,44 @@ function generate_text(data, key_items, items, depth) pop_name = ucwords(resource.name) end - --separator line for each top-level mob - if depth == 1 then + if depth == 1 and EmpyPopTracker.settings.expanded then text = text .. '\n' end - local item_colour - if owns_pop then - item_colour = start_color('obtained') - else - item_colour = start_color('needed') - end - + local item_colour = start_color(owns_pop and 'obtained' or 'needed') local pool_notification = '' if in_pool_count > 0 then pool_notification = start_color('pool') .. ' [' .. in_pool_count .. ']' .. '\\cr' end - text = text .. '\n' .. get_indent(depth) .. pop.dropped_from.name .. '\n' .. get_indent(depth) .. ' >> ' .. item_colour .. item_identifier .. pop_name .. '\\cr' .. pool_notification + + local name_color = '' + local name_color_end = '' + if not EmpyPopTracker.settings.expanded and owns_pop then + name_color = item_colour + name_color_end = '\\cr' + end + + text = text .. '\n' .. get_indent(depth) .. name_color .. pop.dropped_from.name .. name_color_end + + if EmpyPopTracker.settings.expanded then + text = text .. '\n' .. get_indent(depth) .. ' >> ' .. item_colour .. item_identifier .. pop_name .. '\\cr' .. pool_notification + end + if pop.dropped_from.pops then text = text .. generate_text(pop.dropped_from, key_items, items, depth + 1) end end - if data.item then - local count = get_item_count(data.item, items) + if data.collectable and EmpyPopTracker.settings.collectables then + local count = get_item_count(data.collectable, items) local start = '' local finish = '' - if count >= data.item_target_count then + if count >= data.collectable_target_count then start = start_color('obtained') finish = '\\cr' end - text = text .. '\n\n' .. start .. res.items[data.item].name .. ': ' .. count .. '/' .. data.item_target_count .. finish + text = text .. '\n\n' .. start .. res.items[data.collectable].name .. ': ' .. count .. '/' .. data.collectable_target_count .. finish end return text @@ -291,6 +299,8 @@ commands.help = function() windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '//ept hide - hides the UI') windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '//ept show - shows the UI') windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '//ept list - lists all trackable NMs') + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '//ept mini - toggles mini/expanded mode') + windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '//ept collectables - toggles the collectable item') windower.add_to_chat(EmpyPopTracker.settings.add_to_chat_mode, '//ept help - displays this help') end @@ -308,6 +318,18 @@ commands.bg = function() windower.open_url(url) end +commands.collectables = function() + EmpyPopTracker.settings.collectables = not EmpyPopTracker.settings.collectables + EmpyPopTracker.settings:save() + EmpyPopTracker.update() +end + +commands.mini = function() + EmpyPopTracker.settings.expanded = not EmpyPopTracker.settings.expanded + EmpyPopTracker.settings:save() + EmpyPopTracker.update() +end + EmpyPopTracker.update = function() local key_items = windower.ffxi.get_key_items() local items = windower.ffxi.get_items() diff --git a/addons/EmpyPopTracker/README.md b/addons/EmpyPopTracker/README.md index 24684f744b..42a99a5b9d 100644 --- a/addons/EmpyPopTracker/README.md +++ b/addons/EmpyPopTracker/README.md @@ -46,6 +46,14 @@ For a full list of trackable NMs, see the nms directory or use the `list` comman `//ept show` +### Toggle Mini Mode + +`//ept mini` + +### Toggle Collectable Item Display + +`//ept collectables` + ### Display Help `//ept help` diff --git a/addons/EmpyPopTracker/nms/README.md b/addons/EmpyPopTracker/nms/README.md index 7833e7e3bd..38b7f51c90 100644 --- a/addons/EmpyPopTracker/nms/README.md +++ b/addons/EmpyPopTracker/nms/README.md @@ -2,23 +2,23 @@ The data structure for each trackable NM uses a series of nested NM entities. A standard NM entity contains the following data: -| Key | Type | Required? | Description | -| ------------------- | --------- | --------- | ------------------------------ | -| name | String | Required | Name of the NM | -| item | Number | Optional | The ID of the wanted item | -| item_target_count | Number | Optional | The target no. of wanted items | -| pops | Table | Optional | The pop information for the NM | -| pops{}.id | Number | Required | The ID of the item/key item | -| pops{}.type | String | Required | Either "key item" or "item" | -| pops{}.dropped_from | NM Entity | Required | A nested set of NM information | +| Key | Type | Required? | Description | +| ------------------------ | --------- | --------- | ----------------------------------- | +| name | String | Required | Name of the NM | +| collectable | Number | Optional | The ID of the collectable item | +| collectable_target_count | Number | Optional | The target no. of collectable items | +| pops | Table | Optional | The pop information for the NM | +| pops{}.id | Number | Required | The ID of the item/key item | +| pops{}.type | String | Required | Either "key item" or "item" | +| pops{}.dropped_from | NM Entity | Required | A nested set of NM information | A simple example of the above would be: ```lua { name = 'Azdaja', - item = 3292, --Azdaja's Horn - item_target_count = 75, + collectable = 3292, --Azdaja's Horn + collectable_target_count = 75, pops = { { id = 1531, --Vacant Bugard Eye type = 'key item', @@ -32,8 +32,8 @@ A larger example with multiple nested entities: ```lua { name = 'Bukhis', - item = 2966, --Bukhis's Wing - item_target_count = 50, + collectable = 2966, --Bukhis's Wing + collectable_target_count = 50, pops = { { id = 1508, --Ingrown Taurus Nail type = 'key item', diff --git a/addons/EmpyPopTracker/nms/alfard.lua b/addons/EmpyPopTracker/nms/alfard.lua index d1f50b404f..a88f6c9c3a 100644 --- a/addons/EmpyPopTracker/nms/alfard.lua +++ b/addons/EmpyPopTracker/nms/alfard.lua @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Alfard', - item = 3291, --Alfard's Fang - item_target_count = 75, + collectable = 3291, --Alfard's Fang + collectable_target_count = 75, pops = { { id = 1530, --Venomous hydra fang type = 'key item', diff --git a/addons/EmpyPopTracker/nms/apademak.lua b/addons/EmpyPopTracker/nms/apademak.lua index 51c4a6c397..924545d3d0 100644 --- a/addons/EmpyPopTracker/nms/apademak.lua +++ b/addons/EmpyPopTracker/nms/apademak.lua @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Apademak', - item = 3289, --Apademak Horn - item_target_count = 75, + collectable = 3289, --Apademak Horn + collectable_target_count = 75, pops = { { id = 1525, --Torn Khimaira Wing type = 'key item', diff --git a/addons/EmpyPopTracker/nms/azdaja.lua b/addons/EmpyPopTracker/nms/azdaja.lua index 03c72f35e7..774304f6fb 100644 --- a/addons/EmpyPopTracker/nms/azdaja.lua +++ b/addons/EmpyPopTracker/nms/azdaja.lua @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Azdaja', - item = 3292, --Azdaja's Horn - item_target_count = 75, + collectable = 3292, --Azdaja's Horn + collectable_target_count = 75, pops = { { id = 1531, --Vacant Bugard Eye type = 'key item', diff --git a/addons/EmpyPopTracker/nms/briareus.lua b/addons/EmpyPopTracker/nms/briareus.lua index 2cf8e93ced..a7c8f9be9a 100644 --- a/addons/EmpyPopTracker/nms/briareus.lua +++ b/addons/EmpyPopTracker/nms/briareus.lua @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Briareus', - item = 2929, --Helm of Briareus - item_target_count = 50, + collectable = 2929, --Helm of Briareus + collectable_target_count = 50, pops = { { id = 1482, --Dented Gigas Shield type = 'key item', diff --git a/addons/EmpyPopTracker/nms/brulo.lua b/addons/EmpyPopTracker/nms/brulo.lua index 668fad3922..35317fa460 100644 --- a/addons/EmpyPopTracker/nms/brulo.lua +++ b/addons/EmpyPopTracker/nms/brulo.lua @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Brulo', - item = 3294, --Colorless Soul - item_target_count = 75, + collectable = 3294, --Colorless Soul + collectable_target_count = 75, pops = { { id = 1652, --Emerald demilune abyssite type = 'key item', diff --git a/addons/EmpyPopTracker/nms/bukhis.lua b/addons/EmpyPopTracker/nms/bukhis.lua index f435901565..699b4c1781 100644 --- a/addons/EmpyPopTracker/nms/bukhis.lua +++ b/addons/EmpyPopTracker/nms/bukhis.lua @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Bukhis', - item = 2966, --Bukhis's Wing - item_target_count = 50, + collectable = 2966, --Bukhis's Wing + collectable_target_count = 50, pops = { { id = 1508, --Ingrown Taurus Nail type = 'key item', diff --git a/addons/EmpyPopTracker/nms/carabosse.lua b/addons/EmpyPopTracker/nms/carabosse.lua index d82d78d355..88bec48e48 100644 --- a/addons/EmpyPopTracker/nms/carabosse.lua +++ b/addons/EmpyPopTracker/nms/carabosse.lua @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Carabosse', - item = 2930, --Carabosse's Gem - item_target_count = 50, + collectable = 2930, --Carabosse's Gem + collectable_target_count = 50, pops = { { id = 1485, --Pellucid Fly Eye type = 'key item', diff --git a/addons/EmpyPopTracker/nms/chloris.lua b/addons/EmpyPopTracker/nms/chloris.lua index 1659220bd2..ba64fc70a4 100644 --- a/addons/EmpyPopTracker/nms/chloris.lua +++ b/addons/EmpyPopTracker/nms/chloris.lua @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Chloris', - item = 2928, --2Lf. Chloris Bud - item_target_count = 50, + collectable = 2928, --2Lf. Chloris Bud + collectable_target_count = 50, pops = { { id = 1470, --Gory Scorpion Claw type = 'key item', diff --git a/addons/EmpyPopTracker/nms/cirein-croin.lua b/addons/EmpyPopTracker/nms/cirein-croin.lua index e561612bc5..3f664e7de6 100644 --- a/addons/EmpyPopTracker/nms/cirein-croin.lua +++ b/addons/EmpyPopTracker/nms/cirein-croin.lua @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Cirein-croin', - item = 2965, --Cirein. Lantern - item_target_count = 50, + collectable = 2965, --Cirein. Lantern + collectable_target_count = 50, pops = { { id = 1504, --Glistening Orobon Liver type = 'key item', diff --git a/addons/EmpyPopTracker/nms/dragua.lua b/addons/EmpyPopTracker/nms/dragua.lua index f56742104b..0bb120c1d6 100644 --- a/addons/EmpyPopTracker/nms/dragua.lua +++ b/addons/EmpyPopTracker/nms/dragua.lua @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Dragua', - item = 3288, --Dragua's Scale - item_target_count = 75, + collectable = 3288, --Dragua's Scale + collectable_target_count = 75, pops = { { id = 1521, --Bloodied Dragon Ear type = 'key item', diff --git a/addons/EmpyPopTracker/nms/glavoid.lua b/addons/EmpyPopTracker/nms/glavoid.lua index b9443c76e6..cb604bda3f 100644 --- a/addons/EmpyPopTracker/nms/glavoid.lua +++ b/addons/EmpyPopTracker/nms/glavoid.lua @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Glavoid', - item = 2927, --Glavoid Shell - item_target_count = 50, + collectable = 2927, --Glavoid Shell + collectable_target_count = 50, pops = { { id = 1473, --Sodden Sandworm Husk type = 'key item', diff --git a/addons/EmpyPopTracker/nms/isgebind.lua b/addons/EmpyPopTracker/nms/isgebind.lua index 7b3125fda9..76f5aa7eee 100644 --- a/addons/EmpyPopTracker/nms/isgebind.lua +++ b/addons/EmpyPopTracker/nms/isgebind.lua @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Isgebind', - item = 3290, --Isgebind's Heart - item_target_count = 75, + collectable = 3290, --Isgebind's Heart + collectable_target_count = 75, pops = { { id = 1526, --Begrimed Dragon Hide type = 'key item', diff --git a/addons/EmpyPopTracker/nms/itzpapalotl.lua b/addons/EmpyPopTracker/nms/itzpapalotl.lua index a95e1cb246..47d078a140 100644 --- a/addons/EmpyPopTracker/nms/itzpapalotl.lua +++ b/addons/EmpyPopTracker/nms/itzpapalotl.lua @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Itzpapalotl', - item = 2962, --Itzpapa. Scale - item_target_count = 50, + collectable = 2962, --Itzpapa. Scale + collectable_target_count = 50, pops = { { id = 1488, --Venomous Wamoura Feeler type = 'key item', diff --git a/addons/EmpyPopTracker/nms/kukulkan.lua b/addons/EmpyPopTracker/nms/kukulkan.lua index 4ec79246bd..4b1e896aed 100644 --- a/addons/EmpyPopTracker/nms/kukulkan.lua +++ b/addons/EmpyPopTracker/nms/kukulkan.lua @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Kukulkan', - item = 2932, --Kukulkan's Fang - item_target_count = 50, + collectable = 2932, --Kukulkan's Fang + collectable_target_count = 50, pops = { { id = 1466, --Mucid Ahriman Eyeball type = 'key item', diff --git a/addons/EmpyPopTracker/nms/maere.lua b/addons/EmpyPopTracker/nms/maere.lua index eeeb9086e0..3250818f8b 100644 --- a/addons/EmpyPopTracker/nms/maere.lua +++ b/addons/EmpyPopTracker/nms/maere.lua @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Maere', - item = 3294, --Colorless Soul - item_target_count = 75, + collectable = 3294, --Colorless Soul + collectable_target_count = 75, pops = { { id = 1654, --Indigo demilune abyssite type = 'key item', diff --git a/addons/EmpyPopTracker/nms/ogopogo.lua b/addons/EmpyPopTracker/nms/ogopogo.lua index 07bae75968..d4ca13ad94 100644 --- a/addons/EmpyPopTracker/nms/ogopogo.lua +++ b/addons/EmpyPopTracker/nms/ogopogo.lua @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Ogopogo', - item = 3294, --Colorless Soul - item_target_count = 75, + collectable = 3294, --Colorless Soul + collectable_target_count = 75, pops = { { id = 1653, --Vermillion demilune abyssite type = 'key item', diff --git a/addons/EmpyPopTracker/nms/orthrus.lua b/addons/EmpyPopTracker/nms/orthrus.lua index d3af0165ae..59d13a8e13 100644 --- a/addons/EmpyPopTracker/nms/orthrus.lua +++ b/addons/EmpyPopTracker/nms/orthrus.lua @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Orthrus', - item = 3287, --Orthrus's Claw - item_target_count = 75, + collectable = 3287, --Orthrus's Claw + collectable_target_count = 75, pops = { { id = 1520, --Steaming cerberus tongue type = 'key item', diff --git a/addons/EmpyPopTracker/nms/sedna.lua b/addons/EmpyPopTracker/nms/sedna.lua index 8629925af0..c00d641d62 100644 --- a/addons/EmpyPopTracker/nms/sedna.lua +++ b/addons/EmpyPopTracker/nms/sedna.lua @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Sedna', - item = 2967, --Sedna's Tusk - item_target_count = 50, + collectable = 2967, --Sedna's Tusk + collectable_target_count = 50, pops = { { id = 1512, --Shimmering Pugil Scale type = 'key item', diff --git a/addons/EmpyPopTracker/nms/sobek.lua b/addons/EmpyPopTracker/nms/sobek.lua index 682fb3bef2..4aa9a80b11 100644 --- a/addons/EmpyPopTracker/nms/sobek.lua +++ b/addons/EmpyPopTracker/nms/sobek.lua @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Sobek', - item = 2964, --Sobek's Skin - item_target_count = 50, + collectable = 2964, --Sobek's Skin + collectable_target_count = 50, pops = { { id = 1500, --Molted Peiste Skin type = 'key item', diff --git a/addons/EmpyPopTracker/nms/ulhuadshi.lua b/addons/EmpyPopTracker/nms/ulhuadshi.lua index 8d6ab0a927..2245791d3d 100644 --- a/addons/EmpyPopTracker/nms/ulhuadshi.lua +++ b/addons/EmpyPopTracker/nms/ulhuadshi.lua @@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return { name = 'Ulhuadshi', - item = 2963, --Ulhuadshi's Fang - item_target_count = 50, + collectable = 2963, --Ulhuadshi's Fang + collectable_target_count = 50, pops = { { id = 1492, --Shriveled Hecteyes Stalk type = 'key item', From 9b053f729abd9b218dbc82503c7ad3a395a397da Mon Sep 17 00:00:00 2001 From: Chiaia Date: Wed, 7 Oct 2020 11:57:18 -0400 Subject: [PATCH 0496/1002] Update craft.lua --- addons/craft/craft.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/craft/craft.lua b/addons/craft/craft.lua index 66717857c4..6a26a16337 100644 --- a/addons/craft/craft.lua +++ b/addons/craft/craft.lua @@ -29,8 +29,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] _addon.name = 'craft' -_addon.author = 'Mojo' -_addon.version = '1.1.1' +_addon.author = 'Mojo, Recipes provided by BG-Wiki.com' +_addon.version = '1.1.2' _addon.commands = {'craft'} require('chat') From 50cd319f15e0abe17c0f2c018f122e2ce8a1ccd4 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Mon, 12 Oct 2020 03:21:12 +0200 Subject: [PATCH 0497/1002] [battlemod] Critical fix and new feature added Fixed a critical bug that could end with a windower crash, added condensation for targets with the same name, several minor fixes. --- addons/battlemod/battlemod.lua | 10 +++++- addons/battlemod/parse_action_packet.lua | 46 ++++++++++++++++-------- addons/battlemod/statics.lua | 12 +++++-- 3 files changed, 51 insertions(+), 17 deletions(-) diff --git a/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index 7a1e277a15..07f2382298 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -12,7 +12,7 @@ require 'generic_helpers' require 'parse_action_packet' require 'statics' -_addon.version = '3.27' +_addon.version = '3.28' _addon.name = 'BattleMod' _addon.author = 'Byrth, maintainer: SnickySnacks' _addon.commands = {'bm','battlemod'} @@ -41,6 +41,9 @@ windower.register_event('addon command', function(command, ...) 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)) @@ -67,6 +70,9 @@ windower.register_event('addon command', function(command, ...) 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() == 'colortest' then local counter = 0 local line = '' @@ -93,6 +99,7 @@ windower.register_event('addon command', function(command, ...) 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(' * targetname --- Toggle target name condensation ('..tostring(targetname)..')') 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)..')') @@ -100,6 +107,7 @@ windower.register_event('addon command', function(command, ...) print(' * sumdamage --- Sums condensed damage, if false damage is comma separated ('..tostring(sumdamage)..')') print(' * condensecrits --- Condenses critical hits and normal hits together ('..tostring(condensecrits)..')') print(' 4. cancelmulti --- Cancles multiple consecutive identical lines ('..tostring(cancelmulti)..')') + print(' 5. showonernames --- Show the name of the owner on pet messages ('..tostring(showownernames)..')') 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') diff --git a/addons/battlemod/parse_action_packet.lua b/addons/battlemod/parse_action_packet.lua index c39e7f855d..7c10931ebb 100644 --- a/addons/battlemod/parse_action_packet.lua +++ b/addons/battlemod/parse_action_packet.lua @@ -10,6 +10,7 @@ function parse_action_packet(act) 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)) --fix for ffxi chat splits on trusts with - if not act.action then return act @@ -144,7 +145,7 @@ function parse_action_packet(act) 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) + --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 @@ -182,6 +183,7 @@ function parse_action_packet(act) 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 @@ -221,9 +223,13 @@ function parse_action_packet(act) 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..' (stunned)' - elseif m.message == 1023 then - m.status = color_it('attacks and defenses enhanced',color_arr['statuscol']) + 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 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. @@ -394,14 +400,14 @@ function simplify_message(msg_ID) local fields = fieldsearch(msg) if simplify and not T{23,64,133,139,140,204,210,211,212,213,214,350,442,516,531,557,565,582,674}: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,1023}: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,1023}:contains(msg_ID) then + T{129,152,161,162,163,165,229,384,453,603,652,798}:contains(msg_ID) then fields.ability = true end @@ -410,7 +416,7 @@ function simplify_message(msg_ID) fields.item = true end - if T{129,152,153,160,161,162,163,164,165,166,167,168,229,244,652,1023}:contains(msg_ID) then + 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 @@ -455,28 +461,40 @@ 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) then - targets[#targets+1] = v + 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 #targets > 1 then - out_str = '{'..#targets..'} ' + if targetnumber and total > 1 then + out_str = '{'..total..'}: ' else out_str = '' end for i,v in pairs(targets) do + local name + local numb = condensetargetname and samename[v.name] > 1 and ' {'..samename[v.name]..'}' or '' if i == 1 then - out_str = out_str..color_it(v.name,color_arr[v.owner or v.type]) + name = color_it(v.name,color_arr[v.owner or v.type]) + out_str = out_str..name..numb else - out_str = conjunctions(out_str,color_it(v.name,color_arr[v.owner or v.type]),#targets,i) + name = color_it(v.name,color_arr[v.owner or v.type]) + out_str = conjunctions(out_str,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 diff --git a/addons/battlemod/statics.lua b/addons/battlemod/statics.lua index c6872d9373..3fbd4b5707 100644 --- a/addons/battlemod/statics.lua +++ b/addons/battlemod/statics.lua @@ -29,7 +29,7 @@ ratings_arr = {'TW','IEP','EP','DC','EM','T','VT','IT'} current_job = 'NONE' default_filt = false 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,608,648,650,651,658,732,736,746,747,748,749,750,751,752,753,767,768,769,770,781} +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,40,47,48,49,64,78,87,88,89,90,112,116,154,170,171,172,173,174,175,176,177,178,191,192,198,204,215,217,218,219,234,246,249,307,315,328,350,336,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,62,94,251,308,313,372,8,105,253,679,97,62,94,251,313,308,206,72,38,53} 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. @@ -108,7 +108,7 @@ default_settings_table = {line_aoe = 'AOE ${numb} '..string.char(129,168). 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,swingnumber=true,sumdamage=true,condensecrits=false} + condensedamage=true,condensetargets=true,cancelmulti=true,oxford=true,commamode=false,targetnumber=true,condensetargetname=false,swingnumber=true,sumdamage=true,condensecrits=false,showownernames=false} message_map = {} for n=1,700,1 do @@ -164,6 +164,13 @@ 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} @@ -518,6 +525,7 @@ default_settings = [[ true false true + false true true false From 1080e44a12dd4ceb249771801a72f2b6a14b6109 Mon Sep 17 00:00:00 2001 From: funkworkz Date: Mon, 12 Oct 2020 00:31:08 -0500 Subject: [PATCH 0498/1002] Update setbgm.lua New song October update --- addons/setbgm/setbgm.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/setbgm/setbgm.lua b/addons/setbgm/setbgm.lua index ad7033706b..12935dbb2e 100644 --- a/addons/setbgm/setbgm.lua +++ b/addons/setbgm/setbgm.lua @@ -50,7 +50,7 @@ music_types = { } songs = { - [25]='Voracious Resurgence Unknown 1', [26]='Voracious Resurgence Unknown 2', [27]='Voracious Resurgence Unknown 3', [28]='Voracious Resurgence Unknown 4', + [25]='Voracious Resurgence Unknown 1', [26]='Voracious Resurgence Unknown 2', [27]='Voracious Resurgence Unknown 3', [28]='Voracious Resurgence Unknown 4', [29]='Voracious Resurgence Unknown 5', [40]='Cloister of Time and Souls', [41]='Royal Wanderlust', [42]='Snowdrift Waltz', [43]='Troubled Shadows', [44]='Where Lords Rule Not', [45]='Summers Lost', [46]='Goddess Divine', [47]='Echoes of Creation', [48]='Main Theme', [49]='Luck of the Mog', [50]='Feast of the Ladies', [51]='Abyssea - Scarlet Skies, Shadowed Plains', [52]='Melodies Errant', [53]='Shinryu', [54]='Everlasting Bonds', [55]='Provenance Watcher', [56]='Where it All Begins', [57]='Steel Sings, Blades Dance', [58]='A New Direction', [59]='The Pioneers', [60]='Into Lands Primeval - Ulbuka', [61]="Water's Umbral Knell", [62]='Keepers of the Wild', [63]='The Sacred City of Adoulin', [64]='Breaking Ground', [65]='Hades', [66]='Arciela', [67]='Mog Resort', [68]='Worlds Away', [69]="Distant Worlds (Nanaa Mihgo's version)", From ab45e71387769e18ccbcf5f10b4b08ac57ff375c Mon Sep 17 00:00:00 2001 From: Posimagi Date: Mon, 12 Oct 2020 12:41:35 -0700 Subject: [PATCH 0499/1002] [battlemod] add crafting display toggle --- addons/battlemod/README.md | 11 +++++++---- addons/battlemod/battlemod.lua | 12 ++++++++---- addons/battlemod/statics.lua | 3 ++- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/addons/battlemod/README.md b/addons/battlemod/README.md index fbcced3b01..259b94ba50 100644 --- a/addons/battlemod/README.md +++ b/addons/battlemod/README.md @@ -8,16 +8,19 @@ Battlemod, packet version Abbreviation: //bm -Commands: +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 + * targetnumber - Toggle condensed target number display, Default = True * condensedamage - Collapses similar damage messages with the same target, Default = True -** swingnumber - Toggle condensed damage number display, Default = True + * swingnumber - Toggle condensed damage number display, Default = True * cancelmulti - Cancels multiple consecutive identical lines, Default = True * oxford - Toggle use of oxford comma, Default = True * commamode - Toggle comma-only mode, 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 @@ -32,4 +35,4 @@ The settings files for battlemod are composed of 3 to 25 xml files (depending on * 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-.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 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. \ No newline at end of file +* filters/filters-.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 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/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index 07f2382298..aa9759d1bd 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -73,6 +73,9 @@ windower.register_event('addon command', function(command, ...) 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() == 'colortest' then local counter = 0 local line = '' @@ -106,8 +109,9 @@ windower.register_event('addon command', function(command, ...) print(' * swingnumber --- Show # of attack rounds ('..tostring(swingnumber)..')') print(' * sumdamage --- Sums condensed damage, if false damage is comma separated ('..tostring(sumdamage)..')') print(' * condensecrits --- Condenses critical hits and normal hits together ('..tostring(condensecrits)..')') - print(' 4. cancelmulti --- Cancles multiple consecutive identical lines ('..tostring(cancelmulti)..')') - print(' 5. showonernames --- Show the name of the owner on pet messages ('..tostring(showownernames)..')') + 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('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') @@ -390,7 +394,7 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec end ------------ SYNTHESIS ANIMATION -------------- - elseif id == 0x030 then + 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) @@ -404,7 +408,7 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec windower.add_to_chat(8,'Craftmod: Unhandled result '..tostring(result)) end end - elseif id == 0x06F then + 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 diff --git a/addons/battlemod/statics.lua b/addons/battlemod/statics.lua index 3fbd4b5707..1af1e45be7 100644 --- a/addons/battlemod/statics.lua +++ b/addons/battlemod/statics.lua @@ -108,7 +108,7 @@ default_settings_table = {line_aoe = 'AOE ${numb} '..string.char(129,168). 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} + condensedamage=true,condensetargets=true,cancelmulti=true,oxford=true,commamode=false,targetnumber=true,condensetargetname=false,swingnumber=true,sumdamage=true,condensecrits=false,showownernames=false,crafting=true,} message_map = {} for n=1,700,1 do @@ -532,6 +532,7 @@ default_settings = [[ true true false + true AOE ${numb} ]]..string.char(129,168)..[[ ${target} ${actor} ${abil} ]]..string.char(129,168)..[[ ${target} (${status}) [${actor}] ${numb} ${abil} ]]..string.char(129,168)..[[ ${target} From 88b096fb7d208157bfe3cc34aae43d7f79bd010e Mon Sep 17 00:00:00 2001 From: Posimagi Date: Mon, 12 Oct 2020 14:35:09 -0700 Subject: [PATCH 0500/1002] [battlemod] fix condensetargetname toggle --- addons/battlemod/README.md | 22 +++++++++++++--------- addons/battlemod/battlemod.lua | 32 ++++++++++++++++---------------- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/addons/battlemod/README.md b/addons/battlemod/README.md index 259b94ba50..2a9a823b1f 100644 --- a/addons/battlemod/README.md +++ b/addons/battlemod/README.md @@ -11,15 +11,19 @@ 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 -* condensedamage - Collapses similar damage messages with the same target, Default = True - * swingnumber - Toggle condensed damage number display, Default = True -* cancelmulti - Cancels multiple consecutive identical lines, Default = True -* oxford - Toggle use of oxford comma, Default = True -* commamode - Toggle comma-only mode, Default = False -* crafting - Toggle early display of crafting results, Default = True +* 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 diff --git a/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index aa9759d1bd..89a0de26f3 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -99,22 +99,22 @@ windower.register_event('addon command', function(command, ...) 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(' * targetname --- Toggle target name condensation ('..tostring(targetname)..')') - 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 false damage is comma separated ('..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('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') + 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('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) From 72b756f5f9017b0d0ac6355a9685a6e5a5330960 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Tue, 13 Oct 2020 04:37:24 +0200 Subject: [PATCH 0501/1002] [translate] back to hardcoded packet, bug fix Back to hardcoded packet modification instead of library, bug fix when several incoming text with mode 204 comes in a short period of time. --- addons/translate/translate.lua | 54 ++++++++++++++++------------------ 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/addons/translate/translate.lua b/addons/translate/translate.lua index f036e92976..a33bbdab52 100644 --- a/addons/translate/translate.lua +++ b/addons/translate/translate.lua @@ -33,7 +33,6 @@ _addon.commands = {'trans','translate'} language = 'english' trans_list = {} res = require 'resources' -packets = require('packets') require 'sets' require 'lists' require 'pack' @@ -71,7 +70,7 @@ red_close = string.char(0xEF,0x28) green_col = ''--string.char(0x1E,2) rcol = ''--string.char(0x1E,1) - +local temp_str function to_a_code(num) local first_byte,second_byte = math.floor(num/256),num%256 @@ -197,18 +196,26 @@ trans_list['\.'] = nil windower.register_event('incoming chunk',function(id,orgi,modi,is_injected,is_blocked) if id == 0x17 and not is_injected and not is_blocked then - local packet = packets.parse('incoming', modi) - local out_text = packet.Message + local out_text = modi:unpack('z',0x18) out_text = translate_phrase(out_text) if not out_text then return end - if show_original then windower.add_to_chat(8, '[Original]: '..packet.Message) end - - packet.Message = out_text - local rebuilt = packets.build(packet) - return rebuilt + if show_original then windower.add_to_chat(8,modi:sub(9,0x17):unpack('z',1)..'[Original]: '..modi:unpack('z',0x18)) end + while #out_text > 0 do + local boundary = get_boundary_length(out_text,151) + local len = math.ceil((boundary+1+23)/2) -- Make sure there is at least one nul after the string + local out_pack = string.char(0x17,len)..modi:sub(3,0x17)..out_text:sub(1,boundary) + + -- zero pad it + while #out_pack < len*2 do + out_pack = out_pack..string.char(0) + end + windower.packets.inject_incoming(0x17,out_pack) + out_text = out_text:sub(boundary+1) + end + return true end end) @@ -317,29 +324,18 @@ end) windower.register_event('incoming text',function(org,mod,ocol,mcol,blk) if not blk and ocol == 204 then - local ret = translate_phrase(org) - if os.clock()-search_comment.ts>0.4 then - search_comment = {ts = os.clock(), reg = L{}, translated = false} - end + local ret = translate_phrase(mod) + temp_str = ret or org if ret then - if not search_comment.reg:contains(ret) then - search_comment.translated = true - search_comment.reg:append(ret) - windower.add_to_chat(204,ret) - coroutine.yield(true) - if show_original then - coroutine.sleep(0.3) - if search_comment.translated then windower.add_to_chat(8,'[Original]: '..org) end - end - end - elseif not search_comment.reg:contains(org) then - search_comment.reg:append(org) - windower.add_to_chat(204,org) - coroutine.yield(true) if show_original then - coroutine.sleep(0.3) - if search_comment.translated then windower.add_to_chat(8,'[Original]: '..org) end + windower.add_to_chat:schedule(0.3, 8,'[Original]: '..org) + end + mod = ret + if org == temp_str then + blk = true + temp_str = '' end + return blk and blk or mod end end end) From e85f172abbbb82917d47223f408b4cfe15e029c5 Mon Sep 17 00:00:00 2001 From: funkworkz Date: Sun, 25 Oct 2020 09:48:31 -0500 Subject: [PATCH 0502/1002] Update setbgm.lua Song name was confirmed from obtaining and using the key item "Sheet of harvest tunes" during the halloween 2020 event. --- addons/setbgm/setbgm.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/setbgm/setbgm.lua b/addons/setbgm/setbgm.lua index 12935dbb2e..ca6917db10 100644 --- a/addons/setbgm/setbgm.lua +++ b/addons/setbgm/setbgm.lua @@ -50,7 +50,7 @@ music_types = { } songs = { - [25]='Voracious Resurgence Unknown 1', [26]='Voracious Resurgence Unknown 2', [27]='Voracious Resurgence Unknown 3', [28]='Voracious Resurgence Unknown 4', [29]='Voracious Resurgence Unknown 5', + [25]='Voracious Resurgence Unknown 1', [26]='Voracious Resurgence Unknown 2', [27]='Voracious Resurgence Unknown 3', [28]='Voracious Resurgence Unknown 4', [29]="Devils' Delight", [40]='Cloister of Time and Souls', [41]='Royal Wanderlust', [42]='Snowdrift Waltz', [43]='Troubled Shadows', [44]='Where Lords Rule Not', [45]='Summers Lost', [46]='Goddess Divine', [47]='Echoes of Creation', [48]='Main Theme', [49]='Luck of the Mog', [50]='Feast of the Ladies', [51]='Abyssea - Scarlet Skies, Shadowed Plains', [52]='Melodies Errant', [53]='Shinryu', [54]='Everlasting Bonds', [55]='Provenance Watcher', [56]='Where it All Begins', [57]='Steel Sings, Blades Dance', [58]='A New Direction', [59]='The Pioneers', [60]='Into Lands Primeval - Ulbuka', [61]="Water's Umbral Knell", [62]='Keepers of the Wild', [63]='The Sacred City of Adoulin', [64]='Breaking Ground', [65]='Hades', [66]='Arciela', [67]='Mog Resort', [68]='Worlds Away', [69]="Distant Worlds (Nanaa Mihgo's version)", From 86d935ccde3b333d36594bd8c2b0ab74cd153b9a Mon Sep 17 00:00:00 2001 From: Nifim Date: Mon, 9 Nov 2020 08:56:41 -0800 Subject: [PATCH 0503/1002] Update bstpet_range new pet moves added to resources, need to change max value to reflect new value. --- addons/GearSwap/statics.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/GearSwap/statics.lua b/addons/GearSwap/statics.lua index 9693b89529..257058929d 100644 --- a/addons/GearSwap/statics.lua +++ b/addons/GearSwap/statics.lua @@ -54,7 +54,7 @@ for i,v in pairs(res.bags) do bag_string_lookup[to_windower_bag_api(v.en)]=i end -bstpet_range = {min=672,max=782} -- Range of the JA resource devoted to BST jugpet abilities +bstpet_range = {min=672,max=798} -- Range of the JA resource devoted to BST jugpet abilities delay_map_to_action_type = {['Ability']=3,['Magic']=20,['Ranged Attack']=10,['Item']=10,['Monster Move']=10,['Interruption']=3} @@ -444,4 +444,4 @@ function initialize_globals() end end -initialize_globals() \ No newline at end of file +initialize_globals() From f4e08b1313a3a34fd3c80804f3d5b2755383dbdc Mon Sep 17 00:00:00 2001 From: Chiaia Date: Sat, 14 Nov 2020 01:35:24 -0500 Subject: [PATCH 0504/1002] Update static_variables.lua --- addons/DressUp/static_variables.lua | 32 ++++++++++++++--------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/addons/DressUp/static_variables.lua b/addons/DressUp/static_variables.lua index e05b43341e..0359eeade2 100644 --- a/addons/DressUp/static_variables.lua +++ b/addons/DressUp/static_variables.lua @@ -74,22 +74,22 @@ _races["g"] = 8 -- Maps commonly known face IDs to their actual IDs _faces = {} -_faces["1a"] = 1 -_faces["1b"] = 2 -_faces["2a"] = 3 -_faces["2b"] = 4 -_faces["3a"] = 5 -_faces["3b"] = 6 -_faces["4a"] = 7 -_faces["4b"] = 8 -_faces["5a"] = 9 -_faces["5b"] = 10 -_faces["6a"] = 11 -_faces["6b"] = 12 -_faces["7a"] = 13 -_faces["7b"] = 14 -_faces["8a"] = 15 -_faces["8b"] = 16 +_faces["1a"] = 0 +_faces["1b"] = 1 +_faces["2a"] = 2 +_faces["2b"] = 3 +_faces["3a"] = 4 +_faces["3b"] = 5 +_faces["4a"] = 6 +_faces["4b"] = 7 +_faces["5a"] = 8 +_faces["5b"] = 9 +_faces["6a"] = 10 +_faces["6b"] = 11 +_faces["7a"] = 12 +_faces["7b"] = 13 +_faces["8a"] = 14 +_faces["8b"] = 15 _faces["Fomor"] = 29 _faces["Mannequin"] = 30 From 0b260e1378432e0561f10d734a21ec2f24a1d7d3 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Tue, 17 Nov 2020 05:22:28 +0100 Subject: [PATCH 0505/1002] Added damaging drain msg to mydmg coloring Added damaging drain msg to mydmg coloring. --- addons/battlemod/battlemod.lua | 2 +- addons/battlemod/parse_action_packet.lua | 16 ++++++++-------- addons/battlemod/statics.lua | 1 + 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index 89a0de26f3..fdf1a25966 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -12,7 +12,7 @@ require 'generic_helpers' require 'parse_action_packet' require 'statics' -_addon.version = '3.28' +_addon.version = '3.29' _addon.name = 'BattleMod' _addon.author = 'Byrth, maintainer: SnickySnacks' _addon.commands = {'bm','battlemod'} diff --git a/addons/battlemod/parse_action_packet.lua b/addons/battlemod/parse_action_packet.lua index 7c10931ebb..83f2f09b85 100644 --- a/addons/battlemod/parse_action_packet.lua +++ b/addons/battlemod/parse_action_packet.lua @@ -258,7 +258,7 @@ function parse_action_packet(act) 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.cparam or m.param),m.message) end + if m.fields.status then numb = m.status else numb = pref_suf((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 @@ -292,7 +292,7 @@ function parse_action_packet(act) :gsub('${item2}',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}',col == 'D' and color_it(numb or 'ERROR 116', color_arr[act.actor.damage]) or (numb or 'ERROR 116')) + :gsub('${numb}',numb or 'ERROR 116') :gsub('${actor}',color_it((act.actor.name or 'ERROR 117' ) .. (act.actor.owner_name or "") ,color_arr[act.actor.owner or act.actor.type])) :gsub('${target}',targ) :gsub('${lb}','\7'..prefix2) @@ -316,7 +316,7 @@ function parse_action_packet(act) else m.simp_add_name = 'AE' end local msg,numb = simplify_message(m.add_effect_message) - 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) 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 @@ -326,7 +326,7 @@ function parse_action_packet(act) :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}',col == 'D' and color_it(numb or 'ERROR 132', color_arr[act.actor.damage]) or (numb or 'ERROR 132')) + :gsub('${numb}',numb or 'ERROR 132') :gsub('${actor}',color_it(act.actor.name,color_arr[act.actor.owner or act.actor.type])) :gsub('${target}',targ) :gsub('${lb}','\7') @@ -361,14 +361,14 @@ function parse_action_packet(act) end local msg = simplify_message(m.spike_effect_message) - 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) 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)..(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}',col == 'D' and color_it(numb or 'ERROR 147', color_arr[actor.damage]) or (numb or 'ERROR 147')) + :gsub('${numb}',numb or 'ERROR 147') :gsub((simplify and '${target}' or '${actor}'),color_it(act.actor.name,color_arr[act.actor.owner or act.actor.type])) :gsub((simplify and '${actor}' or '${target}'),targ) :gsub('${lb}','\7') @@ -384,8 +384,8 @@ function parse_action_packet(act) return act end -function pref_suf(param,msg_ID) - local outstr = tostring(param) +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) if res.action_messages[msg_ID] and res.action_messages[msg_ID].prefix then outstr = res.action_messages[msg_ID].prefix..' '..outstr end diff --git a/addons/battlemod/statics.lua b/addons/battlemod/statics.lua index 1af1e45be7..20b9a80815 100644 --- a/addons/battlemod/statics.lua +++ b/addons/battlemod/statics.lua @@ -36,6 +36,7 @@ color_redundant = T{26,33,41,71,72,89,94,109,114,164,173,181,184,186,70,84,104,1 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} domain_buffs = S{ 250, -- EF Badge From 7f8777c2b438ec8592ec6907afeaed13179c96a5 Mon Sep 17 00:00:00 2001 From: Cellcubed <74109458+Cellcubed@users.noreply.github.com> Date: Thu, 19 Nov 2020 12:54:06 -0600 Subject: [PATCH 0506/1002] Update traits.lua ID for voracious trunk was incorrect changed from 576 to 579 --- addons/bluguide/res/traits.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/bluguide/res/traits.lua b/addons/bluguide/res/traits.lua index e7d98806af..b4d8175149 100644 --- a/addons/bluguide/res/traits.lua +++ b/addons/bluguide/res/traits.lua @@ -36,7 +36,7 @@ return { { name = "Self-Destruct", points = 2, cost = 3, id = 533 }, { name = "Cold Wave", points = 1, cost = 1, id = 535 }, { name = "Light of Penance", points = 2, cost = 5, id = 634 }, - { name = "Voracious Trunk", points = 3, cost = 4, id = 576 }, + { name = "Voracious Trunk", points = 3, cost = 4, id = 579 }, { name = "Actinic Burst", points = 4, cost = 4, id = 612 }, { name = "Plasma Charge", points = 4, cost = 5, id = 615 }, { name = "Winds of Promy.", points = 4, cost = 5, id = 681 }, From e3306b371d1c9e86fb02888f0415c1fa44477646 Mon Sep 17 00:00:00 2001 From: Cellcubed <74109458+Cellcubed@users.noreply.github.com> Date: Thu, 19 Nov 2020 12:57:39 -0600 Subject: [PATCH 0507/1002] Update bluguide.lua Added 3 missing traits --- addons/bluguide/bluguide.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addons/bluguide/bluguide.lua b/addons/bluguide/bluguide.lua index 33c95a0310..e541b98895 100644 --- a/addons/bluguide/bluguide.lua +++ b/addons/bluguide/bluguide.lua @@ -118,12 +118,15 @@ function build_columns() traitpage:add(traitboxes.new(traits['Defense Bonus'])) traitpage:add(traitboxes.new(traits['Magic Defense Bonus'])) traitpage:add(traitboxes.new(traits['Magic Evasion Bonus'])) + traitpage:add(traitboxes.new(traits['Evasion Bonus'])) traitpage:add(traitboxes.new(traits['Inquartata'])) traitpage:add(traitboxes.new(traits['Auto Regen'])) traitpage:add(traitboxes.new(traits['Max HP Boost'])) traitpage:add(traitboxes.new(traits['Tenacity'])) traitpage:add(traitboxes.new(traits['Resist Gravity'])) + traitpage:add(traitboxes.new(traits['Resist Silence'])) traitpage:add(traitboxes.new(traits['Resist Sleep'])) + traitpage:add(traitboxes.new(traits['Resist Slow'])) traitpage:add(traitboxes.new(traits['Gilfinder/TH'])) traitpage:add(traitboxes.new(traits['Beast Killer'])) traitpage:add(traitboxes.new(traits['Lizard Killer'])) From 1cd59d3d5d2d70a706c32e87bc14032b6703bdb5 Mon Sep 17 00:00:00 2001 From: Nifim Date: Sun, 22 Nov 2020 19:55:41 -0800 Subject: [PATCH 0508/1002] Correct and Improve burden tracker Burden tracker needed updating and corrections: * Use non-0 manuever action param to infer burden. * Correct activate and zone burden. * improved encapsulation and abstration of burden tracker. * improved automaton ability timer handling. --- addons/autocontrol/autoabils.lua | 60 +++++ addons/autocontrol/autocontrol.lua | 33 +-- addons/autocontrol/burden.lua | 180 +++++++++++++ addons/autocontrol/burdometer.lua | 96 +++++++ addons/autocontrol/maneuver.lua | 420 ----------------------------- 5 files changed, 348 insertions(+), 441 deletions(-) create mode 100644 addons/autocontrol/autoabils.lua create mode 100644 addons/autocontrol/burden.lua create mode 100644 addons/autocontrol/burdometer.lua delete mode 100644 addons/autocontrol/maneuver.lua diff --git a/addons/autocontrol/autoabils.lua b/addons/autocontrol/autoabils.lua new file mode 100644 index 0000000000..668942890d --- /dev/null +++ b/addons/autocontrol/autoabils.lua @@ -0,0 +1,60 @@ +autoabils = { + [1688] = {name='Shield Bash', recast=180, icon="00210"}, + [1689] = {name='Strobe', recast=30, icon="00210"}, + [1690] = {name='Shock Absorber', recast=180, icon="00210"}, + [1691] = {name='Flashbulb', recast=45, icon="00210"}, + [1692] = {name='Mana Converter', recast=180, icon="00210"}, + [1755] = {name='Reactive Shield', recast=65, icon="00210"}, + [1765] = {name='Eraser', recast=30, icon="00210"}, + [1812] = {name='Economizer', recast=180, icon = "00210"}, + [1876] = {name='Replicator', recast=60, icon = "00210"}, + [2489] = {name='Heat Capacitator', recast=90, icon = "00210"}, + [2490] = {name='Barrage Turbine', recast=180, icon = "00210"}, + [2491] = {name='Disruptor', recast=60, icon = "00210"}, +} +attachments_to_abilities = { + [8225] = 1688, + [8449] = 1689, + [8454] = 1755, + [8456] = 2489, + [8457] = 1689, + [8461] = 2489, + [8519] = 1876, + [8520] = 2490, + [8545] = 1690, + [8553] = 1690, + [8557] = 1690, + [8642] = 1691, + [8645] = 1765, + [8674] = 1692, + [8678] = 1812, + [8680] = 2491, + [8682] = 3485, +} + +local player_id = windower.ffxi.get_player().id +windower.register_event("action", function(act) + local abil_ID = act['param'] + local actor_id = act['actor_id'] + local pet_index = windower.ffxi.get_mob_by_id(player_id)['pet_index'] + + if act['category'] == 6 and actor_id == player_id and (abil_ID == 136 or abil_ID == 310 or abil_ID == 139) then + avalible_abilities = {} + local automaton = windower.ffxi.get_mjob_data() + if attachments_to_abilities[automaton.frame] then + table.insert(avalible_abilities, autoabils[attachments_to_abilities[automaton.frame]]) + end + for _, id in pairs(automaton.attachments) do + if attachments_to_abilities[id] then + table.insert(avalible_abilities, autoabils[attachments_to_abilities[id]]) + end + end + + for _, ability in pairs(avalible_abilities) do + windower.send_command('timers '.. (abil_ID == 139 and "d" or "c") .. ' "'..ability.name..'" ' .. (abil_ID == 139 and "" or ability.recast..' up abilities/' .. ability.icon)) + end + elseif autoabils[abil_ID-256] and windower.ffxi.get_mob_by_id(actor_id)['index'] == pet_index and pet_index ~= nil then + local abil = abil_ID - 256 + windower.send_command('@timers c "'..autoabils[abil].name..'" '..autoabils[abil].recast..' up') + end +end) \ No newline at end of file diff --git a/addons/autocontrol/autocontrol.lua b/addons/autocontrol/autocontrol.lua index f16f872c81..8438e51040 100644 --- a/addons/autocontrol/autocontrol.lua +++ b/addons/autocontrol/autocontrol.lua @@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] _addon.name = 'autocontrol' -_addon.version = '1.02' +_addon.version = '2.0' _addon.author = 'Nitrous (Shiva)' _addon.commands = {'autocontrol','acon'} @@ -63,8 +63,8 @@ defaults.burdentracker = true settings = config.load(defaults) -require('maneuver') -- has to be loaded after settings are parsed. - +burden_hud = require('burdometer') -- has to be loaded after settings are parsed. +require("autoabils") recast_ids = {} recast_ids.deactivate = res.job_abilities:with('english', 'Deactivate').recast_id recast_ids.activate = res.job_abilities:with('english', 'Activate').recast_id @@ -83,18 +83,11 @@ function initialize() mjob_id = player.main_job_id atts = res.items:category('Automaton') - decay = 1 - for key,_ in pairs(heat) do - heat[key] = 0 - Burden_tb[key] = 0 - Burden_tb['time' .. key] = 0 - end + if mjob_id == 18 then if player.pet_index then - running = 1 - text_update_loop('start') if settings.burdentracker then - Burden_tb:show() + burden_hud:show() end end end @@ -102,8 +95,6 @@ end windower.register_event('load', 'login', initialize) -windower.register_event('logout', 'unload', text_update_loop:prepare('stop')) - function attach_set(autoset) if windower.ffxi.get_player().main_job_id ~= 18 or not settings.autosets[autoset] then return @@ -268,15 +259,15 @@ windower.register_event('addon command', function(comm, ...) elseif comm == "maneuvertimers" or comm == "mt" then maneuvertimers = not maneuvertimers elseif S{'fonttype','fontsize','pos','bgcolor','txtcolor'}:contains(comm) then - if comm == 'fonttype' then Burden_tb:font(args[1]) - elseif comm == 'fontsize' then Burden_tb:size(args[1]) - elseif comm == 'pos' then Burden_tb:pos(args[1], args[2]) - elseif comm == 'bgcolor' then Burden_tb:bgcolor(args[1], args[2], args[3]) - elseif comm == 'txtcolor' then Burden_tb:color(args[1], args[2], args[3]) + if comm == 'fonttype' then burden_hud:font(args[1]) + elseif comm == 'fontsize' then burden_hud:size(args[1]) + elseif comm == 'pos' then burden_hud:pos(args[1], args[2]) + elseif comm == 'bgcolor' then burden_hud:bgcolor(args[1], args[2], args[3]) + elseif comm == 'txtcolor' then burden_hud:color(args[1], args[2], args[3]) end config.save(settings, 'all') - elseif comm == 'show' then Burden_tb:show() - elseif comm == 'hide' then Burden_tb:hide() + elseif comm == 'show' then burden_hud:show() + elseif comm == 'hide' then burden_hud:hide() elseif comm == 'settings' then log('BG: R: '..settings.bg.red..' G: '..settings.bg.green..' B: '..settings.bg.blue) log('Font: '..settings.text.font..' Size: '..settings.text.size) diff --git a/addons/autocontrol/burden.lua b/addons/autocontrol/burden.lua new file mode 100644 index 0000000000..2ca46335d9 --- /dev/null +++ b/addons/autocontrol/burden.lua @@ -0,0 +1,180 @@ +local set = require("sets") + +local o = { + fire = 0, + earth = 0, + water = 0, + wind = 0, + ice = 0, + thunder = 0, + light = 0, + dark = 0, +} +local burden = {} +local mt = { + __index = burden +} +setmetatable(o, mt) +local updaters = {} +local heatsink +for _, id in pairs(windower.ffxi.get_mjob_data().attachments) do + heatsink = (id == 8610) + if heatsink then + break + end +end + +local thresholdModifiers = +{ + [11101] = 40, -- Cirque Farsetto +2 + [11201] = 20, -- Cirque Farsetto +1 + [14930] = 5, -- Pup. Dastanas + [15030] = 5, -- Pup. Dastanas +1 + [16281] = 5, -- Buffoon's Collar + [16282] = 5, -- Buffoon's Collar +1 + [20520] = 40, -- Midnights + [26263] = 10, -- Visucius's Mantle + [26932] = 40, -- Kara. Farsetto + [26933] = 40, -- Kara. Farsetto +1 + [27960] = 5, -- Foire Dastanas + [27981] = 5, -- Foire Dastanas +1 + [28634] = 5, -- Dispersal Mantle +} +burden.threshold = 30 + +local pet_actions = +{ + [136] = "activate", + [139] = "deactivate", + [141] = "fire", + [142] = "ice", + [143] = "wind", + [144] = "earth", + [145] = "thunder", + [146] = "water", + [147] = "light", + [148] = "dark", + [309] = "cooldown", + [310] = "deus_ex_automata", +} +function burden:update(action) + updaters[action](self) +end + +function burden:zone() + for k in pairs(self) do + self[k] = 15 + end +end + +function burden.set_decay_event(func) + burden.decay_event = func +end +function updaters.deactivate(self) + for k in pairs(self) do + self[k] = 0 + end +end + +function updaters.activate(self) + for _, id in pairs(windower.ffxi.get_mjob_data().attachments) do + heatsink = (id == 8610) + if heatsink then + break + end + end + burden.update_decay_rate() + for k in pairs(self) do + self[k] = 15 + end +end +updaters.deus_ex_automata = updaters.activate + +function updaters.cooldown(self) + for k in pairs(self) do + self[k] = self[k] / 2 + end +end + +function updaters.maneuver(self, type) + self[type] = self[type] + 15 + local inventory = windower.ffxi.get_items() + local equipment = { + sub = {}, + ammo = {}, + main = {}, + head = {}, + body = {}, + back = {}, + legs = {}, + feet = {}, + neck = {}, + hands = {}, + range = {}, + waist = {}, + left_ear = {}, + left_ring = {}, + right_ear = {}, + right_ring = {}, + } + for k, v in pairs(inventory.equipment) do + equipment[string.gsub(k ,"_bag","")][k] = v + end + burden.threshold = 30 + for k, v in pairs(equipment) do + item = windower.ffxi.get_items(v[k .. "_bag"], v[k]) + if thresholdModifiers[item.id] then + burden.threshold = burden.threshold + thresholdModifiers[item.id] + end + end + windower.add_to_chat(4, self[type]) +end + +function updaters.ice(self) updaters.maneuver(self, "ice") end +function updaters.fire(self) updaters.maneuver(self, "fire") end +function updaters.wind(self) updaters.maneuver(self, "wind") end +function updaters.dark(self) updaters.maneuver(self, "dark") end +function updaters.earth(self) updaters.maneuver(self, "earth") end +function updaters.water(self) updaters.maneuver(self, "water") end +function updaters.light(self) updaters.maneuver(self, "light") end +function updaters.thunder(self) updaters.maneuver(self, "thunder") end + +burden.decay_rate = 1 +function burden.decay() + for k in pairs(o) do + if o[k] > burden.decay_rate then + o[k] = o[k] - burden.decay_rate + elseif o[k] > 0 then + o[k] = 0 + end + end + if burden.decay_event then + burden.decay_event() + end + coroutine.schedule(burden.decay, 3) +end +coroutine.schedule(burden.decay, os.date("*t").sec % 3) + +local count_to_decay_rate = { + [0] = 2, + [1] = 4, + [2] = 5, + [3] = 6, +} +function burden.update_decay_rate() + print(heatsink) + if heatsink then + local count = 0 + for _, v in pairs(windower.ffxi.get_player().buffs) do + print(v) + if v == 305 then + count = count + 1 + end + end + burden.decay_rate = count_to_rate[count]; + else + burden.decay_rate = 1 + end +end + +return o diff --git a/addons/autocontrol/burdometer.lua b/addons/autocontrol/burdometer.lua new file mode 100644 index 0000000000..a7b528db89 --- /dev/null +++ b/addons/autocontrol/burdometer.lua @@ -0,0 +1,96 @@ +local sets = require("sets") +local texts = require("texts") +local burden = require("burden") + +local pet_actions = +{ + [136] = "activate", + [139] = "deactivate", + [141] = "fire", + [142] = "ice", + [143] = "wind", + [144] = "earth", + [145] = "thunder", + [146] = "water", + [147] = "light", + [148] = "dark", + [309] = "cooldown", + [310] = "deus_ex_automata", +} + +local maneuvers = +S{ + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, +} + +str = 'Fire: \\cs(${color_fire|255,255,255})${fire|0}\\cr - ${time_fire|0}s - ${risk_fire|0}%' +str = str .. '\nIce: \\cs(${color_ice|255,255,255})${ice|0}\\cr - ${time_ice|0}s - ${risk_ice|0}%' +str = str .. '\nWind: \\cs(${color_wind|255,255,255})${wind|0}\\cr - ${time_wind|0}s - ${risk_wind|0}%' +str = str .. '\nEarth: \\cs(${color_earth|255,255,255})${earth|0}\\cr - ${time_earth|0}s - ${risk_earth|0}%' +str = str .. '\nThunder: \\cs(${color_thunder|255,255,255})${thunder|0}\\cr - ${time_thunder|0}s - ${risk_thunder|0}%' +str = str .. '\nWater: \\cs(${color_water|255,255,255})${water|0}\\cr - ${time_water|0}s - ${risk_water|0}%' +str = str .. '\nLight: \\cs(${color_light|255,255,255})${light|0}\\cr - ${time_light|0}s - ${risk_light|0}%' +str = str .. '\nDark: \\cs(${color_dark|255,255,255})${dark|0}\\cr - ${time_dark|0}s - ${risk_dark|0}%' + +local hud = texts.new(str, settings) + +function update_hud(element) + hud[element] = burden[element] + + risk = burden[element] - burden.threshold + hud["risk_" .. element] = risk > 0 and risk or 0 + hud["color_" .. element] = "255," .. (risk > 33 and 0 or 255) .. "," .. (risk > 0 and 0 or 255) + hud["time_" .. element] = (burden[element] / burden.decay_rate) * 3 +end + +windower.register_event("action", function(act) + local abil_id = act['param'] + local actor_id = act['actor_id'] + local player = windower.ffxi.get_player() + local pet_index = windower.ffxi.get_mob_by_id(windower.ffxi.get_player()['id'])['pet_index'] + + if player.main_job_id ~= 18 then + return + end + + if act["category"] == 6 and actor_id == player.id and pet_actions[abil_id] then + burden:update(pet_actions[abil_id]) -- Always assumes good burden (+15). + if maneuvers:contains(abil_id) then + if act.targets[1].actions[1].param > 0 then + burden[pet_actions[abil_id]] = burden.threshold + act.targets[1].actions[1].param -- Corrects for bad burden when over threshold. + end + update_hud(pet_actions[abil_id]) + end + end +end) + +local function decay_event() + for element in pairs(burden) do + update_hud(element) + end +end +burden.set_decay_event(decay_event) + +windower.register_event("zone change", function() + burden:zone() +end) + +local function update_decay_rate(buff_id) + if buff_id == 305 then + burden:update_decay_rate() + end +end + +windower.register_event("gain buff", update_decay_rate) +windower.register_event("lose buff", update_decay_rate) + +decay_event() + +return hud \ No newline at end of file diff --git a/addons/autocontrol/maneuver.lua b/addons/autocontrol/maneuver.lua deleted file mode 100644 index 0a6ae085cc..0000000000 --- a/addons/autocontrol/maneuver.lua +++ /dev/null @@ -1,420 +0,0 @@ ---[[ -Copyright (c) 2013, Ricky Gall -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 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 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. -]] - - -local texts = require 'texts' -threshItems = T - {[16281]=5 -- Buffoon's Collar - ,[16282]=5 -- Buffoon's Collar +1 - ,[11101]=40 -- Cirque Farsetto +2 - ,[11201]=20 -- Cirque Farsetto +1 - ,[14930]=5 -- Pup. Dastanas - ,[15030]=5 -- Pup. Dastanas +1 - ,[27960]=5 -- Foire Dastanas - ,[27981]=5 -- Foire Dastanas +1 - ,[28634]=5 -- Dispersal Mantle - ,[26933]=40 -- Kara. Farsetto +1 - ,[26932]=40 -- Kara. Farsetto - } -heat = T{} -heat.Fire = 0 -heat.Ice = 0 -heat.Wind = 0 -heat.Earth = 0 -heat.Thunder = 0 -heat.Water = 0 -heat.Light = 0 -heat.Dark = 0 -timer = T{} -timer.Fire = 0 -timer.Ice = 0 -timer.Wind = 0 -timer.Earth = 0 -timer.Thunder = 0 -timer.Water = 0 -timer.Light = 0 -timer.Dark = 0 -threshold = 30 -running = 0 -maneuver = 1 -lastMan = 'none' -autoabils = T{} -autoabils[1688] = {name='Shield Bash', recast=180} -autoabils[1689] = {name='Strobe', recast=30} -autoabils[1690] = {name='Shock Absorber', recast=180} -autoabils[1691] = {name='Flashbulb', recast=45} -autoabils[1692] = {name='Mana Converter', recast=180} -autoabils[1755] = {name='Reactive Shield', recast=65} -autoabils[1765] = {name='Eraser', recast=30} -autoabils[1812] = {name='Economizer', recast=180} -autoabils[1876] = {name='Replicator', recast=60} -autoabils[2489] = {name='Heat Capacitator', recast=90} -autoabils[2490] = {name='Barrage Turbine', recast=180} -autoabils[2491] = {name='Disruptor', recast=60} - -str = 'Fire: \\cs(${colFire|255,255,255})${Fire|0}\\cr - ${timeFire|0}s - ${olFire|0}%' -str = str..'\nIce: \\cs(${colIce|255,255,255})${Ice|0}\\cr - ${timeIce|0}s - ${olIce|0}%' -str = str..'\nWind: \\cs(${colWind|255,255,255})${Wind|0}\\cr - ${timeWind|0}s - ${olWind|0}%' -str = str..'\nEarth: \\cs(${colEarth|255,255,255})${Earth|0}\\cr - ${timeEarth|0}s - ${olEarth|0}%' -str = str..'\nThunder: \\cs(${colThunder|255,255,255})${Thunder|0}\\cr - ${timeThunder|0}s - ${olThunder|0}%' -str = str..'\nWater: \\cs(${colWater|255,255,255})${Water|0}\\cr - ${timeWater|0}s - ${olWater|0}%' -str = str..'\nLight: \\cs(${colLight|255,255,255})${Light|0}\\cr - ${timeLight|0}s - ${olLight|0}%' -str = str..'\nDark: \\cs(${colDark|255,255,255})${Dark|0}\\cr - ${timeDark|0}s - ${olDark|0}%' - -Burden_tb = texts.new(str, settings) - -windower.register_event("action", function(act) - if mjob_id == 18 then - local abil_ID = act['param'] - local actor_id = act['actor_id'] - local player = T(windower.ffxi.get_player()) - local pet_index = windower.ffxi.get_mob_by_id(windower.ffxi.get_player()['id'])['pet_index'] - - if act['category'] == 6 and actor_id == player.id and S{136,139,141,142,143,144,145,146,147,148,309,310}:contains(abil_ID) then - if S{141, 142, 143, 144, 145, 146, 147, 148}:contains(abil_ID) and maneuvertimers then - windower.send_command('timers c "Maneuver: '..maneuver..'" 60 down') - if maneuver > 2 then - maneuver = 1 - else - maneuver = maneuver + 1 - end - end - if abil_ID == 141 then - lastMan = 'Fire' - heatupdate('Fire',1) - elseif abil_ID == 142 then - lastMan = 'Ice' - heatupdate('Ice',1) - elseif abil_ID == 143 then - lastMan = 'Wind' - heatupdate('Wind',1) - elseif abil_ID == 144 then - lastMan = 'Earth' - heatupdate('Earth',1) - elseif abil_ID == 145 then - lastMan = 'Thunder' - heatupdate('Thunder',1) - elseif abil_ID == 146 then - lastMan = 'Water' - heatupdate('Water',1) - elseif abil_ID == 147 then - lastMan = 'Light' - heatupdate('Light',1) - elseif abil_ID == 148 then - lastMan = 'Dark' - heatupdate('Dark',1) - elseif abil_ID == 309 then - windower.send_command('@timers d Overloaded!') - heatupdate() - elseif abil_ID == 136 or abil_ID == 310 then -- Activate or Deus Ex Automata - if settings.burdentracker then - Burden_tb:show() - end - decay = get_decay() - activate_burden() - elseif abil_ID == 139 then - zero_all() - windower.send_command('@timers d Overloaded!') - text_update_loop('stop') - Burden_tb:hide() - end - elseif S{1688,1689,1690,1691,1692,1755,1765,1812,1876,2489,2490,2491}:contains(abil_ID-256) - and windower.ffxi.get_mob_by_id(actor_id)['index'] == pet_index - and pet_index ~= nil then - local abil = abil_ID - 256 - windower.send_command('@timers c "'..autoabils[abil].name..'" '..autoabils[abil].recast..' up') - end - - end -end) - -function heatupdate(element, maneuver) - if mjob_id == 18 then - local first = false - if maneuver ~= nil and element ~= nil then - decay = get_decay() - threshold = get_threshold() - if heat[element] == 0 then first = true end - heat[element] = heat[element] + get_jaheat() - - if heat[element] >= threshold then - Burden_tb['col'..element] = '255,0,255' - else - Burden_tb['col'..element] = '255,255,255' - end - Burden_tb[element] = heat[element] - timer[element] = math.ceil(heat[element]/decay)*3 - Burden_tb['time'..element] = math.round(timer[element]) - local tempol = (.05+(.01*(heat[element]-threshold)))*100 - if tempol < 0 or heat[element] < threshold then tempol = 0 end - Burden_tb['ol'..element] = tempol - if first then timer_start(element) end - else - for key,_ in pairs(timer) do - heat[key] = math.round(heat[key]/2) - Burden_tb[key] = heat[key] - timer[key] = math.ceil(heat[key]/decay)*3 - Burden_tb['time'..key] = math.round(timer[key]) - local tempol = (.05+(.01*(heat[key]-threshold)))*100 - if tempol < 0 or heat[key] < threshold then tempol = 0 end - Burden_tb['ol'..key] = tempol - end - end - end -end - -function get_decay() - if mjob_id == 18 then - local newdecay - if T(windower.ffxi.get_mjob_data().attachments):contains(8610) then - local mans = 0 - local buffs = windower.ffxi.get_player().buffs - for z = 1, #buffs do - if buffs[z] == 305 then - mans = mans + 1 - end - end - if mans == 3 then newdecay = 6 - elseif mans == 2 then newdecay = 5 - elseif mans == 1 then newdecay = 4 - else newdecay = 2 - end - else - newdecay = 1 - end - return newdecay - end -end - -function get_jaheat() - if mjob_id == 18 then - local baseheat = 20 - local updatedheat = 0 - local bonusheat = 0 - if T(windower.ffxi.get_mjob_data()['attachments']):contains(8485) then - local mans = 0 - local buffs = windower.ffxi.get_player()['buffs'] - for z = 1, #buffs do - if buffs[z] == 301 then - mans = mans + 1 - end - end - if mans == 3 then bonusheat = 10 - elseif mans == 2 then bonusheat = 9 - elseif mans == 1 then bonusheat = 8 - else bonusheat = 3 - end - end - updatedheat = baseheat + bonusheat - return updatedheat - end -end - -function get_threshold() - if mjob_id == 18 then - local newthreshold = 0 - local basethreshold = 30 - local items = windower.ffxi.get_items() - local bonus = 0 - local slots = {'hands', 'body', 'neck', 'back'} - for i, s in ipairs(slots) do - if items.equipment[s] ~= 0 then - local item = threshItems[items.inventory[items.equipment[s]].id] or threshItems[items.wardrobe[items.equipment[s]].id] - if item ~= nil then - bonus = bonus + item - end - end - end - newthreshold = basethreshold + bonus - return newthreshold - end -end - -function update_element(ele) - if mjob_id == 18 then - heat[ele] = heat[ele] - decay - if heat[ele] < 0 then heat[ele] = 0 end - - if heat[ele] > threshold then - Burden_tb['col'..ele] = '255,0,255' - else - Burden_tb['col'..ele] = '255,255,255' - end - Burden_tb[ele] = heat[ele] - timer[ele] = math.ceil(heat[ele]/decay)*3 - Burden_tb['time'..ele] = math.round(timer[ele]) - local tempol = (.05+(.01*(heat[ele]-threshold)))*100 - if tempol < 0 or heat[ele] < threshold then tempol = 0 end - Burden_tb['ol'..ele] = tempol - if heat[ele] > 0 then - windower.send_command('@wait 3;lua i autocontrol update_element '..ele) - end - end -end - -function activate_burden() - if mjob_id == 18 then - threshold = 30 - for key, _ in pairs(heat) do - heat[key] = 35 - Burden_tb[key] = 35 - - if heat[key] > threshold then - Burden_tb['col'..key] = '255,0,255' - else - Burden_tb['col'..key] = '255,255,255' - end - timer[key] = math.ceil(35/decay) * 3 - Burden_tb['time'..key] = math.round(timer[key]) - local tempol = (.05+(.01*(heat[key]-threshold)))*100 - if tempol < 0 or heat[key] < threshold then tempol = 0 end - Burden_tb['ol'..key] = tempol - - windower.send_command('lua i autocontrol timer_start '..key) - end - if running ~= 1 then text_update() end - end -end - -function text_update() - if mjob_id == 18 then - Burden_tb:update() - windower.send_command('@wait 1;lua i autocontrol text_update_loop start') - running = 1 - end -end - -function text_update_loop(str) - if mjob_id == 18 then - if str == 'start' and running == 1 and not petlessZones:contains(windower.ffxi.get_info().zone) then - for key, _ in pairs(heat) do - timer[key] = timer[key] - 1 - if timer[key] < 1 then timer[key] = 0 end - - if heat[key] > threshold then - Burden_tb['col'..key] = '255,0,255' - else - Burden_tb['col'..key] = '255,255,255' - end - Burden_tb['time'..key] = timer[key] - local tempol = (.05+(.01*(heat[key]-threshold)))*100 - if tempol < 0 or heat[key] < threshold then tempol = 0 end - Burden_tb['ol'..key] = tempol - end - Burden_tb:update() - - local player_mob = windower.ffxi.get_mob_by_id(windower.ffxi.get_player()['id']) - if player_mob then - if player_mob['pet_index'] - and player_mob['pet_index'] ~= 0 then - windower.send_command('@wait 1;lua i autocontrol text_update_loop start') - running = 1 - end - end - elseif str == 'stop' then running = 0 end - end -end - -windower.register_event('gain buff', function(id) - if mjob_id == 18 then - if id == 305 then - decay = get_decay() - end - if id == 299 then - windower.send_command('@timers c Overloaded! '..heat[lastMan]-threshold..' down') - end - end -end) - -windower.register_event('lose buff', function(id) - if mjob_id == 18 then - if id == 305 then - decay = get_decay() - end - if id == 299 then - windower.send_command('@timers d Overloaded!') - end - end -end) - -function timer_start(ele) - if mjob_id == 18 then - windower.send_command('@wait 3;lua i autocontrol update_element '..ele) - end -end - -windower.register_event('job change', function(mj) - mjob_id = mj - if mjob_id ~= 18 or petlessZones:contains(windower.ffxi.get_info().zone) then - Burden_tb:hide() - text_update_loop('stop') - end -end) - -function zero_all() - for key,val in pairs(heat) do - Burden_tb[key] = 0 - timer[key] = 0 - Burden_tb['time'..key] = 0 - Burden_tb['col'..key] = '255,255,255' - Burden_tb['ol'..key] = tempol - end -end - -function zone_check(to) - to = tonumber(to) - if mjob_id == 18 then - if petlessZones:contains(to) then - text_update_loop('stop') - zero_all() - Burden_tb:hide() - return - else - local player_mob = windower.ffxi.get_mob_by_target('me') - if player_mob then - if player_mob.pet_index - and player_mob.pet_index ~= 0 then - if settings.burdentracker then - Burden_tb:show() - end - activate_burden() - end - else - windower.send_command('@wait 10;lua i autocontrol zone_check ' .. to) - end - end - end -end - -windower.register_event('zone change', zone_check) - -windower.register_event('time change', function() - if mjob_id == 18 then - decay = get_decay() - end -end) From 2d626d7faf03d07f3e3e960e7c2ee15d446fcbe7 Mon Sep 17 00:00:00 2001 From: Nifim Date: Sun, 22 Nov 2020 19:59:21 -0800 Subject: [PATCH 0509/1002] Add regulator to autoabils Regulator was missing from orignal table. --- addons/autocontrol/autoabils.lua | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/addons/autocontrol/autoabils.lua b/addons/autocontrol/autoabils.lua index 668942890d..32a0aca024 100644 --- a/addons/autocontrol/autoabils.lua +++ b/addons/autocontrol/autoabils.lua @@ -1,16 +1,17 @@ autoabils = { - [1688] = {name='Shield Bash', recast=180, icon="00210"}, - [1689] = {name='Strobe', recast=30, icon="00210"}, - [1690] = {name='Shock Absorber', recast=180, icon="00210"}, - [1691] = {name='Flashbulb', recast=45, icon="00210"}, - [1692] = {name='Mana Converter', recast=180, icon="00210"}, - [1755] = {name='Reactive Shield', recast=65, icon="00210"}, - [1765] = {name='Eraser', recast=30, icon="00210"}, - [1812] = {name='Economizer', recast=180, icon = "00210"}, - [1876] = {name='Replicator', recast=60, icon = "00210"}, - [2489] = {name='Heat Capacitator', recast=90, icon = "00210"}, - [2490] = {name='Barrage Turbine', recast=180, icon = "00210"}, - [2491] = {name='Disruptor', recast=60, icon = "00210"}, + [1688] = {name = 'Shield Bash', recast = 180, icon = "00210"}, + [1689] = {name = 'Strobe', recast = 30, icon = "00210"}, + [1690] = {name = 'Shock Absorber', recast = 180, icon = "00210"}, + [1691] = {name = 'Flashbulb', recast = 45, icon = "00210"}, + [1692] = {name = 'Mana Converter', recast = 180, icon = "00210"}, + [1755] = {name = 'Reactive Shield', recast = 65, icon = "00210"}, + [1765] = {name = 'Eraser', recast = 30, icon = "00210"}, + [1812] = {name = 'Economizer', recast = 180, icon = "00210"}, + [1876] = {name = 'Replicator', recast = 60, icon = "00210"}, + [2489] = {name = 'Heat Capacitator', recast = 90, icon = "00210"}, + [2490] = {name = 'Barrage Turbine', recast = 180, icon = "00210"}, + [2491] = {name = 'Disruptor', recast = 60, icon = "00210"}, + [3485] = {name = 'Regulator', recast = 60, icon = "00210" } } attachments_to_abilities = { [8225] = 1688, From 2874d4666639e248c01c036503b5d11c536d7b04 Mon Sep 17 00:00:00 2001 From: Nifim Date: Sun, 22 Nov 2020 20:09:02 -0800 Subject: [PATCH 0510/1002] Update autoabils.lua Add a missing local to a variable. Add comment for timer creation/deletion --- addons/autocontrol/autoabils.lua | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/addons/autocontrol/autoabils.lua b/addons/autocontrol/autoabils.lua index 32a0aca024..50d84f0002 100644 --- a/addons/autocontrol/autoabils.lua +++ b/addons/autocontrol/autoabils.lua @@ -34,24 +34,27 @@ attachments_to_abilities = { } local player_id = windower.ffxi.get_player().id + windower.register_event("action", function(act) local abil_ID = act['param'] local actor_id = act['actor_id'] local pet_index = windower.ffxi.get_mob_by_id(player_id)['pet_index'] if act['category'] == 6 and actor_id == player_id and (abil_ID == 136 or abil_ID == 310 or abil_ID == 139) then - avalible_abilities = {} + local avalible_abilities = {} local automaton = windower.ffxi.get_mjob_data() + if attachments_to_abilities[automaton.frame] then table.insert(avalible_abilities, autoabils[attachments_to_abilities[automaton.frame]]) end + for _, id in pairs(automaton.attachments) do if attachments_to_abilities[id] then table.insert(avalible_abilities, autoabils[attachments_to_abilities[id]]) end end - for _, ability in pairs(avalible_abilities) do + for _, ability in pairs(avalible_abilities) do -- if abil_ID is deactivate delete ability timers, otherwise create them. windower.send_command('timers '.. (abil_ID == 139 and "d" or "c") .. ' "'..ability.name..'" ' .. (abil_ID == 139 and "" or ability.recast..' up abilities/' .. ability.icon)) end elseif autoabils[abil_ID-256] and windower.ffxi.get_mob_by_id(actor_id)['index'] == pet_index and pet_index ~= nil then From 3c24ec3929d85b8665abc01aefabd49a77fdad1d Mon Sep 17 00:00:00 2001 From: dtw <362017+dtw@users.noreply.github.com> Date: Mon, 23 Nov 2020 09:15:14 +0000 Subject: [PATCH 0511/1002] Fix player.pet_index This always returns nil --- addons/autocontrol/autocontrol.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/autocontrol/autocontrol.lua b/addons/autocontrol/autocontrol.lua index 8438e51040..dac5b2787d 100644 --- a/addons/autocontrol/autocontrol.lua +++ b/addons/autocontrol/autocontrol.lua @@ -83,9 +83,9 @@ function initialize() mjob_id = player.main_job_id atts = res.items:category('Automaton') - + local playermob = windower.ffxi.get_mob_by_index(windower.ffxi.get_player().index) if mjob_id == 18 then - if player.pet_index then + if playermob.pet_index then if settings.burdentracker then burden_hud:show() end From 6835e213cb03b29aa332d6ca99c29dc2f8f015ca Mon Sep 17 00:00:00 2001 From: dtw <362017+dtw@users.noreply.github.com> Date: Mon, 23 Nov 2020 09:15:39 +0000 Subject: [PATCH 0512/1002] Update id to index Arcon said so --- addons/autocontrol/autocontrol.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/autocontrol/autocontrol.lua b/addons/autocontrol/autocontrol.lua index dac5b2787d..8ba1533d3a 100644 --- a/addons/autocontrol/autocontrol.lua +++ b/addons/autocontrol/autocontrol.lua @@ -104,8 +104,8 @@ function attach_set(autoset) return end - local playermob = windower.ffxi.get_mob_by_id(windower.ffxi.get_player().id) if playermob.pet_index and playermob.pet_index ~= 0 then + local playermob = windower.ffxi.get_mob_by_index(windower.ffxi.get_player().index) local recast = windower.ffxi.get_ability_recasts()[recast_ids.deactivate] if recast == 0 then windower.send_command('input /pet "Deactivate" ') From 41389c3120c9f50d887d3d7c08efec02d773ef0a Mon Sep 17 00:00:00 2001 From: Nifim Date: Mon, 23 Nov 2020 07:30:14 -0800 Subject: [PATCH 0513/1002] Insure `player_id` is updated register login event to update `player_id` --- addons/autocontrol/autoabils.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/addons/autocontrol/autoabils.lua b/addons/autocontrol/autoabils.lua index 50d84f0002..06cb8c8289 100644 --- a/addons/autocontrol/autoabils.lua +++ b/addons/autocontrol/autoabils.lua @@ -35,6 +35,10 @@ attachments_to_abilities = { local player_id = windower.ffxi.get_player().id +windower.register_event("login", function() + player_id = windower.ffxi.get_player().id +end) + windower.register_event("action", function(act) local abil_ID = act['param'] local actor_id = act['actor_id'] @@ -61,4 +65,4 @@ windower.register_event("action", function(act) local abil = abil_ID - 256 windower.send_command('@timers c "'..autoabils[abil].name..'" '..autoabils[abil].recast..' up') end -end) \ No newline at end of file +end) From 86748998f956efc6885c38293355a9503cea935a Mon Sep 17 00:00:00 2001 From: Nifim Date: Tue, 24 Nov 2020 07:38:29 -0800 Subject: [PATCH 0514/1002] Improve code for getting `pet_index` use `get_mob_by_index` rather than `get_mob_by_id` --- addons/autocontrol/burdometer.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/autocontrol/burdometer.lua b/addons/autocontrol/burdometer.lua index a7b528db89..c36f64517e 100644 --- a/addons/autocontrol/burdometer.lua +++ b/addons/autocontrol/burdometer.lua @@ -54,7 +54,7 @@ windower.register_event("action", function(act) local abil_id = act['param'] local actor_id = act['actor_id'] local player = windower.ffxi.get_player() - local pet_index = windower.ffxi.get_mob_by_id(windower.ffxi.get_player()['id'])['pet_index'] + local pet_index = windower.ffxi.get_mob_by_index(player.index).pet_index if player.main_job_id ~= 18 then return @@ -93,4 +93,4 @@ windower.register_event("lose buff", update_decay_rate) decay_event() -return hud \ No newline at end of file +return hud From cfa6e15318efdc3d948cf52906aa974cf202d432 Mon Sep 17 00:00:00 2001 From: Nifim Date: Sat, 5 Dec 2020 09:35:35 -0800 Subject: [PATCH 0515/1002] correct placement of playermob definition playermob was moved inside of an statement when it should be before that statement. --- addons/autocontrol/autocontrol.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/autocontrol/autocontrol.lua b/addons/autocontrol/autocontrol.lua index 8ba1533d3a..0d3806042d 100644 --- a/addons/autocontrol/autocontrol.lua +++ b/addons/autocontrol/autocontrol.lua @@ -103,9 +103,9 @@ function attach_set(autoset) log('The '..autoset..' set is already equipped.') return end - - if playermob.pet_index and playermob.pet_index ~= 0 then + local playermob = windower.ffxi.get_mob_by_index(windower.ffxi.get_player().index) + if playermob.pet_index and playermob.pet_index ~= 0 then local recast = windower.ffxi.get_ability_recasts()[recast_ids.deactivate] if recast == 0 then windower.send_command('input /pet "Deactivate" ') From 755d2a73ecf0356bad6cf4cf89679b5c1b4343b3 Mon Sep 17 00:00:00 2001 From: Nifim Date: Sun, 6 Dec 2020 18:54:29 -0800 Subject: [PATCH 0516/1002] Autocontrol fix logged out loading Fix issues when player/playermob is not avalible. --- addons/autocontrol/autoabils.lua | 2 +- addons/autocontrol/autocontrol.lua | 12 +++++++++--- addons/autocontrol/burden.lua | 18 +++++++++++------- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/addons/autocontrol/autoabils.lua b/addons/autocontrol/autoabils.lua index 06cb8c8289..f8d8ae3864 100644 --- a/addons/autocontrol/autoabils.lua +++ b/addons/autocontrol/autoabils.lua @@ -33,7 +33,7 @@ attachments_to_abilities = { [8682] = 3485, } -local player_id = windower.ffxi.get_player().id +local player_id windower.register_event("login", function() player_id = windower.ffxi.get_player().id diff --git a/addons/autocontrol/autocontrol.lua b/addons/autocontrol/autocontrol.lua index 0d3806042d..c380841408 100644 --- a/addons/autocontrol/autocontrol.lua +++ b/addons/autocontrol/autocontrol.lua @@ -1,5 +1,5 @@ --[[ -Copyright © 2013-2014, Ricky Gall +Copyright © 2013, 2014, 2020 Ricky Gall, Nifim All rights reserved. Redistribution and use in source and binary forms, with or without @@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] _addon.name = 'autocontrol' -_addon.version = '2.0' +_addon.version = '2.0.1' _addon.author = 'Nitrous (Shiva)' _addon.commands = {'autocontrol','acon'} @@ -83,7 +83,13 @@ function initialize() mjob_id = player.main_job_id atts = res.items:category('Automaton') - local playermob = windower.ffxi.get_mob_by_index(windower.ffxi.get_player().index) + + local playermob = windower.ffxi.get_mob_by_index(player.index) + while(playermob == nil) do + coroutine.sleep(1) + playermob = windower.ffxi.get_mob_by_index(player.index) + end + if mjob_id == 18 then if playermob.pet_index then if settings.burdentracker then diff --git a/addons/autocontrol/burden.lua b/addons/autocontrol/burden.lua index 2ca46335d9..1d480edcfe 100644 --- a/addons/autocontrol/burden.lua +++ b/addons/autocontrol/burden.lua @@ -1,4 +1,5 @@ local set = require("sets") +local packets = require("packets") local o = { fire = 0, @@ -17,12 +18,17 @@ local mt = { setmetatable(o, mt) local updaters = {} local heatsink -for _, id in pairs(windower.ffxi.get_mjob_data().attachments) do - heatsink = (id == 8610) - if heatsink then - break + +windower.register_event('incoming chunk',function(id,org,modi,is_injected,is_blocked) + if id == 0x044 then + for _, id in pairs(windower.ffxi.get_mjob_data().attachments) do + heatsink = (id == 8610) + if heatsink then + break + end + end end -end +end) local thresholdModifiers = { @@ -162,11 +168,9 @@ local count_to_decay_rate = { [3] = 6, } function burden.update_decay_rate() - print(heatsink) if heatsink then local count = 0 for _, v in pairs(windower.ffxi.get_player().buffs) do - print(v) if v == 305 then count = count + 1 end From 30ad2938529da3755b270c7ae82822571be2ff03 Mon Sep 17 00:00:00 2001 From: Nifim Date: Mon, 7 Dec 2020 12:56:03 -0800 Subject: [PATCH 0517/1002] Fix issue when job is not pup Check if `attachments` table is `nil` --- addons/autocontrol/burden.lua | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/addons/autocontrol/burden.lua b/addons/autocontrol/burden.lua index 1d480edcfe..d997e8e86e 100644 --- a/addons/autocontrol/burden.lua +++ b/addons/autocontrol/burden.lua @@ -21,10 +21,13 @@ local heatsink windower.register_event('incoming chunk',function(id,org,modi,is_injected,is_blocked) if id == 0x044 then - for _, id in pairs(windower.ffxi.get_mjob_data().attachments) do - heatsink = (id == 8610) - if heatsink then - break + attachments = windower.ffxi.get_mjob_data().attachments + if attachements then + for _, id in pairs(attachements) do + heatsink = (id == 8610) + if heatsink then + break + end end end end From f91b6780c03c3562e8f1ec245583c995a31c19de Mon Sep 17 00:00:00 2001 From: Nifim Date: Mon, 7 Dec 2020 13:05:01 -0800 Subject: [PATCH 0518/1002] burden.lua fix typo * correct `attachements` to `attachments` * add `local` to `attachments` definition --- addons/autocontrol/burden.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/autocontrol/burden.lua b/addons/autocontrol/burden.lua index d997e8e86e..26ec253587 100644 --- a/addons/autocontrol/burden.lua +++ b/addons/autocontrol/burden.lua @@ -21,9 +21,9 @@ local heatsink windower.register_event('incoming chunk',function(id,org,modi,is_injected,is_blocked) if id == 0x044 then - attachments = windower.ffxi.get_mjob_data().attachments - if attachements then - for _, id in pairs(attachements) do + local attachments = windower.ffxi.get_mjob_data().attachments + if attachments then + for _, id in pairs(attachments) do heatsink = (id == 8610) if heatsink then break From 7700d85fcfa45f5049724dec2582a86a4d41aa94 Mon Sep 17 00:00:00 2001 From: Nifim Date: Mon, 7 Dec 2020 13:06:09 -0800 Subject: [PATCH 0519/1002] autocontrol bump revision --- addons/autocontrol/autocontrol.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/autocontrol/autocontrol.lua b/addons/autocontrol/autocontrol.lua index c380841408..6d01482d6b 100644 --- a/addons/autocontrol/autocontrol.lua +++ b/addons/autocontrol/autocontrol.lua @@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] _addon.name = 'autocontrol' -_addon.version = '2.0.1' +_addon.version = '2.0.2' _addon.author = 'Nitrous (Shiva)' _addon.commands = {'autocontrol','acon'} From e403df5bd0b182f877a672f97509b93e71ba93f2 Mon Sep 17 00:00:00 2001 From: Nifim Date: Mon, 7 Dec 2020 13:07:02 -0800 Subject: [PATCH 0520/1002] Update version on readme.md --- addons/autocontrol/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/autocontrol/readme.md b/addons/autocontrol/readme.md index e9cd100251..ab9664226b 100644 --- a/addons/autocontrol/readme.md +++ b/addons/autocontrol/readme.md @@ -1,5 +1,5 @@ **Author:** Ricky Gall -**Version:** 0.21 +**Version:** 2.0.2 **Description:** Addon to make setting automaton attachments easier. Currently only works as pup main. Includes burden tracker. From ad2efe6f22848cadb078aea2f09f6d534e657683 Mon Sep 17 00:00:00 2001 From: Nifim Date: Mon, 7 Dec 2020 13:46:28 -0800 Subject: [PATCH 0521/1002] Autocontrol: Add load event to autoabils.lua `player_id` was nil if addon was loaded after login event. --- addons/autocontrol/autoabils.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/addons/autocontrol/autoabils.lua b/addons/autocontrol/autoabils.lua index f8d8ae3864..50f087fe41 100644 --- a/addons/autocontrol/autoabils.lua +++ b/addons/autocontrol/autoabils.lua @@ -39,6 +39,11 @@ windower.register_event("login", function() player_id = windower.ffxi.get_player().id end) +windower.register_event("load", function() + local player = windower.ffxi.get_player() + player_id = player and player.id +end) + windower.register_event("action", function(act) local abil_ID = act['param'] local actor_id = act['actor_id'] From 4fba7a93d65470345931ef17bca8a3cf3543b45a Mon Sep 17 00:00:00 2001 From: Nifim Date: Mon, 7 Dec 2020 13:48:18 -0800 Subject: [PATCH 0522/1002] bump version --- addons/autocontrol/autocontrol.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/autocontrol/autocontrol.lua b/addons/autocontrol/autocontrol.lua index 6d01482d6b..5d936a7664 100644 --- a/addons/autocontrol/autocontrol.lua +++ b/addons/autocontrol/autocontrol.lua @@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] _addon.name = 'autocontrol' -_addon.version = '2.0.2' +_addon.version = '2.0.3' _addon.author = 'Nitrous (Shiva)' _addon.commands = {'autocontrol','acon'} From fe2b38943edf3a383c65ab4cf0ebd9b56f687ef2 Mon Sep 17 00:00:00 2001 From: Nifim Date: Mon, 7 Dec 2020 13:49:19 -0800 Subject: [PATCH 0523/1002] Bump revision --- addons/autocontrol/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/autocontrol/readme.md b/addons/autocontrol/readme.md index ab9664226b..f322b42185 100644 --- a/addons/autocontrol/readme.md +++ b/addons/autocontrol/readme.md @@ -1,5 +1,5 @@ **Author:** Ricky Gall -**Version:** 2.0.2 +**Version:** 2.0.3 **Description:** Addon to make setting automaton attachments easier. Currently only works as pup main. Includes burden tracker. From 77b2c8475dad41cc8d35a5a945bfa8cacf81c53a Mon Sep 17 00:00:00 2001 From: Nifim Date: Mon, 7 Dec 2020 20:36:12 -0800 Subject: [PATCH 0524/1002] autocontrol hide burden display * hide burden display when job is not pup. * remove debug `add_to_chat` statement --- addons/autocontrol/autoabils.lua | 2 +- addons/autocontrol/autocontrol.lua | 10 +++++++++- addons/autocontrol/burden.lua | 1 - addons/autocontrol/readme.md | 2 +- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/addons/autocontrol/autoabils.lua b/addons/autocontrol/autoabils.lua index 50f087fe41..ea44bdc780 100644 --- a/addons/autocontrol/autoabils.lua +++ b/addons/autocontrol/autoabils.lua @@ -70,4 +70,4 @@ windower.register_event("action", function(act) local abil = abil_ID - 256 windower.send_command('@timers c "'..autoabils[abil].name..'" '..autoabils[abil].recast..' up') end -end) +end) diff --git a/addons/autocontrol/autocontrol.lua b/addons/autocontrol/autocontrol.lua index 5d936a7664..0481649da0 100644 --- a/addons/autocontrol/autocontrol.lua +++ b/addons/autocontrol/autocontrol.lua @@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] _addon.name = 'autocontrol' -_addon.version = '2.0.3' +_addon.version = '2.0.4' _addon.author = 'Nitrous (Shiva)' _addon.commands = {'autocontrol','acon'} @@ -295,3 +295,11 @@ windower.register_event('addon command', function(comm, ...) log(' show/hide - toggles visibility of the tracker so you can make changes.') end end) + +windower.register_event("job change", function(main_job_id) + if main_job_id == 18 and settings.burdentracker then + burden_hud:show() + else + burden_hud:hide() + end +end) diff --git a/addons/autocontrol/burden.lua b/addons/autocontrol/burden.lua index 26ec253587..fe83dfd054 100644 --- a/addons/autocontrol/burden.lua +++ b/addons/autocontrol/burden.lua @@ -136,7 +136,6 @@ function updaters.maneuver(self, type) burden.threshold = burden.threshold + thresholdModifiers[item.id] end end - windower.add_to_chat(4, self[type]) end function updaters.ice(self) updaters.maneuver(self, "ice") end diff --git a/addons/autocontrol/readme.md b/addons/autocontrol/readme.md index f322b42185..eb14bce0ed 100644 --- a/addons/autocontrol/readme.md +++ b/addons/autocontrol/readme.md @@ -1,5 +1,5 @@ **Author:** Ricky Gall -**Version:** 2.0.3 +**Version:** 2.0.4 **Description:** Addon to make setting automaton attachments easier. Currently only works as pup main. Includes burden tracker. From 1ae26a5838d1ca2bfb2b630655d6fb0a929db246 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Thu, 10 Dec 2020 00:58:16 -0500 Subject: [PATCH 0525/1002] Dec 9th, 2020 Update --- addons/boxdestroyer/messages.lua | 48 ++++++++++++++++---------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/addons/boxdestroyer/messages.lua b/addons/boxdestroyer/messages.lua index 90083cc792..24216e7dae 100644 --- a/addons/boxdestroyer/messages.lua +++ b/addons/boxdestroyer/messages.lua @@ -1,31 +1,31 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination" for the associated zone IDs - [100] = 8056, + [100] = 8074, [101] = 7505, - [102] = 7907, - [103] = 8082, - [104] = 8647, - [105] = 7698, - [106] = 8072, - [107] = 7533, - [108] = 7602, - [109] = 8465, - [110] = 7589, - [111] = 8566, - [112] = 8168, + [102] = 7925, + [103] = 8100, + [104] = 8665, + [105] = 7716, + [106] = 8090, + [107] = 7551, + [108] = 7620, + [109] = 8483, + [110] = 7607, + [111] = 8584, + [112] = 8186, [113] = 7928, - [114] = 7767, - [115] = 7863, - [116] = 7559, - [117] = 7566, - [118] = 8108, - [119] = 8345, - [120] = 7505, - [121] = 8085, + [114] = 7785, + [115] = 7881, + [116] = 7577, + [117] = 7584, + [118] = 8126, + [119] = 8363, + [120] = 7523, + [121] = 8103, [122] = 7434, - [123] = 7868, - [124] = 7819, - [125] = 7629, - [126] = 8052, + [123] = 7886, + [124] = 7837, + [125] = 7647, + [126] = 8070, [127] = 7351, [128] = 7506, [130] = 7570, From fe7d79686c4c492d4078acce64513cfd0c601cc7 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Fri, 11 Dec 2020 12:54:54 -0500 Subject: [PATCH 0526/1002] New Trust: Matsui-P --- addons/Trusts/Trusts.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/Trusts/Trusts.lua b/addons/Trusts/Trusts.lua index ca911df186..1664af2e67 100644 --- a/addons/Trusts/Trusts.lua +++ b/addons/Trusts/Trusts.lua @@ -369,4 +369,5 @@ trusts = T{ [119]={id=1019,japanese="シャントットII",english="Shantotto II",name="Shantotto",models=3110}, -- [120]={id=1003,japanese="コーネリア",english="Cornelia",name="Cornelia",models=3119}, --goodbye, my love [121]={id=999,japanese="モンブロー",english="Monberaux",name="Monberaux",models=3120}, + [122]={id=1003,japanese="マツイP",english="Matsui-P",name="Matsui-P",models=3121}, } From 0c76bb2078e1bfc9fc161a6fd2f9576b195ad174 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Fri, 11 Dec 2020 12:56:35 -0500 Subject: [PATCH 0527/1002] Tab ohno --- addons/Trusts/Trusts.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/Trusts/Trusts.lua b/addons/Trusts/Trusts.lua index 1664af2e67..11e9c6de7f 100644 --- a/addons/Trusts/Trusts.lua +++ b/addons/Trusts/Trusts.lua @@ -369,5 +369,5 @@ trusts = T{ [119]={id=1019,japanese="シャントットII",english="Shantotto II",name="Shantotto",models=3110}, -- [120]={id=1003,japanese="コーネリア",english="Cornelia",name="Cornelia",models=3119}, --goodbye, my love [121]={id=999,japanese="モンブロー",english="Monberaux",name="Monberaux",models=3120}, - [122]={id=1003,japanese="マツイP",english="Matsui-P",name="Matsui-P",models=3121}, + [122]={id=1003,japanese="マツイP",english="Matsui-P",name="Matsui-P",models=3121}, } From b5d6d825f409fac32175e034bd28afe59fbf31a2 Mon Sep 17 00:00:00 2001 From: Nifim Date: Mon, 14 Dec 2020 19:51:37 -0800 Subject: [PATCH 0528/1002] Correct `count_to_rate` to `count_to_decay_rate` --- addons/autocontrol/burden.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/autocontrol/burden.lua b/addons/autocontrol/burden.lua index fe83dfd054..51a8136a36 100644 --- a/addons/autocontrol/burden.lua +++ b/addons/autocontrol/burden.lua @@ -177,7 +177,7 @@ function burden.update_decay_rate() count = count + 1 end end - burden.decay_rate = count_to_rate[count]; + burden.decay_rate = count_to_decay_rate[count]; else burden.decay_rate = 1 end From 17f591b7b511f599e6b6b3a3c06b1d67a0daeaec Mon Sep 17 00:00:00 2001 From: Nifim Date: Mon, 14 Dec 2020 19:55:11 -0800 Subject: [PATCH 0529/1002] Bump autocontrol version 2.0.5 --- addons/autocontrol/autocontrol.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/autocontrol/autocontrol.lua b/addons/autocontrol/autocontrol.lua index 0481649da0..3c0d51c2cf 100644 --- a/addons/autocontrol/autocontrol.lua +++ b/addons/autocontrol/autocontrol.lua @@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] _addon.name = 'autocontrol' -_addon.version = '2.0.4' +_addon.version = '2.0.5' _addon.author = 'Nitrous (Shiva)' _addon.commands = {'autocontrol','acon'} From 8bd4bc1e14c8979ff9b10d11fad0f5004a2bb70b Mon Sep 17 00:00:00 2001 From: Chiaia Date: Sun, 27 Dec 2020 01:54:52 -0500 Subject: [PATCH 0530/1002] wardrobe 2-4 --- .../Variables.xlsx | Bin 32911 -> 32990 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/addons/GearSwap/beta_examples_and_information/Variables.xlsx b/addons/GearSwap/beta_examples_and_information/Variables.xlsx index ebc19916e99db35d34f923f02822e6eaf387a170..e5846c12082a1a3fa34904403552e3c17f508d2b 100644 GIT binary patch delta 23211 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

  • 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 PMU%9EBnHQP000001IT>F From 94302a4030c54bdfbcba5565d51b18715324ec8b Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Mon, 28 Dec 2020 16:22:47 -0700 Subject: [PATCH 0531/1002] Fix use of quotes in `gs equip` and exit loop properly This is intended to allow quotes to be omitted when using brackets`[]` in the equip command. This allows the command to function properly when double quites are used. The following should now all work: gs equip precast.WS["Rudra's Storm"] gs equip precast.WS['Rudra's Storm'] gs equip precast.WS[Rudra's Storm] gs equip precast.WS.Rudra's Storm While I'm at it, the function also would only ever exit after 30 iterations. This is now fixed. --- addons/GearSwap/helper_functions.lua | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/addons/GearSwap/helper_functions.lua b/addons/GearSwap/helper_functions.lua index d15bae3301..2fc8a11d0a 100644 --- a/addons/GearSwap/helper_functions.lua +++ b/addons/GearSwap/helper_functions.lua @@ -42,6 +42,7 @@ function string.lower(message) end end + ----------------------------------------------------------------------------------- --Name: string.upper() --Args: @@ -359,7 +360,7 @@ function parse_set_to_keys(str) local count = 0 -- Loop as long as remainder hasn't been nil'd or reduced to 0 characters, but only to a maximum of 30 tries. - while remainder and #remainder and count < 30 do + while remainder ~= "" and count < 30 do -- Try aaa.bbb set names first while sep == '.' do _,_,key,sep,remainder = remainder:find("^([^%.%[]*)(%.?%[?)(.*)") @@ -380,7 +381,8 @@ function parse_set_to_keys(str) _,_,key,stop,sep,remainder = remainder:find("^([^']+)('])(%.?%[?)(.*)") elseif sep == '"' then _,_,key,stop,sep,remainder = remainder:find('^([^"]+)("])(%.?%[?)(.*)') - elseif not sep or #sep == 0 then + end + if not sep or #sep == 0 then -- If there is no single or double quote detected, attempt to treat the index as a number or boolean local _,_,pot_key,pot_stop,pot_sep,pot_remainder = remainder:find('^([^%]]+)(])(%.?%[?)(.*)') if tonumber(pot_key) then @@ -389,6 +391,8 @@ function parse_set_to_keys(str) key,stop,sep,remainder = true,pot_stop,pot_sep,pot_remainder elseif pot_key == 'false' then key,stop,sep,remainder = false,pot_stop,pot_sep,pot_remainder + elseif pot_key and pot_key ~= "" then + key,stop,sep,remainder = pot_key,pot_stop,pot_sep,pot_remainder end end result:append(key) @@ -400,6 +404,7 @@ function parse_set_to_keys(str) return result end + ----------------------------------------------------------------------------------- ----Name: get_set_from_keys(keys) -- Function to take a list of keys select the set they point to, if possible. @@ -427,7 +432,6 @@ function get_set_from_keys(keys) end - ----------------------------------------------------------------------------------- --Name: initialize_arrow_offset(mob_table) --Desc: Returns the current target arrow offset. @@ -452,7 +456,6 @@ function initialize_arrow_offset(mob_table) end - ----------------------------------------------------------------------------------- --Name: assemble_action_packet(target_id,target_index,category,spell_id) --Desc: Puts together an "action" packet (0x1A) @@ -566,6 +569,7 @@ function assemble_menu_item_packet(target_id,target_index,...) return outstr end + ----------------------------------------------------------------------------------- --Name: find_inventory_item(item_id) --Desc: Finds a npc trade item in normal inventory. Assumes items array @@ -585,6 +589,7 @@ function find_inventory_item(item_id) end end + ----------------------------------------------------------------------------------- --Name: find_usable_item(item_id,bool) --Desc: Finds a usable item in temporary or normal inventory. Assumes items array @@ -596,7 +601,6 @@ end ---- inventory_index - The item's use inventory index (if it exists) ---- bag_id - The item's bag ID (if it exists) ----------------------------------------------------------------------------------- - function find_usable_item(item_id) for _,bag in ipairs(usable_item_bags) do for i,v in pairs(items[to_windower_bag_api(bag.en)]) do From 6426cd0b78197465d58c4ba8b5e34f8531a9806c Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Thu, 31 Dec 2020 00:33:50 +0000 Subject: [PATCH 0532/1002] Adding Chaosbringer Adding Chaosbringer to the list of checkable weapons (DRK flag quest weapon) --- addons/latentchecker/latentchecker.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/latentchecker/latentchecker.lua b/addons/latentchecker/latentchecker.lua index 5b339ce761..354ad77f93 100644 --- a/addons/latentchecker/latentchecker.lua +++ b/addons/latentchecker/latentchecker.lua @@ -68,7 +68,7 @@ windower.register_event('addon command', function(command, ...) "werebuster","mage's staff","vorpal sword","swordbreaker","brave blade","death sickle","double axe","dancing dagger","killer bow","windslicer", "sasuke katana","radiant lance","scepter staff","wightslayer","quicksilver","inferno claws","main gauche","elder staff","destroyers","senjuinrikio", "heart snatcher","subduer","dissector","expunger","morgenstern","gravedigger","rampager","coffinmaker","gonzo-shizunori","retributor","michishiba","thyrsusstab", - "trial wand","trial blade"} + "trial wand","trial blade","chaosbringer"} if command == 'run' then windower.add_to_chat(121,'latentchecker: Starting...') windower.ffxi.set_equip(0, 0, 0) -- Remove main/sub weapons From c70e4b3a271b7fc590fd1e2b7803a186bcbd607c Mon Sep 17 00:00:00 2001 From: Hadin1 <73416717+Hadin1@users.noreply.github.com> Date: Fri, 8 Jan 2021 21:04:06 -0500 Subject: [PATCH 0533/1002] Update slips.lua Added new items to Slip 22 --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index e295ea4ad8..214947bfdf 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757}, -- 191 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453,}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454,}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743}, -- 120 + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 25910, 54, 20571}, -- 120 [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745}, --171 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330,}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665,}, --115 From dda6ca35313d87ba408014b6afe775213d399a9a Mon Sep 17 00:00:00 2001 From: Chiaia Date: Thu, 14 Jan 2021 19:37:16 -0500 Subject: [PATCH 0534/1002] jan update changes --- addons/boxdestroyer/messages.lua | 116 +++++++++++++++---------------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/addons/boxdestroyer/messages.lua b/addons/boxdestroyer/messages.lua index 24216e7dae..de74eafbe5 100644 --- a/addons/boxdestroyer/messages.lua +++ b/addons/boxdestroyer/messages.lua @@ -1,61 +1,61 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination" for the associated zone IDs - [100] = 8074, - [101] = 7505, - [102] = 7925, - [103] = 8100, - [104] = 8665, - [105] = 7716, - [106] = 8090, - [107] = 7551, - [108] = 7620, - [109] = 8483, - [110] = 7607, - [111] = 8584, - [112] = 8186, - [113] = 7928, - [114] = 7785, - [115] = 7881, - [116] = 7577, - [117] = 7584, - [118] = 8126, - [119] = 8363, - [120] = 7523, - [121] = 8103, - [122] = 7434, - [123] = 7886, - [124] = 7837, - [125] = 7647, - [126] = 8070, - [127] = 7351, - [128] = 7506, - [130] = 7570, - [153] = 11396, - [158] = 7382, - [159] = 8445, - [160] = 7409, - [166] = 10578, - [167] = 10592, - [169] = 7539, - [172] = 7412, - [173] = 10517, - [174] = 11395, - [176] = 7604, - [177] = 11219, - [178] = 11399, - [190] = 8253, - [191] = 8373, - [192] = 7409, - [193] = 8385, - [194] = 8265, - [195] = 7596, - [196] = 8305, - [197] = 7350, - [198] = 8271, - [200] = 7527, - [204] = 7515, - [205] = 11482, - [208] = 8284, - [212] = 10638, - [213] = 10448, + [100] = 8075, + [101] = 7506, + [102] = 7926, + [103] = 8101, + [104] = 8666, + [105] = 7717, + [106] = 8091, + [107] = 7552, + [108] = 7621, + [109] = 8484, + [110] = 7608, + [111] = 8585, + [112] = 8187, + [113] = 7929, + [114] = 7786, + [115] = 7882, + [116] = 7578, + [117] = 7585, + [118] = 8127, + [119] = 8364, + [120] = 7524, + [121] = 8104, + [122] = 7435, + [123] = 7887, + [124] = 7838, + [125] = 7648, + [126] = 8071, + [127] = 7352, + [128] = 7507, + [130] = 7571, + [153] = 11397, + [158] = 7383, + [159] = 8446, + [160] = 7410, + [166] = 10579, + [167] = 10593, + [169] = 7540, + [172] = 7413, + [173] = 10518, + [174] = 11396, + [176] = 7605, + [177] = 11220, + [178] = 11400, + [190] = 8254, + [191] = 8374, + [192] = 7410, + [193] = 8386, + [194] = 8266, + [195] = 7597, + [196] = 8306, + [197] = 7351, + [198] = 8272, + [200] = 7528, + [204] = 7516, + [205] = 11483, + [208] = 8285, + [212] = 10639, + [213] = 10449, } offsets = {greater_less=1, failure=2, success=4, second_even_odd=5, first_even_odd=6, range=7, less=8, greater=9, equal=10, second_multiple=11, first_multiple=12, tool_failure=13} From 29d6a0eb2b470724c5dc22e27a8173baceb7da6f Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Fri, 22 Jan 2021 13:06:15 -0700 Subject: [PATCH 0535/1002] Mastery Rank Added Mastery Rank to 0x01B and an unknown/junk field to 0x061 --- addons/libs/packets/fields.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 18a1698cb6..c04907d5d3 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1467,6 +1467,8 @@ fields.incoming[0x01B] = L{ {ref=types.job_level, lookup={res.jobs, 0x01}, count=0x16}, -- 49 {ctype='unsigned char', label='Current Monster Level'}, -- 5F {ctype='unsigned int', label='Encumbrance Flags'}, -- 60 [legs, hands, body, head, ammo, range, sub, main,] [back, right_ring, left_ring, right_ear, left_ear, waist, neck, feet] [HP, CHR, MND, INT, AGI, VIT, DEX, STR,] [X X X X X X X MP] + {ctype='unsigned short', label='_unknown7'}, -- 64 + {ctype='unsigned short', label='Mastery Rank'}, -- 66 } -- Inventory Count @@ -2920,7 +2922,8 @@ fields.incoming[0x061] = L{ {ctype='bit[5]', label='Unity Rank'}, -- 58 Danger, 00ing caused my client to crash {ctype='bit[16]', label='Unity Points'}, -- 59 {ctype='bit[6]', label='_unknown6'}, -- 5A No obvious function - {ctype='unsigned int', label='_junk1'}, -- 5B + {ctype='unsigned int', label='_junk1'}, -- 5B + {ctype='unsigned int', label='_junk2'}, -- 60 } types.combat_skill = L{ From 194ceff309390f187b433734ce9496a7ae990d53 Mon Sep 17 00:00:00 2001 From: Ian Anderson Date: Sat, 23 Jan 2021 02:51:12 -0800 Subject: [PATCH 0536/1002] Update craft.lua This is to add back the synthesis results that are lost on the injected synths. --- addons/craft/craft.lua | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/addons/craft/craft.lua b/addons/craft/craft.lua index 6a26a16337..7bf405129d 100644 --- a/addons/craft/craft.lua +++ b/addons/craft/craft.lua @@ -779,6 +779,37 @@ local function handle_command(cmd, ...) end end +-- This is here so if a player does a manual synth the result is not displayed twice, since results are only hidden on injected synthesis. +windower.register_event('outgoing chunk', function(id,original,modified,injected,blocked) + if id == 0x096 and injected then + injected_synth = true + end +end) + +windower.register_event('incoming chunk', function(id,original,modified,injected,blocked) + if id == 0x06F and injected_synth then + local p = packets.parse('incoming',original) + if p['Result'] == (0 or 2) then + local item = res.items[p['Item']].en + windower.add_to_chat(121, 'You synthesized: \30\02%s\30\01.':format(item)) + injected_synth = false + end + if p['Result'] == (1 or 5) then + windower.add_to_chat(121,'Your synthesis has failed and your crystal is lost.') + if p['Lost Item 1'] ~= 0 then windower.add_to_chat(121, 'You lost: \30\02%s\30\01.':format(res.items[p['Lost Item 1']].en)) end + if p['Lost Item 2'] ~= 0 then windower.add_to_chat(121, 'You lost: \30\02%s\30\01.':format(res.items[p['Lost Item 2']].en)) end + if p['Lost Item 3'] ~= 0 then windower.add_to_chat(121, 'You lost: \30\02%s\30\01.':format(res.items[p['Lost Item 3']].en)) end + if p['Lost Item 4'] ~= 0 then windower.add_to_chat(121, 'You lost: \30\02%s\30\01.':format(res.items[p['Lost Item 4']].en)) end + if p['Lost Item 5'] ~= 0 then windower.add_to_chat(121, 'You lost: \30\02%s\30\01.':format(res.items[p['Lost Item 5']].en)) end + if p['Lost Item 6'] ~= 0 then windower.add_to_chat(121, 'You lost: \30\02%s\30\01.':format(res.items[p['Lost Item 6']].en)) end + if p['Lost Item 7'] ~= 0 then windower.add_to_chat(121, 'You lost: \30\02%s\30\01.':format(res.items[p['Lost Item 7']].en)) end + if p['Lost Item 8'] ~= 0 then windower.add_to_chat(121, 'You lost: \30\02%s\30\01.':format(res.items[p['Lost Item 8']].en)) end + injected_synth = false + end + end +end) + + windower.register_event('addon command', handle_command) windower.register_event('outgoing chunk', display_crafting_packet) windower.register_event('outgoing chunk', block_sort) From a2b045b444f908a9cf819143f9098e3e43daa052 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sat, 23 Jan 2021 15:26:18 +0000 Subject: [PATCH 0537/1002] Updated to version 2.0 Added resize and reset commands, implemented IPC, cleaned up code. --- addons/position_manager/position_manager.lua | 162 +++++++++++++------ 1 file changed, 113 insertions(+), 49 deletions(-) diff --git a/addons/position_manager/position_manager.lua b/addons/position_manager/position_manager.lua index 8671aaad42..8eecb52d26 100644 --- a/addons/position_manager/position_manager.lua +++ b/addons/position_manager/position_manager.lua @@ -1,4 +1,4 @@ ---Copyright © 2020, Lili +--Copyright © 2021, Lili --All rights reserved. --Redistribution and use in source and binary forms, with or without @@ -26,7 +26,7 @@ _addon.name = 'position_manager' _addon.author = 'Lili' -_addon.version = '1.1.1' +_addon.version = '2.0' _addon.command = 'pm' if not windower.file_exists(windower.windower_path .. '\\plugins\\WinControl.dll') then @@ -43,80 +43,137 @@ config = require('config') default = { x = 0, y = 0, + width = -1, + height = -1, delay = 0, } settings = config.load(default) -function move(settings) - if settings.delay > 0 then - coroutine.sleep(settings.delay) +function get_name(name) + if name ~= nil and type(name) ~= 'string' then + err('invalid name provided') + return false + elseif not name then + return windower.ffxi.get_player().name + elseif name == ':all' then + return 'all' end - windower.send_command('wincontrol move %s %s':format(settings.x, settings.y)) + return name +end + +function err(reason) + windower.add_to_chat(207, 'position_manager: ERROR - %s.':format(err)) + show_help() + return end function show_help() windower.add_to_chat(207, 'position_manager: Commands:') windower.add_to_chat(207, ' //pm set [name]') - windower.add_to_chat(207, ' //pm set delay [name]') + windower.add_to_chat(207, ' //pm size [name]') + windower.add_to_chat(207, ' //pm delay [name]') windower.add_to_chat(207, 'position_manager: See the readme for details.') end +function move(settings) + if settings.delay > 0 then + coroutine.sleep(settings.delay) + end + + windower.send_command('wincontrol move %s %s':format(settings.x, settings.y)) + --print('::wincontrol move %s %s':format(settings.x, settings.y)) +end + +function resize(settings) + if settings.width == -1 and settings.height == -1 then + windower.send_command('wincontrol resize reset') + return + end + + if settings.delay > 0 then + coroutine.sleep(settings.delay) + end + + local width = settings.width == -1 and windower.get_windower_settings().ui_x_res or settings.width + local height = settings.height == -1 and windower.get_windower_settings().ui_y_res or settings.height + + windower.send_command('wincontrol move %s %s':format(settings.x, settings.y)) + --print('::wincontrol resize %s %s':format(width, height)) +end + function handle_commands(cmd, ...) - cmd = cmd or cmd:lower() + cmd = cmd and cmd:lower() if cmd == 'r' then windower.send_command('lua r position_manager') return - elseif cmd == 'set' then + elseif cmd == 'set' or cmd == 'size' then local arg = {...} - local name = arg[3] - if name ~= nil and type(name) ~= 'string' then - windower.add_to_chat(207, 'position_manager: ERROR - invalid name provided.') - show_help() + local name = get_name(arg[3]) + + if not name then return - elseif not name then - name = windower.ffxi.get_player().name - elseif name == ':all' then - name = 'all' end - - if arg[1] == 'delay' then - settings.delay = tonumber(arg[2]) - if settings.delay > 0 then - config.save(settings, name) - windower.add_to_chat(207, 'position_manager: Delay set to %s for %s.':format(settings.delay, name)) - else - windower.add_to_chat(207, 'position_manager: ERROR - invalid delay provided.') - show_help() - return + + arg[1] = arg[1] == 'default' and -1 or tonumber(arg[1]) + arg[2] = arg[2] == 'default' and -1 or tonumber(arg[2]) + + if arg[1] and arg[2] then + if cmd == 'set' then + settings.x = arg[1] + settings.y = arg[2] + + if settings.x and settings.y then + config.save(settings, name) + windower.add_to_chat(207, 'position_manager: Position set to %s, %s for %s.':format(settings.x, settings.y, name)) + else + err('invalid position provided.') + return false + end + elseif cmd == 'size' then + settings.width = arg[1] + settings.height = arg[2] + + if settings.width and settings.height then + config.save(settings, name) + windower.add_to_chat(207, 'position_manager: Window size set to %s, %s for %s.':format(settings.width, settings.height, name)) + else + err('invalid window size provided.') + return false + end end - elseif arg[1] and arg[2] then - settings.x = tonumber(arg[1]) - settings.y = tonumber(arg[2]) - - if settings.x and settings.y then - config.save(settings, name) - - if windower.ffxi.get_info().logged_in then - player_name = windower.ffxi.get_player().name - if name:lower() == player_name:lower() then - move(settings) - end + else + err('invalid arguments provided.') + return false + end + + if windower.ffxi.get_info().logged_in then + player_name = windower.ffxi.get_player().name + if name:lower() == player_name:lower() then + if cmd == 'set' then + move(settings) + elseif cmd == 'size' then + resize(settings) end - windower.add_to_chat(207, 'position_manager: Position set to %s, %s for %s.':format(settings.x, settings.y, name)) - else - windower.add_to_chat(207, 'position_manager: ERROR - invalid position provided.') - show_help() - return end + end + + windower.send_ipc_message(name) + return true + + elseif cmd == 'delay' then + settings.delay = tonumber(arg[2]) + + if settings.delay > 0 then + config.save(settings, name) + windower.add_to_chat(207, 'position_manager: Delay set to %s for %s.':format(settings.delay, name)) else - windower.add_to_chat(207, 'position_manager: ERROR - invalid arguments provided.') - show_help() - return + err('invalid delay provided') + return false end - -- TODO: possibly add IPC - return + return true + elseif cmd ~= 'help' then windower.add_to_chat(207, 'position_manager: %s command not found.':format(cmd)) end @@ -124,5 +181,12 @@ function handle_commands(cmd, ...) end config.register(settings, move) +config.register(settings, resize) windower.register_event('addon command', handle_commands) + +windower.register_event('ipc message', function(msg) + if (windower.ffxi.get_info().logged_in and msg == windower.ffxi.get_player().name) or msg == 'all' then + config.reload(settings) + end +end) From 8582160eaa4b8a443f76ec220a586870313a5ec8 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sat, 23 Jan 2021 15:27:48 +0000 Subject: [PATCH 0538/1002] Update README.md --- addons/position_manager/README.md | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/addons/position_manager/README.md b/addons/position_manager/README.md index 53c3637aee..d695b64bf8 100644 --- a/addons/position_manager/README.md +++ b/addons/position_manager/README.md @@ -2,17 +2,20 @@ Set and save screen position per-character. Requires the WinControl addon. -Command: -`//pm set [name]` +Commands: +`//pm set [name]` +`//pm size [name]` +`//pm size reset [name]` -`pos_x` and `pos_y` are obligatory and must be numbers. +`pos_x`, `pos_y`, `width` and `height` are obligatory and must be numbers. +`size reset` will restore the original windows size for that character (as specified in the Windower profile). `name` is optional. If no name is provided, settings will be saved for the current character. `:all` is a special name that can be used to set the default position. -**Note**: Characters are only moved after they're logged in. The `:all` position will be used for the character login screen as well. +**Note**: Characters are only moved or resized after they're logged in. The `:all` position will be used for the character login screen as well. **Note**: On some systems with very fast or very slow disks, it can happen that the `WinControl` addon does not get loaded in time for `position_manager` to send the proper command. In that case, you can use this command: -`//pm set delay [name]` +`//pm delay [name]` (where `seconds` is obligatory and must be a positive number, and `name` follows the same rules as before), to set a delay that will hopefully let the plugin load in time. ### Examples: @@ -27,11 +30,13 @@ Will set the default position for the character called "Yourname" to X: 1920 and This will make the character appear on the secondary screen that is to the right of the main screen - useful for multi-screen setups. `//pm set delay 1 all` -`//pm set Yourmain 0 40` -`//pm set Youralt 800 40` +`//pm set 0 40 Yourman` +`//pm set 800 40 Youralt` Will set delay to 1 for all characters, then set the position of your main to X: 0, Y: 40, and your alt to X: 800, Y: 40. If your laptop screen is 1600px wide, and your instances are both set at 800x600, this will put them side by side. **Warning:** the `all` name will delete every other character-specific settings that are already saved! It's best to use it only once after you install the addon, to set default position and delay for non-specified characters. +IPC is supported. Setting a character's position or size from another character's window, will cause the affected character to update automatically. + Enjoy. From 8f17534398cdfa2c49a7016d6bb270cbfc2dcb88 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sat, 23 Jan 2021 22:43:10 +0000 Subject: [PATCH 0539/1002] Code cleanup Got rid of windower.ffxi.get_info() and .get_player() calls. --- addons/position_manager/position_manager.lua | 52 ++++++++++---------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/addons/position_manager/position_manager.lua b/addons/position_manager/position_manager.lua index 8eecb52d26..c0e6d9f4fb 100644 --- a/addons/position_manager/position_manager.lua +++ b/addons/position_manager/position_manager.lua @@ -26,7 +26,7 @@ _addon.name = 'position_manager' _addon.author = 'Lili' -_addon.version = '2.0' +_addon.version = '2.0.1' _addon.command = 'pm' if not windower.file_exists(windower.windower_path .. '\\plugins\\WinControl.dll') then @@ -38,9 +38,9 @@ else windower.send_command('load wincontrol') end -config = require('config') +local config = require('config') -default = { +local default = { x = 0, y = 0, width = -1, @@ -48,7 +48,7 @@ default = { delay = 0, } -settings = config.load(default) +local settings = config.load(default) function get_name(name) if name ~= nil and type(name) ~= 'string' then @@ -71,7 +71,7 @@ end function show_help() windower.add_to_chat(207, 'position_manager: Commands:') windower.add_to_chat(207, ' //pm set [name]') - windower.add_to_chat(207, ' //pm size [name]') + windower.add_to_chat(207, ' //pm size [name]') windower.add_to_chat(207, ' //pm delay [name]') windower.add_to_chat(207, 'position_manager: See the readme for details.') end @@ -80,9 +80,9 @@ function move(settings) if settings.delay > 0 then coroutine.sleep(settings.delay) end - + windower.send_command('wincontrol move %s %s':format(settings.x, settings.y)) - --print('::wincontrol move %s %s':format(settings.x, settings.y)) + --print('::wincontrol move %s %s':format(settings.x, settings.y)) end function resize(settings) @@ -90,16 +90,16 @@ function resize(settings) windower.send_command('wincontrol resize reset') return end - + if settings.delay > 0 then coroutine.sleep(settings.delay) end - + local width = settings.width == -1 and windower.get_windower_settings().ui_x_res or settings.width local height = settings.height == -1 and windower.get_windower_settings().ui_y_res or settings.height - + windower.send_command('wincontrol move %s %s':format(settings.x, settings.y)) - --print('::wincontrol resize %s %s':format(width, height)) + --print('::wincontrol resize %s %s':format(width, height)) end function handle_commands(cmd, ...) @@ -115,10 +115,10 @@ function handle_commands(cmd, ...) if not name then return end - + arg[1] = arg[1] == 'default' and -1 or tonumber(arg[1]) arg[2] = arg[2] == 'default' and -1 or tonumber(arg[2]) - + if arg[1] and arg[2] then if cmd == 'set' then settings.x = arg[1] @@ -134,7 +134,7 @@ function handle_commands(cmd, ...) elseif cmd == 'size' then settings.width = arg[1] settings.height = arg[2] - + if settings.width and settings.height then config.save(settings, name) windower.add_to_chat(207, 'position_manager: Window size set to %s, %s for %s.':format(settings.width, settings.height, name)) @@ -148,20 +148,17 @@ function handle_commands(cmd, ...) return false end - if windower.ffxi.get_info().logged_in then - player_name = windower.ffxi.get_player().name - if name:lower() == player_name:lower() then - if cmd == 'set' then - move(settings) - elseif cmd == 'size' then - resize(settings) - end + if player_name and name:lower() == player_name:lower() then + if cmd == 'set' then + move(settings) + elseif cmd == 'size' then + resize(settings) end end - + windower.send_ipc_message(name) return true - + elseif cmd == 'delay' then settings.delay = tonumber(arg[2]) @@ -185,8 +182,13 @@ config.register(settings, resize) windower.register_event('addon command', handle_commands) +windower.register_event('load','login','logout', function(name) + local player = windower.ffxi.get_player() + player_name = player and player.name +end) + windower.register_event('ipc message', function(msg) - if (windower.ffxi.get_info().logged_in and msg == windower.ffxi.get_player().name) or msg == 'all' then + if msg == player_name or msg == 'all' then config.reload(settings) end end) From be5543120f4e347d557210b84c266fea63241068 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sat, 23 Jan 2021 23:08:19 +0000 Subject: [PATCH 0540/1002] Last second copypaste bug squash. --- addons/position_manager/position_manager.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/position_manager/position_manager.lua b/addons/position_manager/position_manager.lua index c0e6d9f4fb..4df4123870 100644 --- a/addons/position_manager/position_manager.lua +++ b/addons/position_manager/position_manager.lua @@ -1,4 +1,4 @@ ---Copyright © 2021, Lili +--Copyright © 2020, Lili --All rights reserved. --Redistribution and use in source and binary forms, with or without @@ -98,7 +98,7 @@ function resize(settings) local width = settings.width == -1 and windower.get_windower_settings().ui_x_res or settings.width local height = settings.height == -1 and windower.get_windower_settings().ui_y_res or settings.height - windower.send_command('wincontrol move %s %s':format(settings.x, settings.y)) + windower.send_command('wincontrol resize %s %s':format(width, height)) --print('::wincontrol resize %s %s':format(width, height)) end From 16b349921d30b4eecc80fb35135983a0550787db Mon Sep 17 00:00:00 2001 From: Ian Anderson Date: Sat, 23 Jan 2021 15:19:52 -0800 Subject: [PATCH 0541/1002] Update craft.lua --- addons/craft/craft.lua | 50 +++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/addons/craft/craft.lua b/addons/craft/craft.lua index 7bf405129d..ba7693f89a 100644 --- a/addons/craft/craft.lua +++ b/addons/craft/craft.lua @@ -779,37 +779,33 @@ local function handle_command(cmd, ...) end end --- This is here so if a player does a manual synth the result is not displayed twice, since results are only hidden on injected synthesis. -windower.register_event('outgoing chunk', function(id,original,modified,injected,blocked) - if id == 0x096 and injected then - injected_synth = true - end +-- This is here so if a player does a legitimate synth the result is not displayed twice, since results are only hidden on injected synthesis. +windower.register_event('outgoing chunk', function(id, original, modified, injected, blocked) + if id == 0x096 and injected then + injected_synth = true + end end) -windower.register_event('incoming chunk', function(id,original,modified,injected,blocked) - if id == 0x06F and injected_synth then - local p = packets.parse('incoming',original) - if p['Result'] == (0 or 2) then - local item = res.items[p['Item']].en - windower.add_to_chat(121, 'You synthesized: \30\02%s\30\01.':format(item)) - injected_synth = false - end - if p['Result'] == (1 or 5) then - windower.add_to_chat(121,'Your synthesis has failed and your crystal is lost.') - if p['Lost Item 1'] ~= 0 then windower.add_to_chat(121, 'You lost: \30\02%s\30\01.':format(res.items[p['Lost Item 1']].en)) end - if p['Lost Item 2'] ~= 0 then windower.add_to_chat(121, 'You lost: \30\02%s\30\01.':format(res.items[p['Lost Item 2']].en)) end - if p['Lost Item 3'] ~= 0 then windower.add_to_chat(121, 'You lost: \30\02%s\30\01.':format(res.items[p['Lost Item 3']].en)) end - if p['Lost Item 4'] ~= 0 then windower.add_to_chat(121, 'You lost: \30\02%s\30\01.':format(res.items[p['Lost Item 4']].en)) end - if p['Lost Item 5'] ~= 0 then windower.add_to_chat(121, 'You lost: \30\02%s\30\01.':format(res.items[p['Lost Item 5']].en)) end - if p['Lost Item 6'] ~= 0 then windower.add_to_chat(121, 'You lost: \30\02%s\30\01.':format(res.items[p['Lost Item 6']].en)) end - if p['Lost Item 7'] ~= 0 then windower.add_to_chat(121, 'You lost: \30\02%s\30\01.':format(res.items[p['Lost Item 7']].en)) end - if p['Lost Item 8'] ~= 0 then windower.add_to_chat(121, 'You lost: \30\02%s\30\01.':format(res.items[p['Lost Item 8']].en)) end - injected_synth = false - end - end +windower.register_event('incoming chunk', function(id, original, modified, injected, blocked) + if id == 0x06F and injected_synth then + local p = packets.parse('incoming',original) + if p['Result'] == 0 or p['Result'] == 2 then + local item = res.items[p['Item']].english + windower.add_to_chat(121, 'You synthesized: \30\02%s\30\01.':format(item)) + injected_synth = false + end + if p['Result'] == 1 or p['Result'] == 5 then + windower.add_to_chat(121,'Your synthesis has failed and your crystal is lost.') + for i=1, 8 do + if p['Lost Item '..i] ~= 0 then + windower.add_to_chat(121, 'You lost: \30\02%s\30\01.':format(res.items[p['Lost Item '..i]].english)) + end + end + injected_synth = false + end + end end) - windower.register_event('addon command', handle_command) windower.register_event('outgoing chunk', display_crafting_packet) windower.register_event('outgoing chunk', block_sort) From de61b2d5dfe5c985efb39ae290bd2599ee0a9e3a Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sat, 23 Jan 2021 23:25:51 +0000 Subject: [PATCH 0542/1002] Added Cumulus Masque +1 --- addons/Dimmer/Dimmer.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/Dimmer/Dimmer.lua b/addons/Dimmer/Dimmer.lua index bf64f9bfba..b8ca24b852 100644 --- a/addons/Dimmer/Dimmer.lua +++ b/addons/Dimmer/Dimmer.lua @@ -38,6 +38,7 @@ item_info = { [1]={id=26176,japanese='D.ホラリング',english='"Dim. Ring (Holla)"',slot=13}, [2]={id=26177,japanese='D.デムリング',english='"Dim. Ring (Dem)"',slot=13}, [3]={id=26178,japanese='D.メアリング',english='"Dim. Ring (Mea)"',slot=13}, + [4]={id=10385,japanese="キュムラスマスク+1",english="Cumulus Masque +1",slot=4}, } function search_item() From 78fe1d202d04cfb4c61045135f309b1426626bf9 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sat, 23 Jan 2021 23:33:48 +0000 Subject: [PATCH 0543/1002] Update Dimmer.lua --- addons/Dimmer/Dimmer.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/Dimmer/Dimmer.lua b/addons/Dimmer/Dimmer.lua index b8ca24b852..3c0db58356 100644 --- a/addons/Dimmer/Dimmer.lua +++ b/addons/Dimmer/Dimmer.lua @@ -39,7 +39,7 @@ item_info = { [2]={id=26177,japanese='D.デムリング',english='"Dim. Ring (Dem)"',slot=13}, [3]={id=26178,japanese='D.メアリング',english='"Dim. Ring (Mea)"',slot=13}, [4]={id=10385,japanese="キュムラスマスク+1",english="Cumulus Masque +1",slot=4}, - } + } function search_item() local item_array = {} From cbe51ae2f321a17a4520a1f70f0ffa1578f3ead2 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sat, 23 Jan 2021 23:40:00 +0000 Subject: [PATCH 0544/1002] Less spaces --- addons/Dimmer/Dimmer.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/Dimmer/Dimmer.lua b/addons/Dimmer/Dimmer.lua index 3c0db58356..c8f577d530 100644 --- a/addons/Dimmer/Dimmer.lua +++ b/addons/Dimmer/Dimmer.lua @@ -39,7 +39,7 @@ item_info = { [2]={id=26177,japanese='D.デムリング',english='"Dim. Ring (Dem)"',slot=13}, [3]={id=26178,japanese='D.メアリング',english='"Dim. Ring (Mea)"',slot=13}, [4]={id=10385,japanese="キュムラスマスク+1",english="Cumulus Masque +1",slot=4}, - } +} function search_item() local item_array = {} From 5b8e331a5375769e154c17a4913bdc1357f6c371 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Sun, 7 Feb 2021 01:14:32 +0100 Subject: [PATCH 0545/1002] Update slips.lua Update/Fix slips.lua lib --- addons/libs/slips.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 214947bfdf..2d059dee33 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,8 +34,8 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757}, -- 191 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453,}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454,}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 25910, 54, 20571}, -- 120 - [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745}, --171 + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791}, -- 129 + [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759}, --173 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330,}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665,}, --115 [slips.storages[26]] = L{23063, 23130, 23197, 23264, 23331, 23064, 23131, 23198, 23265, 23332, 23065, 23132, 23199, 23266, 23333, 23066, 23133, 23200, 23267, 23334, 23067, 23134, 23201, 23268, 23335, 23068, 23135, 23202, 23269, 23336, 23069, 23136, 23203, 23270, 23337, 23070, 23137, 23204, 23271, 23338, 23071, 23138, 23205, 23272, 23339, 23072, 23139, 23206, 23273, 23340, 23073, 23140, 23207, 23274, 23341, 23074, 23141, 23208, 23275, 23342, 23075, 23142, 23209, 23276, 23343, 23076, 23143, 23210, 23277, 23344, 23077, 23144, 23211, 23278, 23345, 23078, 23145, 23212, 23279, 23346, 23079, 23146, 23213, 23280, 23347, 23080, 23147, 23214, 23281, 23348, 23081, 23148, 23215, 23282, 23349, 23082, 23149, 23216, 23283, 23350, 23083, 23150, 23217, 23284, 23351, 23084, 23151, 23218, 23285, 23352,}, --110 From 7f198561b540b50238d14e249d485d2b9d1ff0a1 Mon Sep 17 00:00:00 2001 From: dtw <362017+dtw@users.noreply.github.com> Date: Sun, 7 Feb 2021 12:18:59 +0000 Subject: [PATCH 0546/1002] Update message_ids.lua --- addons/pointwatch/message_ids.lua | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/addons/pointwatch/message_ids.lua b/addons/pointwatch/message_ids.lua index 470990897c..3cd91ffae9 100644 --- a/addons/pointwatch/message_ids.lua +++ b/addons/pointwatch/message_ids.lua @@ -33,7 +33,7 @@ local messages = { z15 = { name = 'Abyssea - Konschtat', - offset = 7312, + offset = 7315, pearl_ebon_gold_silvery = 0, azure_ruby_amber = 1, visitant_status_update = 9, @@ -50,7 +50,7 @@ local messages = { }, z132 = { name = 'Abyssea - La Theine', - offset = 7312, + offset = 7315, pearl_ebon_gold_silvery = 0, azure_ruby_amber = 1, visitant_status_update = 9, @@ -67,7 +67,7 @@ local messages = { }, z45 = { name = 'Abyssea - Tahrongi', - offset = 7312, + offset = 7315, pearl_ebon_gold_silvery = 0, azure_ruby_amber = 1, visitant_status_update = 9, @@ -84,7 +84,7 @@ local messages = { }, z215 = { name = 'Abyssea - Attohwa', - offset = 7212, + offset = 7215, pearl_ebon_gold_silvery = 0, azure_ruby_amber = 1, visitant_status_update = 9, @@ -101,7 +101,7 @@ local messages = { }, z216 = { name = 'Abyssea - Misareaux', - offset = 7312, + offset = 7315, pearl_ebon_gold_silvery = 0, azure_ruby_amber = 1, visitant_status_update = 9, @@ -118,7 +118,7 @@ local messages = { }, z217 = { name = 'Abyssea - Vunkerl', - offset = 7312, + offset = 7315, pearl_ebon_gold_silvery = 0, azure_ruby_amber = 1, visitant_status_update = 9, @@ -135,7 +135,7 @@ local messages = { }, z218 = { name = 'Abyssea - Altepa', - offset = 7312, + offset = 7315, pearl_ebon_gold_silvery = 0, azure_ruby_amber = 1, visitant_status_update = 9, @@ -152,7 +152,7 @@ local messages = { }, z254 = { name = 'Abyssea - Grauberg', - offset = 7312, + offset = 7315, pearl_ebon_gold_silvery = 0, azure_ruby_amber = 1, visitant_status_update = 9, @@ -169,7 +169,7 @@ local messages = { }, z253 = { name = 'Abyssea - Uleguerand', - offset = 7212, + offset = 7215, pearl_ebon_gold_silvery = 0, azure_ruby_amber = 1, visitant_status_update = 9, From b42bd9ecbc631eb54f8a90ef01922159a3cc744a Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Sun, 7 Feb 2021 22:52:08 +0100 Subject: [PATCH 0547/1002] Yush: Added function support --- addons/Yush/Yush.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/addons/Yush/Yush.lua b/addons/Yush/Yush.lua index 32cf38fd1b..0bee580f96 100644 --- a/addons/Yush/Yush.lua +++ b/addons/Yush/Yush.lua @@ -1,5 +1,5 @@ _addon.author = 'Arcon' -_addon.version = '2.1.2.0' +_addon.version = '2.2.0.0' _addon.language = 'English' _addon.command = 'yush' @@ -107,6 +107,8 @@ check = function(keyset) if key <= keyset then if type(val) == 'string' then windower.send_command(val) + elseif type(val) == 'function' then + val() else current = val stack:append(current) @@ -126,7 +128,7 @@ parse_binds = function(fbinds, top) rawset(names, top, rawget(_innerG._names, fbinds)) for key, val in pairs(fbinds) do key = S(key:split('+')):map(string.lower) - if type(val) == 'string' then + if type(val) == 'string' or type(val) == 'function' then rawset(top, key, val) else local sub = {} From c0bcc0e8d077e76ab2db23b965cd39342597e1ee Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Mon, 8 Feb 2021 17:31:47 -0700 Subject: [PATCH 0548/1002] Packets fields.lua incoming `0x017` and `0x01B` for Assist Channels `incoming 0x017` changed to have different data for different chat modes Also tweaked `incoming 0x01B` for Mastery Rank and Mentor icon data --- addons/libs/packets/fields.lua | 57 +++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index c04907d5d3..a2f90857da 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1433,25 +1433,57 @@ fields.incoming[0x00E] = L{ {ctype='char*', label='Name'}, -- 34 - * } --- Incoming Chat -fields.incoming[0x017] = L{ - {ctype='unsigned char', label='Mode', fn=chat}, -- 04 +enums['mentor icon'] = { + [0] = 'None', + [1] = 'Bronze', + [2] = 'Silver', + [3] = 'Gold' +} + +func.incoming[0x017] = {} +func.incoming[0x017].base = L{ + {ctype='unsigned char', label='Mode', fn=chat}, -- 04 +} +func.incoming[0x017].default = L{ + {ctype='bool', label='GM'}, -- 05 + {ctype='unsigned short', label='_padding1',}, -- 06 Reserved for Yell and Assist Modes + {ctype='char[0xF]', label='Sender Name'}, -- 08 + {ctype='char*', label='Message'}, -- 17 Max of 150 characters +} +func.incoming[0x017][0x1A] = L{ -- Yell + {ctype='bool', label='GM'}, -- 05 + {ctype='unsigned short', label='Zone', fn=zone}, -- 06 Zone ID of sender + {ctype='char[0xF]', label='Sender Name'}, -- 08 + {ctype='char*', label='Message'}, -- 17 Max of 150 characters +} +func.incoming[0x017][0x22] = L{ -- AssistJ {ctype='bool', label='GM'}, -- 05 - {ctype='unsigned short', label='Zone', fn=zone}, -- 06 Set only for Yell + {ctype='unsigned char', label='Mastery Rank'}, -- 06 Sender Mastery Rank + {ctype='unsigned char', label='Mentor Icon', fn=e+{'mentor icon'}},-- 07 Color of Mentor Flag {ctype='char[0xF]', label='Sender Name'}, -- 08 {ctype='char*', label='Message'}, -- 17 Max of 150 characters } +func.incoming[0x017][0x23] = func.incoming[0x017][0x22] -- AssistE + +-- Incoming Chat +fields.incoming[0x017] = function() + local fields = func.incoming[0x017] + + return function(data, type) + return fields.base + (fields[type or data:byte(5)] or fields.default) + end +end() -- Job Info fields.incoming[0x01B] = L{ {ctype='unsigned int', label='_unknown1'}, -- 04 Observed value of 05 - {ctype='unsigned char', label='Main Job', fn=job}, -- 08 + {ctype='unsigned char', label='Main Job', fn=job}, -- 08 {ctype='unsigned char', label='Flag or Main Job Level?'}, -- 09 {ctype='unsigned char', label='Flag or Sub Job Level?'}, -- 0A - {ctype='unsigned char', label='Sub Job', fn=job}, -- 0B + {ctype='unsigned char', label='Sub Job', fn=job}, -- 0B {ctype='bit[32]', label='Sub/Job Unlock Flags'}, -- 0C Indicate whether subjob is unlocked and which jobs are unlocked. lsb of 0x0C indicates subjob unlock. {ctype='unsigned char', label='_unknown3'}, -- 10 Flag or List Start - {ref=types.job_level, lookup={res.jobs, 0x01}, count=0x0F}, -- 11 + {ref=types.job_level, lookup={res.jobs, 0x01}, count=0x0F}, -- 11 {ctype='unsigned short', label='Base STR'}, -- 20 -- Altering these stat values has no impact on your equipment menu. {ctype='unsigned short', label='Base DEX'}, -- 22 {ctype='unsigned short', label='Base VIT'}, -- 24 @@ -1464,11 +1496,13 @@ fields.incoming[0x01B] = L{ {ctype='unsigned int', label='Maximum MP'}, -- 40 {ctype='unsigned int', label='Flags'}, -- 44 Looks like a bunch of flags. Observed value if 01 00 00 00 {ctype='unsigned char', label='_unknown5'}, -- 48 Potential flag to signal the list start. Observed value of 01 - {ref=types.job_level, lookup={res.jobs, 0x01}, count=0x16}, -- 49 + {ref=types.job_level, lookup={res.jobs, 0x01}, count=0x16}, -- 49 {ctype='unsigned char', label='Current Monster Level'}, -- 5F {ctype='unsigned int', label='Encumbrance Flags'}, -- 60 [legs, hands, body, head, ammo, range, sub, main,] [back, right_ring, left_ring, right_ear, left_ear, waist, neck, feet] [HP, CHR, MND, INT, AGI, VIT, DEX, STR,] [X X X X X X X MP] - {ctype='unsigned short', label='_unknown7'}, -- 64 - {ctype='unsigned short', label='Mastery Rank'}, -- 66 + {ctype='unsigned char', label='_unknown7'}, -- 64 + {ctype='unsigned char', label='Mentor Icon', fn=e+{'mentor icon'}},-- 65 + {ctype='unsigned char', label='Mastery Rank'}, -- 66 + {ctype='unsigned char', label='_unknown8'}, -- 67 } -- Inventory Count @@ -2923,7 +2957,7 @@ fields.incoming[0x061] = L{ {ctype='bit[16]', label='Unity Points'}, -- 59 {ctype='bit[6]', label='_unknown6'}, -- 5A No obvious function {ctype='unsigned int', label='_junk1'}, -- 5B - {ctype='unsigned int', label='_junk2'}, -- 60 + {ctype='unsigned int', label='_junk2'}, -- 5F } types.combat_skill = L{ @@ -3860,3 +3894,4 @@ Redistribution and use in source and binary forms, with or without modification, 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 Windower 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. ]] + From bb5b1ff8d2594504550fb4c96ba7c28a8a93e765 Mon Sep 17 00:00:00 2001 From: Ian Anderson Date: Mon, 8 Feb 2021 17:21:09 -0800 Subject: [PATCH 0549/1002] Update FastCS.lua Add the unity warp NPCs to the exclusion list(currently, only home points books and waypoints are excluded) --- addons/FastCS/FastCS.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/FastCS/FastCS.lua b/addons/FastCS/FastCS.lua index 082d82342b..e3a4e08517 100644 --- a/addons/FastCS/FastCS.lua +++ b/addons/FastCS/FastCS.lua @@ -1,6 +1,6 @@ _addon.name = "FastCS" _addon.author = "Cairthenn" -_addon.version = "1.2" +_addon.version = "1.3" _addon.commands = {"FastCS","FCS"} --Requires: @@ -11,7 +11,7 @@ require("luau") defaults = {} defaults.frame_rate_divisor = 2 -defaults.exclusions = S{"home point #1", "home point #2", "home point #3", "home point #4", "home point #5", "survival guide", "waypoint"} +defaults.exclusions = S{"home point #1", "home point #2", "home point #3", "home point #4", "home point #5", "igsli", "urbiolaine", "teldro-kesdrodo", "nunaarl bthtrogg", "survival guide", "waypoint"} settings = config.load(defaults) -- Globals: From 05b2971a7c44cab481d3fb147b09477d7f779182 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Mon, 8 Feb 2021 22:02:22 -0500 Subject: [PATCH 0550/1002] Unity Warps --- addons/FastCS/FastCS.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/FastCS/FastCS.lua b/addons/FastCS/FastCS.lua index 082d82342b..e3a4e08517 100644 --- a/addons/FastCS/FastCS.lua +++ b/addons/FastCS/FastCS.lua @@ -1,6 +1,6 @@ _addon.name = "FastCS" _addon.author = "Cairthenn" -_addon.version = "1.2" +_addon.version = "1.3" _addon.commands = {"FastCS","FCS"} --Requires: @@ -11,7 +11,7 @@ require("luau") defaults = {} defaults.frame_rate_divisor = 2 -defaults.exclusions = S{"home point #1", "home point #2", "home point #3", "home point #4", "home point #5", "survival guide", "waypoint"} +defaults.exclusions = S{"home point #1", "home point #2", "home point #3", "home point #4", "home point #5", "igsli", "urbiolaine", "teldro-kesdrodo", "nunaarl bthtrogg", "survival guide", "waypoint"} settings = config.load(defaults) -- Globals: From 780e841ec3535e32b0348876c70b3932fa7e8d00 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Thu, 11 Feb 2021 14:39:15 +0100 Subject: [PATCH 0551/1002] Update slips.lua Adding Troth and Helgoland --- addons/libs/slips.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 2d059dee33..a87743fc65 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,8 +34,8 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757}, -- 191 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453,}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454,}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791}, -- 129 - [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759}, --173 + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489}, -- 130 + [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770}, --174 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330,}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665,}, --115 [slips.storages[26]] = L{23063, 23130, 23197, 23264, 23331, 23064, 23131, 23198, 23265, 23332, 23065, 23132, 23199, 23266, 23333, 23066, 23133, 23200, 23267, 23334, 23067, 23134, 23201, 23268, 23335, 23068, 23135, 23202, 23269, 23336, 23069, 23136, 23203, 23270, 23337, 23070, 23137, 23204, 23271, 23338, 23071, 23138, 23205, 23272, 23339, 23072, 23139, 23206, 23273, 23340, 23073, 23140, 23207, 23274, 23341, 23074, 23141, 23208, 23275, 23342, 23075, 23142, 23209, 23276, 23343, 23076, 23143, 23210, 23277, 23344, 23077, 23144, 23211, 23278, 23345, 23078, 23145, 23212, 23279, 23346, 23079, 23146, 23213, 23280, 23347, 23080, 23147, 23214, 23281, 23348, 23081, 23148, 23215, 23282, 23349, 23082, 23149, 23216, 23283, 23350, 23083, 23150, 23217, 23284, 23351, 23084, 23151, 23218, 23285, 23352,}, --110 From cba53dd7ae54f6c1ee3450a15e82f1c859fb4916 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sat, 13 Feb 2021 03:31:25 +0000 Subject: [PATCH 0552/1002] Fixing errors on Linkshell/Linkpearls/Pearlsacks This change fixes two errors that happen when Linkshells with certain combinations of characters result in a bitpacked LS name that contains zeroed bytes in the middle. First change detects the length of the name properly, second change fixes the `nil` error. --- addons/libs/extdata.lua | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/addons/libs/extdata.lua b/addons/libs/extdata.lua index c92e7bdcf1..456c0a5e8e 100644 --- a/addons/libs/extdata.lua +++ b/addons/libs/extdata.lua @@ -1481,7 +1481,7 @@ function tools.bit.l_to_r_bit_packed(dat_string,start,stop) local c_count = math.ceil(stop/8) while c_count >= math.ceil((start+1)/8) do -- Grabs the most significant byte first and works down towards the least significant. - local cur_val = dat_string:byte(c_count) + local cur_val = dat_string:byte(c_count) or 0 local scal = 1 if c_count == math.ceil(stop/8) then -- Take the least significant bits of the most significant byte @@ -1683,7 +1683,17 @@ end function decode.Linkshell(str) local status_map = {[0]='Unopened',[1]='Linkshell',[2]='Pearlsack',[3]='Linkpearl',[4]='Broken'} - local name_end = string.find(str,string.char(0),10) + local name_end = function() + if str:sub(#str,#str) ~= string.char(0) then + return #str + end + for i=#str-1,10,-1 do + if str:sub(i,i) ~= string.char(0) then + return i + end + end + end() + local name_map = {[0]="'",[1]="a",[2]='b',[3]='c',[4]='d',[5]='e',[6]='f',[7]='g',[8]='h',[9]='i',[10]='j', [11]='k',[12]='l',[13]='m',[14]='n',[15]='o',[16]='p',[17]='q',[18]='r',[19]='s',[20]='t',[21]='u',[22]='v',[23]='w', [24]='x',[25]='yx',[26]='z',[27]='A',[28]='B',[29]='C',[30]='D',[31]='E',[32]='F',[33]='G',[34]='H',[35]='I',[36]='J', From c8fa161d5d6926a1b71a03bb497aa7f49f2aee9b Mon Sep 17 00:00:00 2001 From: Chiaia Date: Sat, 13 Feb 2021 01:12:40 -0500 Subject: [PATCH 0553/1002] Slips-be-fixed Looks like it was just a typo. Looking in game the 2 items before and after are what go together. --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index a87743fc65..495e624b24 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757}, -- 191 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453,}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454,}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489}, -- 130 + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489}, -- 129 [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770}, --174 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330,}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665,}, --115 From 30b8859a2d8335ed9c63c24c4bd2221a9022eb58 Mon Sep 17 00:00:00 2001 From: dtw <362017+dtw@users.noreply.github.com> Date: Sat, 13 Feb 2021 10:23:54 +0000 Subject: [PATCH 0554/1002] Use logger instead of add_to_chat --- addons/macrochanger/macrochanger.lua | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/addons/macrochanger/macrochanger.lua b/addons/macrochanger/macrochanger.lua index 727f592dd3..6eb09e0f55 100644 --- a/addons/macrochanger/macrochanger.lua +++ b/addons/macrochanger/macrochanger.lua @@ -30,6 +30,7 @@ _addon.version = '1.0.0.1' _addon.commands = {'mc','macrochanger'} require('strings') +require('logger') windower.register_event('load', function() globaldisable = 0 @@ -107,7 +108,7 @@ function options_load() RUN = {Book = '20', Page = '1'}, } print('Default settings file created') - windower.add_to_chat(12,'MacroChanger created a settings file and loaded!') + notice('MacroChanger created a settings file and loaded!') else f:close() for curline in io.lines(windower.addon_path..'data/settings.txt') do @@ -119,7 +120,7 @@ function options_load() globaldisable = tonumber(splat[3]) end end - windower.add_to_chat(12,'MacroChanger read from a settings file and loaded!') + notice('MacroChanger read from a settings file and loaded!') end end @@ -135,14 +136,14 @@ windower.register_event('job change',function () end if ((book == 'disabled') or (page == 'disabled')) then - windower.add_to_chat(17, ' Auto Macro Switching Disabled for ' .. job ..'.') + notice('Auto Macro Switching Disabled for ' .. job ..'.') else - windower.add_to_chat(17, ' Changing macros to Book: ' .. book .. ' and Page: ' .. page .. '. Job Changed to ' .. job) + log('Changing macros to Book: ' .. book .. ' and Page: ' .. page .. '. Job Changed to ' .. job) windower.send_command('input /macro book '..book..';wait 0.2;input /macro set '..page..';') end elseif globaldisable == 1 then - windower.add_to_chat(17, ' Auto Macro Switching Disabled for All Jobs.') + notice('Auto Macro Switching Disabled for All Jobs.') end end) @@ -153,16 +154,16 @@ windower.register_event('addon command', function(...) if args[1] == 'disableall' then if args[2] == 'on' then globaldisable = 1 - windower.add_to_chat(17, 'All automated macro switching disabled.') + warning('All automated macro switching disabled.') elseif args[2] == 'off' then globaldisable = 0 - windower.add_to_chat(17, 'Automated macro switching enabled.') + notice('Automated macro switching enabled.') end elseif args[1]:lower() == 'help' then - windower.add_to_chat(17, 'MacroChanger Commands:') - windower.add_to_chat(17, 'disableall [on|off]') - windower.add_to_chat(17, ' on - Disables all automated macro switching') - windower.add_to_chat(17, ' off - Enables all automated macro switching not disabled individually') - windower.add_to_chat(17, ' Resets to what is stored in settings upon unloading of addon. To Permanently change, please change the option in the settings file.') + log('MacroChanger Commands:') + log('disableall [on|off]') + log(' on - Disables all automated macro switching') + log(' off - Enables all automated macro switching not disabled individually') + log('Resets to what is stored in settings upon unloading of addon. To Permanently change, please change the option in the settings file.') end end) From 42ed61c16d2b3b81290263e5bb56b6ccdfbacda6 Mon Sep 17 00:00:00 2001 From: dtw <362017+dtw@users.noreply.github.com> Date: Sat, 13 Feb 2021 10:30:07 +0000 Subject: [PATCH 0555/1002] Adjust wording ... this is more personal preference, I guess... --- addons/macrochanger/macrochanger.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/macrochanger/macrochanger.lua b/addons/macrochanger/macrochanger.lua index 6eb09e0f55..23af75acc4 100644 --- a/addons/macrochanger/macrochanger.lua +++ b/addons/macrochanger/macrochanger.lua @@ -138,7 +138,7 @@ windower.register_event('job change',function () if ((book == 'disabled') or (page == 'disabled')) then notice('Auto Macro Switching Disabled for ' .. job ..'.') else - log('Changing macros to Book: ' .. book .. ' and Page: ' .. page .. '. Job Changed to ' .. job) + log('Job changed to ' .. job .. ' - switched to Book: ' .. book .. ' and Page: ' .. page) windower.send_command('input /macro book '..book..';wait 0.2;input /macro set '..page..';') end elseif globaldisable == 1 then From 290f004b65fb01bb323e05400d590ad77a4db255 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sat, 13 Feb 2021 11:57:52 +0000 Subject: [PATCH 0556/1002] Update extdata.lua --- addons/libs/extdata.lua | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/addons/libs/extdata.lua b/addons/libs/extdata.lua index 456c0a5e8e..5bec6cc42d 100644 --- a/addons/libs/extdata.lua +++ b/addons/libs/extdata.lua @@ -1683,17 +1683,10 @@ end function decode.Linkshell(str) local status_map = {[0]='Unopened',[1]='Linkshell',[2]='Pearlsack',[3]='Linkpearl',[4]='Broken'} - local name_end = function() - if str:sub(#str,#str) ~= string.char(0) then - return #str - end - for i=#str-1,10,-1 do - if str:sub(i,i) ~= string.char(0) then - return i - end - end - end() - + local name_end = #str + while str:byte(name_end) == 0 do + name_end = name_end - 1 + end local name_map = {[0]="'",[1]="a",[2]='b',[3]='c',[4]='d',[5]='e',[6]='f',[7]='g',[8]='h',[9]='i',[10]='j', [11]='k',[12]='l',[13]='m',[14]='n',[15]='o',[16]='p',[17]='q',[18]='r',[19]='s',[20]='t',[21]='u',[22]='v',[23]='w', [24]='x',[25]='yx',[26]='z',[27]='A',[28]='B',[29]='C',[30]='D',[31]='E',[32]='F',[33]='G',[34]='H',[35]='I',[36]='J', From 9cfde8c039c47ea5ecef204772e82153eb9e8ed6 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sat, 13 Feb 2021 12:01:15 +0000 Subject: [PATCH 0557/1002] Update extdata.lua --- addons/libs/extdata.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/extdata.lua b/addons/libs/extdata.lua index 5bec6cc42d..61f73a2d94 100644 --- a/addons/libs/extdata.lua +++ b/addons/libs/extdata.lua @@ -1684,7 +1684,7 @@ end function decode.Linkshell(str) local status_map = {[0]='Unopened',[1]='Linkshell',[2]='Pearlsack',[3]='Linkpearl',[4]='Broken'} local name_end = #str - while str:byte(name_end) == 0 do + while str:byte(name_end) == 0 and name_end > 10 do name_end = name_end - 1 end local name_map = {[0]="'",[1]="a",[2]='b',[3]='c',[4]='d',[5]='e',[6]='f',[7]='g',[8]='h',[9]='i',[10]='j', From 4d5c3c3bd77499e98add922227cbca293b71c615 Mon Sep 17 00:00:00 2001 From: dtw <362017+dtw@users.noreply.github.com> Date: Sat, 13 Feb 2021 16:55:40 +0000 Subject: [PATCH 0558/1002] Whitespace --- addons/macrochanger/macrochanger.lua | 142 +++++++++++++-------------- 1 file changed, 70 insertions(+), 72 deletions(-) diff --git a/addons/macrochanger/macrochanger.lua b/addons/macrochanger/macrochanger.lua index 23af75acc4..232ed0967e 100644 --- a/addons/macrochanger/macrochanger.lua +++ b/addons/macrochanger/macrochanger.lua @@ -33,7 +33,7 @@ require('strings') require('logger') windower.register_event('load', function() - globaldisable = 0 + globaldisable = 0 macros = { WAR = {Book = '', Page = ''}, MNK = {Book = '', Page = ''}, @@ -58,31 +58,31 @@ windower.register_event('load', function() GEO = {Book = '', Page = ''}, RUN = {Book = '', Page = ''}, } - options_load() + options_load() end) function options_load() - local f = io.open(windower.addon_path..'data/settings.txt', "r") - if f == nil then - local g = io.open(windower.addon_path..'data/settings.txt', "w") - g:write('Release Date: 9:00 PM, 4-01-13\46\n') - g:write('Author Comment: This document is whitespace sensitive, which means that you need the same number of spaces between things as exist in this initial settings file\46\n') - g:write('Author Comment: It looks at the first two words separated by spaces and then takes anything as the value in question if the first two words are relevant\46\n') - g:write('Author Comment: If you ever mess it up so that it does not work, you can just delete it and MacroChanger will regenerate it upon reload\46\n') - g:write('Author Comment: For the output customization lines, simply place the book and page number that you would like to change to upon a job change.\46\n') - g:write('Author Comment: If 2 jobs share a book, you can place the same book number for each job, then put their individual pages.\46\n') - g:write('Author Comment: Example: BLM and SCH both use Macro Book 2: BLM uses page 3. SCH uses page 1.\46\n') - g:write('Author Comment: Put BLM Book: 2, BLM Page: 3, SCH Book: 2, SCH Page: 1.\46\n') - g:write('Author Comment: If you wish to disable auto-macro Changing for a specific job, type "disabled" instead of a book number. (e.g. BLM Book: disabled)\n') - g:write('Author Comment: The design of the settings file is credited to Byrthnoth as well as the creation of the settings file.\n\n\n') - g:write('File Settings: Fill in below\n') - g:write('Disable All: 0\n') - g:write('WAR Book: 1\nWAR Page: 1\nMNK Book: 2\nMNK Page: 1\nWHM Book: 3\nWHM Page: 1\nBLM Book: 4\nBLM Page: 1\nRDM Book: 5\nRDM Page: 1\nTHF Book: 6\nTHF Page: 1\n') - g:write('PLD Book: 7\nPLD Page: 1\nDRK Book: 8\nDRK Page: 1\nBST Book: 9\nBST Page: 1\nBRD Book: 10\nBRD Page: 1\nRNG Book: 11\nRNG Page: 1\nSAM Book: 12\nSAM Page: 1\n') - g:write('NIN Book: 13\nNIN Page: 1\nDRG Book: 14\nDRG Page: 1\nSMN Book: 15\nSMN Page: 1\nBLU Book: 16\nBLU Page: 1\nCOR Book: 17\nCOR Page: 1\nPUP Book: 18\nPUP Page: 1\n') - g:write('DNC Book: 19\nDNC Page: 1\nSCH Book: 20\nSCH Page: 1\nGEO Book: 20\nGEO Page: 1\nRUN Book: 20\nRUN Page: 1\n') - g:close() - DisableAll = 0 + local f = io.open(windower.addon_path..'data/settings.txt', "r") + if f == nil then + local g = io.open(windower.addon_path..'data/settings.txt', "w") + g:write('Release Date: 9:00 PM, 4-01-13\46\n') + g:write('Author Comment: This document is whitespace sensitive, which means that you need the same number of spaces between things as exist in this initial settings file\46\n') + g:write('Author Comment: It looks at the first two words separated by spaces and then takes anything as the value in question if the first two words are relevant\46\n') + g:write('Author Comment: If you ever mess it up so that it does not work, you can just delete it and MacroChanger will regenerate it upon reload\46\n') + g:write('Author Comment: For the output customization lines, simply place the book and page number that you would like to change to upon a job change.\46\n') + g:write('Author Comment: If 2 jobs share a book, you can place the same book number for each job, then put their individual pages.\46\n') + g:write('Author Comment: Example: BLM and SCH both use Macro Book 2: BLM uses page 3. SCH uses page 1.\46\n') + g:write('Author Comment: Put BLM Book: 2, BLM Page: 3, SCH Book: 2, SCH Page: 1.\46\n') + g:write('Author Comment: If you wish to disable auto-macro Changing for a specific job, type "disabled" instead of a book number. (e.g. BLM Book: disabled)\n') + g:write('Author Comment: The design of the settings file is credited to Byrthnoth as well as the creation of the settings file.\n\n\n') + g:write('File Settings: Fill in below\n') + g:write('Disable All: 0\n') + g:write('WAR Book: 1\nWAR Page: 1\nMNK Book: 2\nMNK Page: 1\nWHM Book: 3\nWHM Page: 1\nBLM Book: 4\nBLM Page: 1\nRDM Book: 5\nRDM Page: 1\nTHF Book: 6\nTHF Page: 1\n') + g:write('PLD Book: 7\nPLD Page: 1\nDRK Book: 8\nDRK Page: 1\nBST Book: 9\nBST Page: 1\nBRD Book: 10\nBRD Page: 1\nRNG Book: 11\nRNG Page: 1\nSAM Book: 12\nSAM Page: 1\n') + g:write('NIN Book: 13\nNIN Page: 1\nDRG Book: 14\nDRG Page: 1\nSMN Book: 15\nSMN Page: 1\nBLU Book: 16\nBLU Page: 1\nCOR Book: 17\nCOR Page: 1\nPUP Book: 18\nPUP Page: 1\n') + g:write('DNC Book: 19\nDNC Page: 1\nSCH Book: 20\nSCH Page: 1\nGEO Book: 20\nGEO Page: 1\nRUN Book: 20\nRUN Page: 1\n') + g:close() + DisableAll = 0 macros = { WAR = {Book = '1', Page = '1'}, MNK = {Book = '2', Page = '1'}, @@ -107,63 +107,61 @@ function options_load() GEO = {Book = '20', Page = '1'}, RUN = {Book = '20', Page = '1'}, } - print('Default settings file created') - notice('MacroChanger created a settings file and loaded!') - else - f:close() - for curline in io.lines(windower.addon_path..'data/settings.txt') do - local splat = curline:gsub(':',''):split(' ') - local cmd = '' - if splat[1] and macros[splat[1]:upper()] and splat[2] ~=nil and (splat[2]:lower() == 'book' or splat[2]:lower() == 'page') and splat[3] then - macros[splat[1]:upper()][splat[2]:ucfirst()] = splat[3] -- Instead of a number, this can also be 'disabled' - elseif splat[1] and splat[2] and (splat[1]..' '..splat[2]) == 'disable all' and tonumber(splat[3]) then - globaldisable = tonumber(splat[3]) - end - end - notice('MacroChanger read from a settings file and loaded!') - end + print('Default settings file created') + notice('MacroChanger created a settings file and loaded!') + else + f:close() + for curline in io.lines(windower.addon_path..'data/settings.txt') do + local splat = curline:gsub(':',''):split(' ') + local cmd = '' + if splat[1] and macros[splat[1]:upper()] and splat[2] ~=nil and (splat[2]:lower() == 'book' or splat[2]:lower() == 'page') and splat[3] then + macros[splat[1]:upper()][splat[2]:ucfirst()] = splat[3] -- Instead of a number, this can also be 'disabled' + elseif splat[1] and splat[2] and (splat[1]..' '..splat[2]) == 'disable all' and tonumber(splat[3]) then + globaldisable = tonumber(splat[3]) + end + end + notice('MacroChanger read from a settings file and loaded!') + end end windower.register_event('job change',function () -- Could use the job ID passed into this function, but the addon would have to include the resources library - local job = windower.ffxi.get_player().main_job - local book = '' - local page = '' - if globaldisable == 0 then + local job = windower.ffxi.get_player().main_job + local book = '' + local page = '' + if globaldisable == 0 then if job and macros[job] then - book = macros[job].Book - page = macros[job].Page - end + book = macros[job].Book + page = macros[job].Page + end - if ((book == 'disabled') or (page == 'disabled')) then - notice('Auto Macro Switching Disabled for ' .. job ..'.') - else - log('Job changed to ' .. job .. ' - switched to Book: ' .. book .. ' and Page: ' .. page) - windower.send_command('input /macro book '..book..';wait 0.2;input /macro set '..page..';') - end - elseif globaldisable == 1 then - - notice('Auto Macro Switching Disabled for All Jobs.') - - end + if ((book == 'disabled') or (page == 'disabled')) then + notice('Auto Macro Switching Disabled for ' .. job ..'.') + else + log('Job changed to ' .. job .. ' - switched to Book: ' .. book .. ' and Page: ' .. page) + windower.send_command('input /macro book '..book..';wait 0.2;input /macro set '..page..';') + end + elseif globaldisable == 1 then + notice('Auto Macro Switching Disabled for All Jobs.') + end end) windower.register_event('addon command', function(...) local args = {...} - local mjob = windower.ffxi.get_player().main_job - if args[1] == 'disableall' then - if args[2] == 'on' then - globaldisable = 1 - warning('All automated macro switching disabled.') - elseif args[2] == 'off' then - globaldisable = 0 - notice('Automated macro switching enabled.') - end - elseif args[1]:lower() == 'help' then - log('MacroChanger Commands:') - log('disableall [on|off]') - log(' on - Disables all automated macro switching') - log(' off - Enables all automated macro switching not disabled individually') - log('Resets to what is stored in settings upon unloading of addon. To Permanently change, please change the option in the settings file.') - end + local mjob = windower.ffxi.get_player().main_job + if args[1] == 'disableall' then + if args[2] == 'on' then + globaldisable = 1 + warning('All automated macro switching disabled.') + elseif args[2] == 'off' then + globaldisable = 0 + notice('Automated macro switching enabled.') + end + elseif args[1]:lower() == 'help' then + log('MacroChanger Commands:') + log('disableall [on|off]') + log(' on - Disables all automated macro switching') + log(' off - Enables all automated macro switching not disabled individually') + log('Resets to what is stored in settings upon unloading of addon. To Permanently change, please change the option in the settings file.') + end end) From 4a0a24112ffc57fca7034808d0e58c3f59aaea5b Mon Sep 17 00:00:00 2001 From: dtw <362017+dtw@users.noreply.github.com> Date: Sat, 13 Feb 2021 16:56:29 +0000 Subject: [PATCH 0559/1002] Switch warning to notice --- addons/macrochanger/macrochanger.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/macrochanger/macrochanger.lua b/addons/macrochanger/macrochanger.lua index 232ed0967e..784b54ba71 100644 --- a/addons/macrochanger/macrochanger.lua +++ b/addons/macrochanger/macrochanger.lua @@ -152,7 +152,7 @@ windower.register_event('addon command', function(...) if args[1] == 'disableall' then if args[2] == 'on' then globaldisable = 1 - warning('All automated macro switching disabled.') + notice('All automated macro switching disabled.') elseif args[2] == 'off' then globaldisable = 0 notice('Automated macro switching enabled.') From 24f3fb0f3561304d3cd0fc6d14393487e7825884 Mon Sep 17 00:00:00 2001 From: dtw <362017+dtw@users.noreply.github.com> Date: Sat, 13 Feb 2021 16:57:01 +0000 Subject: [PATCH 0560/1002] Use coroutine.sleep --- addons/macrochanger/macrochanger.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/addons/macrochanger/macrochanger.lua b/addons/macrochanger/macrochanger.lua index 784b54ba71..e535121325 100644 --- a/addons/macrochanger/macrochanger.lua +++ b/addons/macrochanger/macrochanger.lua @@ -139,7 +139,9 @@ windower.register_event('job change',function () notice('Auto Macro Switching Disabled for ' .. job ..'.') else log('Job changed to ' .. job .. ' - switched to Book: ' .. book .. ' and Page: ' .. page) - windower.send_command('input /macro book '..book..';wait 0.2;input /macro set '..page..';') + windower.chat.input('/macro book ' .. book) + coroutine.sleep(0.2) + windower.chat.input('/macro set ' .. page) end elseif globaldisable == 1 then notice('Auto Macro Switching Disabled for All Jobs.') From 3b2700ca4198b1986047b2f046366b7f123c3e86 Mon Sep 17 00:00:00 2001 From: dtw <362017+dtw@users.noreply.github.com> Date: Sat, 13 Feb 2021 17:19:32 +0000 Subject: [PATCH 0561/1002] Whitespace Moar! --- addons/macrochanger/macrochanger.lua | 235 +++++++++++++-------------- 1 file changed, 117 insertions(+), 118 deletions(-) diff --git a/addons/macrochanger/macrochanger.lua b/addons/macrochanger/macrochanger.lua index e535121325..592de141ee 100644 --- a/addons/macrochanger/macrochanger.lua +++ b/addons/macrochanger/macrochanger.lua @@ -33,137 +33,136 @@ require('strings') require('logger') windower.register_event('load', function() - globaldisable = 0 - macros = { - WAR = {Book = '', Page = ''}, - MNK = {Book = '', Page = ''}, - WHM = {Book = '', Page = ''}, - BLM = {Book = '', Page = ''}, - RDM = {Book = '', Page = ''}, - THF = {Book = '', Page = ''}, - PLD = {Book = '', Page = ''}, - DRK = {Book = '', Page = ''}, - BST = {Book = '', Page = ''}, - BRD = {Book = '', Page = ''}, - RNG = {Book = '', Page = ''}, - SAM = {Book = '', Page = ''}, - NIN = {Book = '', Page = ''}, - DRG = {Book = '', Page = ''}, - SMN = {Book = '', Page = ''}, - BLU = {Book = '', Page = ''}, - COR = {Book = '', Page = ''}, - PUP = {Book = '', Page = ''}, - DNC = {Book = '', Page = ''}, - SCH = {Book = '', Page = ''}, - GEO = {Book = '', Page = ''}, - RUN = {Book = '', Page = ''}, - } - options_load() + globaldisable = 0 + macros = { + WAR = {Book = '', Page = ''}, + MNK = {Book = '', Page = ''}, + WHM = {Book = '', Page = ''}, + BLM = {Book = '', Page = ''}, + RDM = {Book = '', Page = ''}, + THF = {Book = '', Page = ''}, + PLD = {Book = '', Page = ''}, + DRK = {Book = '', Page = ''}, + BST = {Book = '', Page = ''}, + BRD = {Book = '', Page = ''}, + RNG = {Book = '', Page = ''}, + SAM = {Book = '', Page = ''}, + NIN = {Book = '', Page = ''}, + DRG = {Book = '', Page = ''}, + SMN = {Book = '', Page = ''}, + BLU = {Book = '', Page = ''}, + COR = {Book = '', Page = ''}, + PUP = {Book = '', Page = ''}, + DNC = {Book = '', Page = ''}, + SCH = {Book = '', Page = ''}, + GEO = {Book = '', Page = ''}, + RUN = {Book = '', Page = ''}, + } + options_load() end) function options_load() - local f = io.open(windower.addon_path..'data/settings.txt', "r") - if f == nil then - local g = io.open(windower.addon_path..'data/settings.txt', "w") - g:write('Release Date: 9:00 PM, 4-01-13\46\n') - g:write('Author Comment: This document is whitespace sensitive, which means that you need the same number of spaces between things as exist in this initial settings file\46\n') - g:write('Author Comment: It looks at the first two words separated by spaces and then takes anything as the value in question if the first two words are relevant\46\n') - g:write('Author Comment: If you ever mess it up so that it does not work, you can just delete it and MacroChanger will regenerate it upon reload\46\n') - g:write('Author Comment: For the output customization lines, simply place the book and page number that you would like to change to upon a job change.\46\n') - g:write('Author Comment: If 2 jobs share a book, you can place the same book number for each job, then put their individual pages.\46\n') - g:write('Author Comment: Example: BLM and SCH both use Macro Book 2: BLM uses page 3. SCH uses page 1.\46\n') - g:write('Author Comment: Put BLM Book: 2, BLM Page: 3, SCH Book: 2, SCH Page: 1.\46\n') - g:write('Author Comment: If you wish to disable auto-macro Changing for a specific job, type "disabled" instead of a book number. (e.g. BLM Book: disabled)\n') - g:write('Author Comment: The design of the settings file is credited to Byrthnoth as well as the creation of the settings file.\n\n\n') - g:write('File Settings: Fill in below\n') - g:write('Disable All: 0\n') - g:write('WAR Book: 1\nWAR Page: 1\nMNK Book: 2\nMNK Page: 1\nWHM Book: 3\nWHM Page: 1\nBLM Book: 4\nBLM Page: 1\nRDM Book: 5\nRDM Page: 1\nTHF Book: 6\nTHF Page: 1\n') - g:write('PLD Book: 7\nPLD Page: 1\nDRK Book: 8\nDRK Page: 1\nBST Book: 9\nBST Page: 1\nBRD Book: 10\nBRD Page: 1\nRNG Book: 11\nRNG Page: 1\nSAM Book: 12\nSAM Page: 1\n') - g:write('NIN Book: 13\nNIN Page: 1\nDRG Book: 14\nDRG Page: 1\nSMN Book: 15\nSMN Page: 1\nBLU Book: 16\nBLU Page: 1\nCOR Book: 17\nCOR Page: 1\nPUP Book: 18\nPUP Page: 1\n') - g:write('DNC Book: 19\nDNC Page: 1\nSCH Book: 20\nSCH Page: 1\nGEO Book: 20\nGEO Page: 1\nRUN Book: 20\nRUN Page: 1\n') - g:close() - DisableAll = 0 - macros = { - WAR = {Book = '1', Page = '1'}, - MNK = {Book = '2', Page = '1'}, - WHM = {Book = '3', Page = '1'}, - BLM = {Book = '4', Page = '1'}, - RDM = {Book = '5', Page = '1'}, - THF = {Book = '6', Page = '1'}, - PLD = {Book = '7', Page = '1'}, - DRK = {Book = '8', Page = '1'}, - BST = {Book = '9', Page = '1'}, - BRD = {Book = '10', Page = '1'}, - RNG = {Book = '11', Page = '1'}, - SAM = {Book = '12', Page = '1'}, - NIN = {Book = '13', Page = '1'}, - DRG = {Book = '14', Page = '1'}, - SMN = {Book = '15', Page = '1'}, - BLU = {Book = '16', Page = '1'}, - COR = {Book = '17', Page = '1'}, - PUP = {Book = '18', Page = '1'}, - DNC = {Book = '19', Page = '1'}, - SCH = {Book = '20', Page = '1'}, - GEO = {Book = '20', Page = '1'}, - RUN = {Book = '20', Page = '1'}, - } - print('Default settings file created') - notice('MacroChanger created a settings file and loaded!') - else - f:close() - for curline in io.lines(windower.addon_path..'data/settings.txt') do - local splat = curline:gsub(':',''):split(' ') - local cmd = '' - if splat[1] and macros[splat[1]:upper()] and splat[2] ~=nil and (splat[2]:lower() == 'book' or splat[2]:lower() == 'page') and splat[3] then - macros[splat[1]:upper()][splat[2]:ucfirst()] = splat[3] -- Instead of a number, this can also be 'disabled' - elseif splat[1] and splat[2] and (splat[1]..' '..splat[2]) == 'disable all' and tonumber(splat[3]) then - globaldisable = tonumber(splat[3]) - end + local f = io.open(windower.addon_path..'data/settings.txt', "r") + if f == nil then + local g = io.open(windower.addon_path..'data/settings.txt', "w") + g:write('Release Date: 9:00 PM, 4-01-13\46\n') + g:write('Author Comment: This document is whitespace sensitive, which means that you need the same number of spaces between things as exist in this initial settings file\46\n') + g:write('Author Comment: It looks at the first two words separated by spaces and then takes anything as the value in question if the first two words are relevant\46\n') + g:write('Author Comment: If you ever mess it up so that it does not work, you can just delete it and MacroChanger will regenerate it upon reload\46\n') + g:write('Author Comment: For the output customization lines, simply place the book and page number that you would like to change to upon a job change.\46\n') + g:write('Author Comment: If 2 jobs share a book, you can place the same book number for each job, then put their individual pages.\46\n') + g:write('Author Comment: Example: BLM and SCH both use Macro Book 2: BLM uses page 3. SCH uses page 1.\46\n') + g:write('Author Comment: Put BLM Book: 2, BLM Page: 3, SCH Book: 2, SCH Page: 1.\46\n') + g:write('Author Comment: If you wish to disable auto-macro Changing for a specific job, type "disabled" instead of a book number. (e.g. BLM Book: disabled)\n') + g:write('Author Comment: The design of the settings file is credited to Byrthnoth as well as the creation of the settings file.\n\n\n') + g:write('File Settings: Fill in below\n') + g:write('Disable All: 0\n') + g:write('WAR Book: 1\nWAR Page: 1\nMNK Book: 2\nMNK Page: 1\nWHM Book: 3\nWHM Page: 1\nBLM Book: 4\nBLM Page: 1\nRDM Book: 5\nRDM Page: 1\nTHF Book: 6\nTHF Page: 1\n') + g:write('PLD Book: 7\nPLD Page: 1\nDRK Book: 8\nDRK Page: 1\nBST Book: 9\nBST Page: 1\nBRD Book: 10\nBRD Page: 1\nRNG Book: 11\nRNG Page: 1\nSAM Book: 12\nSAM Page: 1\n') + g:write('NIN Book: 13\nNIN Page: 1\nDRG Book: 14\nDRG Page: 1\nSMN Book: 15\nSMN Page: 1\nBLU Book: 16\nBLU Page: 1\nCOR Book: 17\nCOR Page: 1\nPUP Book: 18\nPUP Page: 1\n') + g:write('DNC Book: 19\nDNC Page: 1\nSCH Book: 20\nSCH Page: 1\nGEO Book: 20\nGEO Page: 1\nRUN Book: 20\nRUN Page: 1\n') + g:close() + DisableAll = 0 + macros = { + WAR = {Book = '1', Page = '1'}, + MNK = {Book = '2', Page = '1'}, + WHM = {Book = '3', Page = '1'}, + BLM = {Book = '4', Page = '1'}, + RDM = {Book = '5', Page = '1'}, + THF = {Book = '6', Page = '1'}, + PLD = {Book = '7', Page = '1'}, + DRK = {Book = '8', Page = '1'}, + BST = {Book = '9', Page = '1'}, + BRD = {Book = '10', Page = '1'}, + RNG = {Book = '11', Page = '1'}, + SAM = {Book = '12', Page = '1'}, + NIN = {Book = '13', Page = '1'}, + DRG = {Book = '14', Page = '1'}, + SMN = {Book = '15', Page = '1'}, + BLU = {Book = '16', Page = '1'}, + COR = {Book = '17', Page = '1'}, + PUP = {Book = '18', Page = '1'}, + DNC = {Book = '19', Page = '1'}, + SCH = {Book = '20', Page = '1'}, + GEO = {Book = '20', Page = '1'}, + RUN = {Book = '20', Page = '1'}, + } + print('Default settings file created') + notice('MacroChanger created a settings file and loaded!') + else + f:close() + for curline in io.lines(windower.addon_path..'data/settings.txt') do + local splat = curline:gsub(':',''):split(' ') + local cmd = '' + if splat[1] and macros[splat[1]:upper()] and splat[2] ~=nil and (splat[2]:lower() == 'book' or splat[2]:lower() == 'page') and splat[3] then + macros[splat[1]:upper()][splat[2]:ucfirst()] = splat[3] -- Instead of a number, this can also be 'disabled' + elseif splat[1] and splat[2] and (splat[1]..' '..splat[2]) == 'disable all' and tonumber(splat[3]) then + globaldisable = tonumber(splat[3]) + end + end + notice('MacroChanger read from a settings file and loaded!') end - notice('MacroChanger read from a settings file and loaded!') - end end windower.register_event('job change',function () -- Could use the job ID passed into this function, but the addon would have to include the resources library - local job = windower.ffxi.get_player().main_job - local book = '' - local page = '' - if globaldisable == 0 then + local job = windower.ffxi.get_player().main_job + local book = '' + local page = '' + if globaldisable == 0 then if job and macros[job] then - book = macros[job].Book - page = macros[job].Page - end - - if ((book == 'disabled') or (page == 'disabled')) then - notice('Auto Macro Switching Disabled for ' .. job ..'.') - else - log('Job changed to ' .. job .. ' - switched to Book: ' .. book .. ' and Page: ' .. page) - windower.chat.input('/macro book ' .. book) - coroutine.sleep(0.2) - windower.chat.input('/macro set ' .. page) + book = macros[job].Book + page = macros[job].Page + end + if ((book == 'disabled') or (page == 'disabled')) then + notice('Auto Macro Switching Disabled for ' .. job ..'.') + else + log('Job changed to ' .. job .. ' - switched to Book: ' .. book .. ' and Page: ' .. page) + windower.chat.input('/macro book ' .. book) + coroutine.sleep(0.2) + windower.chat.input('/macro set ' .. page) + end + elseif globaldisable == 1 then + notice('Auto Macro Switching Disabled for All Jobs.') end - elseif globaldisable == 1 then - notice('Auto Macro Switching Disabled for All Jobs.') - end end) windower.register_event('addon command', function(...) local args = {...} - local mjob = windower.ffxi.get_player().main_job - if args[1] == 'disableall' then - if args[2] == 'on' then - globaldisable = 1 - notice('All automated macro switching disabled.') - elseif args[2] == 'off' then - globaldisable = 0 - notice('Automated macro switching enabled.') + local mjob = windower.ffxi.get_player().main_job + if args[1] == 'disableall' then + if args[2] == 'on' then + globaldisable = 1 + notice('All automated macro switching disabled.') + elseif args[2] == 'off' then + globaldisable = 0 + notice('Automated macro switching enabled.') + end + elseif args[1]:lower() == 'help' then + log('MacroChanger Commands:') + log('disableall [on|off]') + log(' on - Disables all automated macro switching') + log(' off - Enables all automated macro switching not disabled individually') + log('Resets to what is stored in settings upon unloading of addon. To Permanently change, please change the option in the settings file.') end - elseif args[1]:lower() == 'help' then - log('MacroChanger Commands:') - log('disableall [on|off]') - log(' on - Disables all automated macro switching') - log(' off - Enables all automated macro switching not disabled individually') - log('Resets to what is stored in settings upon unloading of addon. To Permanently change, please change the option in the settings file.') - end end) From 272ce4ec6712cccf2cc0b66eac9a6d858cce0262 Mon Sep 17 00:00:00 2001 From: Ian Anderson Date: Mon, 15 Feb 2021 03:39:44 -0800 Subject: [PATCH 0562/1002] Update fields.lua Change errors in fields for 0x064 and 0x075 --- addons/libs/packets/fields.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index a2f90857da..b96a068bcc 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -733,7 +733,7 @@ fields.outgoing[0x063] = L{ --"New" Key Item examination packet fields.outgoing[0x064] = L{ {ctype='unsigned int', label='Player', fn=id}, -- 04 - {ctype='byte[0x40]', label='flags'}, -- 08 These correspond to a particular section of the 0x55 incoming packet + {ctype='data[0x40]', label='flags'}, -- 08 These correspond to a particular section of the 0x55 incoming packet {ctype='unsigned int', label='_unknown1'}, -- 48 This field somehow denotes which half-0x55-packet the flags corresponds to } @@ -3133,7 +3133,7 @@ fields.incoming[0x075] = L{ {ctype='unsigned int', label='Fight Designation'}, -- 04 Anything other than 0 makes a timer. 0 deletes the timer. {ctype='unsigned int', label='Timestamp Offset', fn=time}, -- 08 Number of seconds since 15:00:00 GMT 31/12/2002 (0x3C307D70) {ctype='unsigned int', label='Fight Duration', fn=time}, -- 0C - {ctype='byte[12]', label='_unknown1'}, -- 10 This packet clearly needs position information, but it's unclear how these bytes carry it + {ctype='data[12]', label='_unknown1'}, -- 10 This packet clearly needs position information, but it's unclear how these bytes carry it {ctype='unsigned int', label='Battlefield Radius'}, -- 1C Yalms*1000, so a 50 yalm battlefield would have 50,000 for this field {ctype='unsigned int', label='Render Radius'}, -- 20 Yalms*1000, so a fence that renders when you're 25 yalms away would have 25,000 for this field } From 93dd76efec9113ad414954a537931b836cbcb10f Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Wed, 17 Feb 2021 13:59:52 +0000 Subject: [PATCH 0563/1002] Minor change to functions.schedule Functions.schedule now returns the coroutine created by coroutine.schedule. --- addons/libs/functions.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/libs/functions.lua b/addons/libs/functions.lua index eaefbd7fb7..5dc15f3004 100644 --- a/addons/libs/functions.lua +++ b/addons/libs/functions.lua @@ -145,9 +145,9 @@ function functions.it(fn, ...) end end --- Schedules the current function to run delayed by the provided time in seconds +-- Schedules the current function to run delayed by the provided time in seconds and returns the coroutine function functions.schedule(fn, time, ...) - coroutine.schedule(fn:prepare(...), time) + return coroutine.schedule(fn:prepare(...), time) end -- Returns a function that, when called, will execute the underlying function delayed by the provided number of seconds @@ -495,7 +495,7 @@ function string.map(str, fn) end --[[ -Copyright 2013-2015, Windower +Copyright © 2013-2015, Windower All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: From f70c941fb15d674d67abf35fa62eac2ad38ef84b Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Fri, 19 Feb 2021 22:18:57 +0000 Subject: [PATCH 0564/1002] Bugfix Fixing bugs because I'm a real dev (Fixed bug where characters with the same name as one of the methods defined in tables.lua would cause an error in the tables library.) --- addons/libs/config.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/config.lua b/addons/libs/config.lua index 11148d7d02..7829c7f199 100644 --- a/addons/libs/config.lua +++ b/addons/libs/config.lua @@ -115,7 +115,7 @@ function parse(settings) local full_parsed = parsed.global local player = windower.ffxi.get_player() if player then - full_parsed = full_parsed:update(parsed[player.name:lower()], true) + full_parsed = table.update(full_parsed, rawget(parsed, player.name:lower()), true) end return settings:update(full_parsed, true) @@ -133,7 +133,7 @@ function parse(settings) local player = windower.ffxi.get_player() if player then - full_parsed = full_parsed:update(parsed[player.name:lower()], true) + full_parsed = table.update(full_parsed, rawget(parsed, player.name:lower()), true) end return merge(settings, full_parsed) From 191bc6fa1db5ef53dacb37a9ea0172b11bea99b0 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Tue, 2 Mar 2021 08:51:48 -0500 Subject: [PATCH 0565/1002] Fixes for Kenshi Slip data so it doesn't break stuff. SE skipped an index so we're using 0 as it is not part of item ids as a placeholder. --- addons/libs/slips.lua | 2 +- addons/organizer/organizer.lua | 6 ++++-- addons/porter/porter.lua | 22 ++++++++++++---------- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 495e624b24..67edbaa3b7 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757}, -- 191 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453,}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454,}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489}, -- 129 + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489}, -- 130 SE Skipped an index hence the 0 as one of the items [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770}, --174 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330,}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665,}, --115 diff --git a/addons/organizer/organizer.lua b/addons/organizer/organizer.lua index 92d0853dea..0d56089c39 100644 --- a/addons/organizer/organizer.lua +++ b/addons/organizer/organizer.lua @@ -186,8 +186,10 @@ function options_load( ) slip_lists = require('slips') for slip_id,slip_list in pairs(slip_lists.items) do for item_id in slip_list:it() do - _retain[item_id] = "moogle slip" - org_debug("settings", "Adding ("..res.items[item_id].english..') to slip retain list') + if item_id ~= 0 then + _retain[item_id] = "moogle slip" + org_debug("settings", "Adding ("..res.items[item_id].english..') to slip retain list') + end end end end diff --git a/addons/porter/porter.lua b/addons/porter/porter.lua index b10c2eae39..10774b5277 100644 --- a/addons/porter/porter.lua +++ b/addons/porter/porter.lua @@ -83,15 +83,17 @@ function show_slip(slip_number, slip_page, owned_only) end for item_position, item_id in ipairs(slip_items) do - local is_contained = player_slip_items:contains(item_id) - - if owned_only == false or owned_only == true and is_contained == true then - windower.add_to_chat( - 55, - ('slip '..printable_slip_number..'/page '..tostring(slip_page and slip_page or math.ceil(item_position / 16)):lpad('0', 2)..':'):color(259)..' '.. - res.items[item_id].name:color(is_contained and 258 or 261) - ) - end + if item_id ~= 0 then + local is_contained = player_slip_items:contains(item_id) + + if owned_only == false or owned_only == true and is_contained == true then + windower.add_to_chat( + 55, + ('slip '..printable_slip_number..'/page '..tostring(slip_page and slip_page or math.ceil(item_position / 16)):lpad('0', 2)..':'):color(259)..' '.. + res.items[item_id].name:color(is_contained and 258 or 261) + ) + end + end end end end @@ -105,7 +107,7 @@ function show_bags() for _, item in ipairs(windower.ffxi.get_items(bag)) do local slip_id = slips.get_slip_id_by_item_id(item.id) - if slip_id then + if slip_id and item_id ~= 0 then n = n + 1 windower.add_to_chat(207, 'slip %02d: %s %s':format(slips.get_slip_number_by_id(slip_id), bag, res.items[item.id].name:color(258))) end From 99f001f0f8b2f7c31b69dded721126f15b7802e6 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Tue, 2 Mar 2021 08:59:56 -0500 Subject: [PATCH 0566/1002] Versions Bumps... --- addons/organizer/organizer.lua | 2 +- addons/porter/porter.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/organizer/organizer.lua b/addons/organizer/organizer.lua index 0d56089c39..7e04f14b28 100644 --- a/addons/organizer/organizer.lua +++ b/addons/organizer/organizer.lua @@ -38,7 +38,7 @@ slips = require 'slips' _addon.name = 'Organizer' _addon.author = 'Byrth, maintainer: Rooks' -_addon.version = 0.20200714 +_addon.version = 0.20210302 _addon.commands = {'organizer','org'} _static = { diff --git a/addons/porter/porter.lua b/addons/porter/porter.lua index 10774b5277..39ca8d6f9a 100644 --- a/addons/porter/porter.lua +++ b/addons/porter/porter.lua @@ -36,7 +36,7 @@ res = require 'resources' slips = require 'slips' _addon.name = 'porter' -_addon.version = '1.20200419' +_addon.version = '1.20210302' _addon.command = 'porter' _addon.author = 'Zohno' From e863250f4a23f9236de699ac0401c56aec5e2ca5 Mon Sep 17 00:00:00 2001 From: Tyler Schneider Date: Sun, 7 Mar 2021 15:39:28 -0700 Subject: [PATCH 0567/1002] Added mount music field to incoming 0x00A packet --- addons/libs/packets/fields.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index b96a068bcc..283aded25d 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1243,7 +1243,8 @@ fields.incoming[0x00A] = L{ {ctype='unsigned short', label='Night Music'}, -- 58 {ctype='unsigned short', label='Solo Combat Music'}, -- 5A {ctype='unsigned short', label='Party Combat Music'}, -- 5C - {ctype='data[4]', label='_unknown4'}, -- 5E + {ctype='unsigned short', label='Mount Music'}, -- 5E + {ctype='data[2]', label='_unknown4'}, -- 60 {ctype='unsigned short', label='Menu Zone'}, -- 62 Only set if the menu ID is sent, used as the zone for menu responses (0x5b, 0x5c) {ctype='unsigned short', label='Menu ID'}, -- 64 {ctype='unsigned short', label='_unknown5'}, -- 66 From ec6acd0476b2247afa26f95d501eb6e82fed084a Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Fri, 12 Mar 2021 12:19:47 -0700 Subject: [PATCH 0568/1002] Pouches Allow Auto-translate --- addons/Pouches/Pouches.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/addons/Pouches/Pouches.lua b/addons/Pouches/Pouches.lua index 815278f5cc..d935ad1868 100644 --- a/addons/Pouches/Pouches.lua +++ b/addons/Pouches/Pouches.lua @@ -58,9 +58,8 @@ end windower.register_event('addon command', function(...) local inv = windower.ffxi.get_items(0) -- get main inventory - local args = T{...}:map(string.lower) - item.name = table.concat(args," ") + item.name = windower.convert_auto_trans(table.concat({...}," ")):lower() item.count = 0 if inverted[item.name] == nil then log('Item, "'..item.name..'", does not exist.') From a827f9214eb8e6c6ad9ae0f81fd4f4621c8045fb Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Sat, 13 Mar 2021 22:46:15 +0100 Subject: [PATCH 0569/1002] [Battlemod] Singular/Plural addition Added singular/plural handling. Added common/proper noum handling. Added quantity of items for message id 377 (Treasury autostack option sometimes interfere with it). Some minor changes. --- addons/battlemod/battlemod.lua | 89 ++++++++++--- addons/battlemod/generic_helpers.lua | 163 +++++++++++++++++++++++ addons/battlemod/parse_action_packet.lua | 153 +++++++++++++++++---- addons/battlemod/statics.lua | 14 +- 4 files changed, 370 insertions(+), 49 deletions(-) diff --git a/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index fdf1a25966..ca551b9827 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -12,7 +12,7 @@ require 'generic_helpers' require 'parse_action_packet' require 'statics' -_addon.version = '3.29' +_addon.version = '3.30' _addon.name = 'BattleMod' _addon.author = 'Byrth, maintainer: SnickySnacks' _addon.commands = {'bm','battlemod'} @@ -24,7 +24,7 @@ end) windower.register_event('login',function (name) if debugging then windower.debug('login') end - windower.send_command('@wait 10;lua i battlemod options_load;') + options_load:schedule(10) end) windower.register_event('addon command', function(command, ...) @@ -149,12 +149,10 @@ windower.register_event('incoming text',function (original, modified, color, col 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 - blocked = true - return blocked + return true end elseif original:endswith(endline) and string.find(original, item) then --block items action messages - blocked = true - return blocked + return true end end @@ -251,9 +249,42 @@ 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 -------- ACTION MESSAGE ------- - if id == 0x29 then +------- 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) @@ -266,6 +297,9 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec 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 @@ -284,9 +318,16 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec windower.add_to_chat(color, msg) else local msg = res.action_messages[am.message_id][language] + if plural_entities:contains(am.actor_id) then + msg = plural_actor(msg) + end + if plural_entities:contains(am.target_id) then + msg = plural_target(msg) + end + local msg = clean_msg(msg :gsub('${status}',status or '') - :gsub('${target}',targ) - :gsub('${number}',number or '') + :gsub('${target}',target_article..targ) + :gsub('${number}',number or '')) windower.add_to_chat(color, msg) end elseif am.message_id == 206 and condensetargets then -- Wears off messages @@ -307,7 +348,7 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec if not multi_targs[status] and not stat_ignore:contains(am.param_1) then multi_targs[status] = {} multi_targs[status][1] = target - windower.send_command('@wait 0.5;lua i battlemod multi_packet '..status) + multi_packet:schedule(0.5, status) elseif not (stat_ignore:contains(am.param_1)) then multi_targs[status][#multi_targs[status]+1] = target else @@ -315,16 +356,23 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec -- Sneak, Invis, etc. that you don't want to see on a delay multi_targs[status] = {} multi_targs[status][1] = target - windower.send_command('@lua i battlemod multi_packet '..status) + 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) + end + if plural_entities:contains(am.target_id) then + outstr = plural_target(outstr) + end - local fields = fieldsearch(res.action_messages[am.message_id][language]) + local fields = fieldsearch(outstr) if fields.status then - if log_form_debuffs:contains(am.param_1) 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) @@ -369,17 +417,17 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec skill = 'to be level '..am.param_1..' ('..ratings_arr[am.param_2-63]..')' end end - local outstr = (res.action_messages[am.message_id][language] - :gsub('$\123actor\125',color_it((actor.name or '') .. (actor.owner_name or ""),color_arr[actor.owner or actor.type])) + outstr = (clean_msg(outstr + :gsub('$\123actor\125',actor_article..color_it((actor.name or '') .. (actor.owner_name or ""),color_arr[actor.owner or actor.type])) :gsub('$\123status\125',status or '') :gsub('$\123item\125',color_it(item or '',color_arr.itemcol)) - :gsub('$\123target\125',color_it(target.name or '',color_arr[target.owner or target.type])) + :gsub('$\123target\125',target_article..color_it(target.name or '',color_arr[target.owner or target.type])) :gsub('$\123spell\125',color_it(spell or '',color_arr.spellcol)) :gsub('$\123skill\125',color_it(skill or '',color_arr.abilcol)) :gsub('$\123number\125',number or '') :gsub('$\123number2\125',number2 or '') :gsub('$\123skill\125',skill or '') - :gsub('$\123lb\125','\7')) + :gsub('$\123lb\125','\7'))) 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 @@ -429,9 +477,10 @@ end) function multi_packet(...) local ind = table.concat({...},' ') local targets = assemble_targets(multi_actor[ind],multi_targs[ind],0,multi_msg[ind]) - local outstr = res.action_messages[multi_msg[ind]][language] + local outstr = targets_condensed and plural_target(res.action_messages[multi_msg[ind]][language]) or res.action_messages[multi_msg[ind]][language] + outstr = clean_msg(outstr :gsub('$\123target\125',targets) - :gsub('$\123status\125',ind) + :gsub('$\123status\125',ind)) windower.add_to_chat(res.action_messages[multi_msg[ind]].color,outstr) multi_targs[ind] = nil multi_msg[ind] = nil diff --git a/addons/battlemod/generic_helpers.lua b/addons/battlemod/generic_helpers.lua index 4bb5ef14ca..1759cafcef 100644 --- a/addons/battlemod/generic_helpers.lua +++ b/addons/battlemod/generic_helpers.lua @@ -114,3 +114,166 @@ function check_filter(actor,target,category,msg) return true end + +function actor_noun(msg) + if msg then + msg = msg + :gsub('${actor}', 'The ${actor}') + end + return msg +end + +function plural_actor(msg) + if msg then + msg = msg + :gsub('${actor} hits ', '${actor} hit ') + :gsub('${actor} casts ', '${actor} cast ') + :gsub('${actor} starts ', '${actor} start ') + :gsub('${actor} defeats ', '${actor} defeat ') + :gsub('${actor} gains ', '${actor} gain ') + :gsub('${actor} attains ', '${actor} attain ') + :gsub('${actor} loses ', '${actor} lose ') + :gsub('${actor} falls ', '${actor} fall ') + :gsub("${actor}'s ", '${actor} ') + :gsub('${actor} misses ' , '${actor} miss ') + :gsub('${actor} calls ' , '${actor} call ') + :gsub('${actor} learns ' , '${actor} learn ') + :gsub('${actor} uses ' , '${actor} use ') + :gsub('${actor} is ' , '${actor} are ') + :gsub('${actor} takes ' , '${actor} take ') + :gsub('${actor} does ' , '${actor} do ') + :gsub('${actor} lacks ' , '${actor} lack ') + :gsub('${actor} redies ' , '${actor} ready ') + :gsub('${actor} earns ' , '${actor} earn ') + :gsub('${actor} scores ' , '${actor} score ') + :gsub('${actor} successfully removes ' , '${actor} successfully remove ') + :gsub('${actor} achieves ' , '${actor} achieve ') + :gsub('${actor} mugs ' , '${actor} mug ') + :gsub('${actor} steals ' , '${actor} steal ') + :gsub('${actor} fails ' , '${actor} fail ') + :gsub(' but finds nothing' , ' but find nothing') + :gsub(' and finds ${item}' , ' and find ${item}') + :gsub('${actor} recovers ' , '${actor} recover ') + :gsub('${ability}, but misses' , '${ability}, but miss') + :gsub(' but misses ${target}' , ' but miss ${target}') + :gsub('${actor} covers ' , '${actor} cover ') + :gsub('${actor} already has ' , '${actor} already have ') + :gsub('${actor} attempts ' , '${actor} attempt ') + :gsub(' but lacks ' , ' but lack ') + :gsub('${actor} destroys ' , '${actor} destroy ') + :gsub('${actor} absorbs ' , '${actor} absorb ') + :gsub('${actor} eats ' , '${actor} eat ') + :gsub('${actor} leads ' , '${actor} lead ') + :gsub('${actor} has ' , '${actor} have ') + :gsub('${actor} obtains ' , '${actor} obtain ') + :gsub(' and finds ${number}' , ' and find ${number}') + end + return msg +end + +function plural_target(msg) + if msg then + msg = msg + :gsub('${target} takes ', '${target} take ') + :gsub('${target} is ', '${target} are ') + :gsub('${target} recovers ', '${target} recover ') + :gsub("${target}'s ", '${target} ') + :gsub('${target} falls ', '${target} fall ') + :gsub('${target} uses ', '${target} use ') + :gsub('${target} resists', '${target} resist') + :gsub('${target} vanishes', '${target} vanish') + :gsub('${target} receives ', '${target} receive ') + :gsub('${target} seems ${skill}', '${target} seem ${skill}') + :gsub('${lb}It seems to have ', '${lb}They seem to have ') + :gsub('${target} gains ', '${target} gain ') + :gsub('${target} evades', '${target} evade') + :gsub('${target} regains ', '${target} regain ') + :gsub('${target} narrowly escapes ', '${target} narrowly escape ') + :gsub('${target} obtains ', '${target} obtain ') + :gsub('${target} learns ', '${target} learn ') + :gsub('${target} loses ', '${target} lose ') + :gsub('${target} was ', '${target} were ') + :gsub('${target} has ', '${target} have ') + :gsub('${target} completely resists ', '${target} completely resist ') + :gsub('${target} now has ', '${target} now have ') + :gsub('${target} feels ', '${target} feel ') + :gsub('${target} stands ', '${target} stand ') + end + return msg +end + +function clean_msg(msg) + if msg then + msg = msg + :gsub(' The ', ' the ') + msg = msg + :gsub('%. the ', '. The ') + :gsub(': the ', ': The ') + :gsub('! the ', '! The ') + end + return msg +end + +function grammatical_number_fix(msg, number) + if msg then + if number == 1 then + msg = msg + :gsub(' points', ' point') + :gsub('${number} Ballista Points', '${number} Ballista Point') + :gsub('healed of ${number} status ailments', 'healed of ${number} status ailment') + :gsub('magical effects from', 'magical effect from') + else + msg = msg + :gsub(' absorbs', ' absorb') + :gsub(' Petra', ' Petras') + :gsub('disappears', 'disappear') + :gsub('attributes is', 'attributes are') + :gsub('status effect is', 'status effects are') + :gsub('piece', 'pieces') + :gsub('Finishing move now ', 'Finishing moves now ') + 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/addons/battlemod/parse_action_packet.lua b/addons/battlemod/parse_action_packet.lua index 83f2f09b85..99352f45db 100644 --- a/addons/battlemod/parse_action_packet.lua +++ b/addons/battlemod/parse_action_packet.lua @@ -11,6 +11,7 @@ function parse_action_packet(act) 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)) --fix for ffxi chat splits on trusts with - + targets_condensed = false if not act.action then return act @@ -190,7 +191,7 @@ function parse_action_packet(act) 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}:contains(m.message) then m.simp_name = 'Magic Burst! '..act.action.name + 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 = {} @@ -216,8 +217,13 @@ function parse_action_packet(act) 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 + -- 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 @@ -230,6 +236,10 @@ function parse_action_packet(act) 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. @@ -268,6 +278,32 @@ function parse_action_packet(act) end end + if col == 'D' or grammar_numb_msg:contains(m.message) then + msg = grammatical_number_fix(msg, (m.cparam or m.param)) + 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 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) + end + if targets_condensed or plural_entities:contains(v.target[1].id) then + msg = plural_target(msg) + end + end + 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 S{1,3,4,6,11,13,14,15}:contains(act.category) and (bit.band(m.unknown,1)==1 and "Cover! " or "") @@ -285,11 +321,11 @@ function parse_action_packet(act) ..(reaction_lookup == 4 and "Blocked! " or "") ..(reaction_lookup == 2 and "Guarded! " or "") ..(reaction_lookup == 3 and S{3,4,6,11,13,14,15}:contains(act.category) and "Parried! " or "") or "" --Unused? They are send the same as missed - windower.add_to_chat(color,prefix..make_condensedamage_number(m.number)..( (msg or tostring(m.message)) + 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}',color_it(act.action.item2 or 'ERROR 121',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 or 'ERROR 116') @@ -299,6 +335,11 @@ function parse_action_packet(act) :gsub('${number}',act.action.number or m.param) :gsub('${status}',m.status or 'ERROR 120') :gsub('${gil}',m.param..' gil'))) + 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 @@ -311,16 +352,20 @@ function parse_action_packet(act) 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 = 'TH' - elseif m.add_effect_message ==776 then m.simp_add_name = 'AE: Chainbound' + 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 and common_nouns:contains(act.actor.id) then + msg = actor_noun(msg) + 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)..(msg + 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') @@ -331,7 +376,7 @@ function parse_action_packet(act) :gsub('${target}',targ) :gsub('${lb}','\7') :gsub('${number}',m.add_effect_param) - :gsub('${status}',m.add_effect_status or 'ERROR 178'))) + :gsub('${status}',m.add_effect_status or 'ERROR 178')))) if not non_block_messages:contains(m.add_effect_message) then m.add_effect_message = 0 end @@ -361,8 +406,11 @@ function parse_action_packet(act) end local msg = simplify_message(m.spike_effect_message) + if not simplify and common_nouns:contains(act.actor.id) then + msg = actor_noun(msg) + 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)..(msg + 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') @@ -373,10 +421,10 @@ function parse_action_packet(act) :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'))) - if not non_block_messages:contains(m.spike_effect_message) then - m.spike_effect_message = 0 - end + :gsub('${status}',m.spike_effect_status or 'ERROR 150')))) + if not non_block_messages:contains(m.spike_effect_message) then + m.spike_effect_message = 0 + end end end end @@ -386,11 +434,44 @@ 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) - if res.action_messages[msg_ID] and res.action_messages[msg_ID].prefix then - outstr = res.action_messages[msg_ID].prefix..' '..outstr - end - if res.action_messages[msg_ID] and res.action_messages[msg_ID].suffix then - outstr = outstr..' '..res.action_messages[msg_ID].suffix + 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 @@ -399,7 +480,7 @@ 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,139,140,204,210,211,212,213,214,350,442,516,531,557,565,582,674}:contains(msg_ID) then + 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 @@ -420,6 +501,10 @@ function simplify_message(msg_ID) 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 @@ -485,13 +570,20 @@ function assemble_targets(actor,targs,category,msg) for i,v in pairs(targets) do local name + local article = common_nouns:contains(v.id) and not simplify and 'The ' or '' local numb = condensetargetname and samename[v.name] > 1 and ' {'..samename[v.name]..'}' or '' if i == 1 then name = color_it(v.name,color_arr[v.owner or v.type]) - out_str = out_str..name..numb + out_str = out_str..article..name..numb + if samename[v.name] > 1 then + targets_condensed = true + else + targets_condensed = false + end else + targets_condensed = true name = color_it(v.name,color_arr[v.owner or v.type]) - out_str = conjunctions(out_str,name..numb,#targets,i) + 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 - @@ -659,6 +751,9 @@ function get_spell(act) 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 @@ -707,19 +802,25 @@ function get_spell(act) if fields.item then if T{125,593,594,595,596,597,598,599}:contains(msg_ID) then - spell.item = color_it(res.items[effect_val]['english_log'], color_arr.itemcol) + 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(spell['english_log'],color_arr.itemcol) - spell.item = color_it(spell['english_log'],color_arr.itemcol) + 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 tempspell = res.items[effect_val] - spell.item2 = color_it(tempspell.english_log,color_arr.itemcol) + 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 diff --git a/addons/battlemod/statics.lua b/addons/battlemod/statics.lua index 20b9a80815..436b376165 100644 --- a/addons/battlemod/statics.lua +++ b/addons/battlemod/statics.lua @@ -28,15 +28,21 @@ skillchain_arr = {'Light:','Darkness:','Gravitation:','Fragmentation:','Distorti 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,40,47,48,49,64,78,87,88,89,90,112,116,154,170,171,172,173,174,175,176,177,178,191,192,198,204,215,217,218,219,234,246,249,307,315,328,350,336,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,62,94,251,308,313,372,8,105,253,679,97,62,94,251,313,308,206,72,38,53} +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} domain_buffs = S{ 250, -- EF Badge @@ -176,8 +182,9 @@ 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 -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} +-- 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 = [[ @@ -542,6 +549,7 @@ default_settings = [[ ${numb} ]]..string.char(129,168)..[[ ${target} ${abil} ${numb} ]]..string.char(129,168)..[[ ${target} [${actor}] ${abil} ]]..string.char(129,168)..[[ ${target} + [${actor}] ${abil} ]]..string.char(129,168)..[[ ${number} ${actor} ${abil} ]]..string.char(129,168)..[[ ${target} ]]..string.char(129,170)..[[ ${number} From 2e28261ead3e1297a9d0acb1e7bc16eb694331c2 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 14 Mar 2021 01:25:26 +0000 Subject: [PATCH 0570/1002] Typo bugfix --- addons/porter/porter.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/porter/porter.lua b/addons/porter/porter.lua index 39ca8d6f9a..74e12e9525 100644 --- a/addons/porter/porter.lua +++ b/addons/porter/porter.lua @@ -107,7 +107,7 @@ function show_bags() for _, item in ipairs(windower.ffxi.get_items(bag)) do local slip_id = slips.get_slip_id_by_item_id(item.id) - if slip_id and item_id ~= 0 then + if slip_id and item.id ~= 0 then n = n + 1 windower.add_to_chat(207, 'slip %02d: %s %s':format(slips.get_slip_number_by_id(slip_id), bag, res.items[item.id].name:color(258))) end From 5820f9203b421c5a4b2f7de92757bc1ad159f0fc Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Wed, 17 Mar 2021 03:06:51 +0100 Subject: [PATCH 0571/1002] fixing a bug fixing a bug --- addons/battlemod/parse_action_packet.lua | 2 +- addons/battlemod/statics.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/battlemod/parse_action_packet.lua b/addons/battlemod/parse_action_packet.lua index 99352f45db..596ac6e2f1 100644 --- a/addons/battlemod/parse_action_packet.lua +++ b/addons/battlemod/parse_action_packet.lua @@ -199,7 +199,7 @@ function parse_action_packet(act) end -- Debuff Application Messages - if message_map[82]:contains(m.message) then + if simplify and message_map[82]:contains(m.message) then if m.status == 'Evasion Down' then m.message = 237 end diff --git a/addons/battlemod/statics.lua b/addons/battlemod/statics.lua index 436b376165..4c64889b2d 100644 --- a/addons/battlemod/statics.lua +++ b/addons/battlemod/statics.lua @@ -134,7 +134,7 @@ message_map[75] = T{283} -- No Effect: Spell, Target 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,268,271} -- Receives: Spell, Target, Status +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 From 19c6271c2c82038085fad99ec32e3dc4739aa8a8 Mon Sep 17 00:00:00 2001 From: pframe Date: Fri, 19 Mar 2021 10:33:46 -0600 Subject: [PATCH 0572/1002] Add equipviewer addon --- addons/equipviewer/encumbrance.png | Bin 0 -> 1500 bytes addons/equipviewer/equipviewer.lua | 521 ++++++++++++++++++++++++++ addons/equipviewer/icon_extractor.lua | 231 ++++++++++++ addons/equipviewer/ui_settings.lua | 116 ++++++ 4 files changed, 868 insertions(+) create mode 100644 addons/equipviewer/encumbrance.png create mode 100644 addons/equipviewer/equipviewer.lua create mode 100644 addons/equipviewer/icon_extractor.lua create mode 100644 addons/equipviewer/ui_settings.lua diff --git a/addons/equipviewer/encumbrance.png b/addons/equipviewer/encumbrance.png new file mode 100644 index 0000000000000000000000000000000000000000..0b0bff3dde321df47fbab8eb8c926f8ab8e8f91f GIT binary patch literal 1500 zcmV<21ta>2P)K+#2Z17xBBKp2@a!&Zd~Y@b`KXt3`pO@GuthjBW7>J{{IYLstFaQ5~xL@-Tt@;2T$x z){P?dI8T8@4gv{~x{ouja(0kselj~_;BW9V*yYOIj;$qL&}pXjCaw90*cvtG`tUe7 z26h7;^4Ezpf{JBCd_GtRGJvQnKqJBUS$ihHKVZ_?@aTwM95;EPHWX{M&;@}mNOhx^UOh7rA@B+4bJ=US3m=~Ib^L7UcI}hm zP?}7%eqePA8&pjUI#K$oT~GVZg7+;;!MO>GJnJHFr5)3%5m0=>7Q%T96seL?as7HT zJQgyn5sq44A21A=!p9@$1}$>5Rlm+fUgYI5OO!}lGjS)PdX2hi+V@8soCxEV2`z_e zLWOCO$MYVemWc!eDwq+qTJu4Rd@2GXmNnIc3RAnoS~NE8TTBNINP=eSxcplN$iYZS zf)<-F90E*EKjXxy9TJ=IHHzZ`Pzn}o7P*$udYiV>A0Yxkcl>4e1&}#^q3aNB)0q=s zsuh4zu;7{hAutx2p1*Tndfrr%?ER4LLdf`p!qFI@Li4)L<#7u-veGo zgl!_XKwv4(FDjgl2<>7?tU*9eA|z_s{c%KuW0r~VWfO+B=7Vne@GoQlohEX&xal`1 z9|Cc09c>{Uy!KpAzbqMn&eHb%oQCMwJ|F7jgUBwtL_`DUl349iXx_R0bg zmZ=t~U*-weF9S$sXG-Ks$+NEe19=kqTxiwhro8S6j*0000 100 then + error('Size too large') + end + settings.size = size + config.save(settings) + + setup_ui() + + log('Size changed to '..settings.size) + elseif cmd == 'alpha' or cmd == "opacity" then + if #cmd_args < 1 then + error("Not enough arguments.") + log("Current alpha/opacity: "..settings.alpha.."/255 = "..settings.alpha/255) + return + end + local alpha = tonumber(cmd_args[1]) + if alpha <= 1 and alpha > 0 then + settings.alpha = math.floor(255 * (alpha)) + else + settings.alpha = math.floor(alpha) + end + config.save(settings) + + setup_ui() + + log('Alpha/Opacity changed to '..settings.alpha..'/255') + elseif cmd:contains('transpar') then + if #cmd_args < 1 then + error("Not enough arguments.") + log("Current transparency: "..(255-settings.alpha).."/255 = "..(255-settings.alpha)/255) + return + end + local transparency = tonumber(cmd_args[1]) + if transparency <= 1 and transparency > 0 then + settings.alpha = math.floor(255 * (1-transparency)) + else + settings.alpha = math.floor(255-transparency) + end + config.save(settings) + + setup_ui() + + log('Transparency changed to '..255-settings.alpha..'/255') + elseif cmd:contains('encumb') then + settings.show_encumbrance = not settings.show_encumbrance + config.save(settings) + + display_encumbrance() + + log('show_encumbrance changed to '..tostring(settings.show_encumbrance)) + elseif cmd:contains('ammo') or cmd:contains('count') then + settings.show_ammo_count = not settings.show_ammo_count + config.save(settings) + + display_ammo_count() + + log('show_ammo_count changed to '..tostring(settings.show_ammo_count)) + elseif cmd == 'hideonzone' or cmd == 'zone' then + settings.hide_on_zone = not settings.hide_on_zone + config.save(settings) + + log('hide_on_zone changed to '..tostring(settings.hide_on_zone)) + elseif cmd == 'hideoncutscene' or cmd == 'cutscene' then + settings.hide_on_cutscene = not settings.hide_on_cutscene + config.save(settings) + + log('hide_on_cutscene changed to '..tostring(settings.hide_on_cutscene)) + elseif cmd == 'justify' then + settings.left_justify = not settings.left_justify + config.save(settings) + + setup_ui() + + log('Ammo text justification changed to '..tostring(settings.left_justify and "Left" or "Right")) + elseif cmd == "testenc" then + display_encumbrance(0xffff) + elseif cmd == "debug" then + if #cmd_args < 1 then + local items = windower.ffxi.get_items() + local e = windower.ffxi.get_items().equipment + for i=0,15 do + local v = equipment_data[i] + local b = e[string.format('%s_bag', v.slot_name)] + local eb = v.bag_id + local ind = v.index + local eind = e[v.slot_name] + local it = v.item_id + local eit = windower.ffxi.get_items(eb, eind).id + log("%s[%d] it=%d eit=%d b=%d eb=%d i=%d ei=%d":format(v.slot_name,i, it, eit, b, eb, ind, eind)) + end + elseif S{"1", "on", "true"}:contains(cmd_args[1]) then + evdebug = true + elseif S{"0", "off", "false"}:contains(cmd_args[1]) then + evdebug = false + end + else + log("HELP:") + log("ev position : move to position (from top left)") + log("ev size : set pixel size of each item slot") + log("ev scale : scale multiplier each item slot (from 32px)") + log("ev alpha : set opacity of display (out of 255)") + log("ev transparency : inverse of alpha (out of 255)") + log("ev ammocount: toggles showing current ammo count") + log("ev encumbrance: toggles showing encumbrance Xs") + log("ev hideonzone: toggles hiding while crossing zone line") + log("ev hideoncutscene: toggles hiding when in cutscene/npc menu/etc") + log("ev justify: toggles between ammo text left and right justify") + end +end) \ No newline at end of file diff --git a/addons/equipviewer/icon_extractor.lua b/addons/equipviewer/icon_extractor.lua new file mode 100644 index 0000000000..07cc09a264 --- /dev/null +++ b/addons/equipviewer/icon_extractor.lua @@ -0,0 +1,231 @@ +-- icon_extractor v1.0.1 +-- Written by Rubenator of Leviathan +-- Base Code graciously provided by Trv of Windower discord +local icon_extractor = {} + +local game_path = windower.pol_path.."\/..\/FINAL FANTASY XI" + +local string = require 'string' +local io = require 'io' +local math = require 'math' + +local concat = table.concat +local floor = math.floor +local byte = string.byte +local char = string.char +local sub = string.sub + +local file_size = '\122\16\00\00' +local reserved1 = '\00\00' +local reserved2 = '\00\00' +local starting_address = '\122\00\00\00' + +local default = '\00\00\00\00' + +local dib_header_size = '\108\00\00\00' +local bitmap_width = '\32\00\00\00' +local bitmap_height = '\32\00\00\00' +local n_color_planes = '\01\00' +local bits_per_pixel = '\32\00' +local compression_type = '\03\00\00\00' +local image_size = '\00\16\00\00' +local h_resolution_target = default +local v_resolution_target = default +local default_n_colors = default +local important_colors = default +local alpha_mask = '\00\00\00\255' +local red_mask = '\00\00\255\00' +local green_mask = '\00\255\00\00' +local blue_mask = '\255\00\00\00' +local colorspace = 'sRGB' +local endpoints = string.rep('\00', 36) +local red_gamma = default +local green_gamma = default +local blue_gamma = default + +local header = 'BM' .. file_size .. reserved1 .. reserved2 .. starting_address + .. dib_header_size .. bitmap_width .. bitmap_height .. n_color_planes + .. bits_per_pixel .. compression_type .. image_size + .. h_resolution_target .. v_resolution_target + .. default_n_colors .. important_colors + .. red_mask .. green_mask .. blue_mask .. alpha_mask + .. colorspace .. endpoints .. red_gamma .. green_gamma .. blue_gamma + +--local icon_file = io.open('C:/Program Files (x86)/PlayOnline/SquareEnix/FINAL FANTASY XI/ROM/118/106.DAT', 'rb') +local color_lookup = {} +local bmp_segments = {} + +for i = 0, 255 do + color_lookup[string.char(i)] = '' +end + +--[[ +3072 bytes per icon +640 bytes for stats, string table, etc. +2432 bytes for pixel data +--]] + +local item_dat_map = { + [1]={min=1, max=4095, dat_path='118/106', offset=-1}, + [2]={min=4096, max=8191, dat_path='118/107', offset=0}, + [3]={min=8192, max=8703, dat_path='118/110', offset=0}, + [4]={min=8704, max=10239, dat_path='301/115', offset=0}, + [5]={min=10240, max=16383, dat_path='118/109', offset=0}, + [6]={min=16384, max=23039, dat_path='118/108', offset=0}, + [7]={min=23040, max=28671, dat_path='286/73', offset=0}, + [8]={min=28672, max=29695, dat_path='217/21', offset=0}, + [9]={min=29696, max=30719, dat_path='288/80', offset=0}, + [10]={min=61440, max=61951, dat_path='288/67', offset=0}, + [11]={min=65535, max=65535, dat_path='174/48', offset=0}, +} + +local item_by_id = function (id, output_path) + local dat_stats = find_item_dat_map(id) + local icon_file = open_dat(dat_stats) + + local id_offset = dat_stats.min + dat_stats.offset + icon_file:seek('set', (id - id_offset) * 0xC00 + 0x2BD) + local data = icon_file:read(2048) + + bmp = convert_item_icon_to_bmp(data) + + local f = io.open(output_path, 'wb') + f:write(bmp) + coroutine.yield() + f:close() +end +icon_extractor.item_by_id = item_by_id + +function find_item_dat_map(id) + for _,stats in pairs(item_dat_map) do + if id >= stats.min and id <= stats.max then + return stats + end + end + return nil +end + +function open_dat(dat_stats) + local icon_file = nil + if dat_stats.file then + icon_file = dat_stats.file + else + if not game_path then + error("ffxi_path must be set before using icon_extractor library") + end + filename = game_path .. '/ROM/' .. tostring(dat_stats.dat_path) .. ".DAT" + icon_file = io.open(filename, 'rb') + if not icon_file then return end + dat_stats.file = icon_file + end + return icon_file +end + +-- 32 bit color palette-indexed bitmaps. Bits are rotated and must be decoded. +local encoded_to_decoded_char = {} +local encoded_byte_to_rgba = {} +local alpha_encoded_to_decoded_adjusted_char = {} +local decoded_byte_to_encoded_char = {} +for i = 0, 255 do + encoded_byte_to_rgba[i] = '' + local n = (i % 32) * 8 + floor(i / 32) + encoded_to_decoded_char[char(i)] = char(n) + decoded_byte_to_encoded_char[n] = char(i) + n = n * 2 + n = n < 256 and n or 255 + alpha_encoded_to_decoded_adjusted_char[char(i)] = char(n) +end +local decoder = function(a, b, c, d) + return encoded_to_decoded_char[a].. + encoded_to_decoded_char[b].. + encoded_to_decoded_char[c].. + alpha_encoded_to_decoded_adjusted_char[d] +end +function convert_item_icon_to_bmp(data) + local color_palette = string.gsub(sub(data, 1, 1024), '(.)(.)(.)(.)', decoder) + -- rather than decoding all 2048 bytes, decode only the palette and index it by encoded byte + for i = 0, 255 do + local offset = i * 4 + 1 + encoded_byte_to_rgba[decoded_byte_to_encoded_char[i]] = sub(color_palette, offset, offset + 3) + end + + return header .. string.gsub(sub(data, 1025, 2048), '(.)', function(a) return encoded_byte_to_rgba[a] end) +end + + +local buff_dat_map = { + [1]={min=0, max=1024, dat_path='119/57', offset=0}, +} +function find_buff_dat_map(id) + for _,stats in pairs(buff_dat_map) do + if id >= stats.min and id <= stats.max then + return stats + end + end + return nil +end +local buff_by_id = function (id, output_path) + local dat_stats = find_buff_dat_map(id) + local icon_file = open_dat(dat_stats) + + local id_offset = dat_stats.min + dat_stats.offset + icon_file:seek('set', (id - id_offset) * 0x1800) + local data = icon_file:read(0x1800) + + bmp = convert_buff_icon_to_bmp(data) + + local f = io.open(output_path, 'wb') + f:write(bmp) + coroutine.yield() + f:close() +end +icon_extractor.buff_by_id = buff_by_id + + +local ffxi_path = function(location) + game_path = location +end +icon_extractor.ffxi_path = ffxi_path + + +-- A mix of 32 bit color uncompressed and *color palette-indexed bitmaps +-- Offsets defined specifically for status icons +-- * some maps use this format as well, but at 512 x 512 +function convert_buff_icon_to_bmp(data) + local length = byte(data, 0x282) -- The length is technically sub(0x281, 0x284), but only 0x282 is unique + + if length == 16 then -- uncompressed + data = sub(data, 0x2BE, 0x12BD) + data = string.gsub(data, '(...)\128', '%1\255') -- All of the alpha bytes are currently 0 or 0x80. + elseif length == 08 then -- color table + local color_palette = sub(data, 0x2BE, 0x6BD) + color_palette = string.gsub(color_palette, '(...)\128', '%1\255') + + local n = 0 + for i = 1, 1024, 4 do + color_lookup[char(n)] = sub(color_palette, i, i + 3) + n = n + 1 + end + + data = string.gsub(sub(data, 0x6BE, 0xABD), '(.)', function(i) return color_lookup[i] end) + elseif length == 04 then -- XIVIEW + data = sub(data, 0x2BE, 0x12BD) + end + + return header .. data +end + +windower.register_event('unload', function() + for _,dat in pairs(item_dat_map) do + if dat and dat.file then + dat.file:close() + end + end + for _,dat in pairs(buff_dat_map) do + if dat and dat.file then + dat.file:close() + end + end +end); + +return icon_extractor diff --git a/addons/equipviewer/ui_settings.lua b/addons/equipviewer/ui_settings.lua new file mode 100644 index 0000000000..ff6d37d50f --- /dev/null +++ b/addons/equipviewer/ui_settings.lua @@ -0,0 +1,116 @@ +function refresh_ui_settings() + --Image and text settings + bg_image_settings = { + color = { + alpha = math.floor(80*settings.alpha/255), + red = 0, + blue = 0, + green = 0 + }, + pos = { + x = settings.pos.x, + y = settings.pos.y, + }, + size = { + width = settings.size * 4, + height = settings.size * 4, + }, + draggable = false, + } + equipment_image_settings = { + color = { + alpha = settings.alpha, + red = 255, + blue = 255, + green = 255, + }, + texture = { + fit = true, + }, + size = { + width = settings.size, + height = settings.size, + }, + draggable = false, + } + encumbrance_image_settings = { + color = { + alpha = settings.alpha*0.8, + red = 255, + blue = 255, + green = 255, + }, + texture = { + fit = true, + }, + size = { + width = settings.size, + height = settings.size, + }, + draggable = false, + } + ammo_count_text_settings = { + text = { + size = settings.size*0.27, + alpha = settings.alpha, + red = 255, + blue = 255, + green = 255, + stroke = { + width = 1, + alpha = 127, + red = 0, + green = 0, + blue = 0, + }, + }, + bg = { + alpha = 0, + red = 255, + blue = 255, + green = 255, + }, + pos = { + x = (windower.get_windower_settings().ui_x_res - (settings.pos.x + settings.size*4))*-1, + y = settings.pos.y + settings.size*0.58, + }, + flags = { + draggable = false, + right = true, + bold = true, + italic = true, + }, + } + ammo_count_text_settings_left_justify = { + text = { + size = settings.size*0.27, + alpha = settings.alpha, + red = 255, + blue = 255, + green = 255, + stroke = { + width = 1, + alpha = 127, + red = 0, + green = 0, + blue = 0 + }, + }, + bg = { + alpha = 0, + red = 255, + blue = 255, + green = 255 + }, + pos = { + x = settings.pos.x + settings.size*3, + y = settings.pos.y + settings.size*0.58 + }, + flags = { + draggable = false, + right = false, + bold = true, + italic = true, + }, + } +end \ No newline at end of file From 6160423b2e4943d28d1427f146cffbe16a7ccd32 Mon Sep 17 00:00:00 2001 From: Kyle Ricks Date: Tue, 23 Mar 2021 17:33:59 -0700 Subject: [PATCH 0573/1002] Five more built in item groups for Treasury.lua Added built in mapping for a number of objects often pooled by linkshells. Heroism, Detritus, Moldy Items, Dynamis Divergence Cards, and Shards/Voids. --- addons/Treasury/Treasury.lua | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/addons/Treasury/Treasury.lua b/addons/Treasury/Treasury.lua index 028297b25e..68ad971af9 100644 --- a/addons/Treasury/Treasury.lua +++ b/addons/Treasury/Treasury.lua @@ -159,6 +159,22 @@ function find_id(name) elseif name == 'crystals' then return S{4096, 4097, 4098, 4099, 4100, 4101, 4102, 4103} + elseif name == 'detritus' then + return S{9875, 9876} + + elseif name == 'heroism' then + return S{9877, 9878} + + elseif name == 'moldy' then + return S{9773, 9830, 9831, 9832, 9833, 9834, 9835, 9836, 9837, 9838, 9839, 9840, 9841, 9843, 9868, 9869, 9870, 9871, 9872, 9873, 9874} + + elseif name == 'dynad' then + return S{9538, 9539, 9540, 9541, 9542, 9543, 9844, 9845} + + elseif name == 'papers' then + return S{9544, 9545, 9546, 9547, 9548, 9549, 9550, 9551, 9552, 9553, 9554, 9555, 9556, 9557, 9558, 9559, 9560, 9561, 9562, 9563, 9564, 9565, 9566, 9567, 9568, 9569, 9570, 9571, 9572, 9573, 9574, 9575, 9576, 9577, 9578, 9579, 9580, 9581, 9582, 9583, 9584, 9585, 9586, 9587, 9588, 9589, 9590, 9591, 9592, 9593, 9594, 9595, 9596, 9597, 9598, 9599, 9600, 9601, 9602, 9603, 9604, 9605, 9606, 9607, 9608, 9609, 9610, 9611, 9612, 9613, 9614, 9615, 9616, 9617, 9618, 9619, 9620, 9621, 9622, 9623, 9624, 9625, 9626, 9627, 9628, 9629, 9630, 9631, 9632, 9633, 9634, 9635, 9636, 9637, 9638, 9639, 9640, 9641, 9642, 9643, 9644, 9645, 9646, 9647, 9648, 9649, 9650, 9651, 9652, 9653, 9654, 9655, 9656, 9657, 9658, 9659, 9660, 9661, 9662, 9663, 9664, 9665, 9666, 9667, 9668, 9669, 9670, 9671, 9672, 9673, 9674, 9675, 9676, 9677, 9678, 9679, 9680, 9681, 9682, 9683, 9684, 9685, 9686, 9687, 9688, 9689, 9690, 9691, 9692, 9693, 9694, 9695, 9696, 9697, 9698, 9699, 9700, 9701, 9702, 9703, 9704, 9705, 9706, 9707, 9708, 9709, 9710, 9711, 9712, 9713, 9714, 9715, 9716, 9717, 9718, 9719, 9720, 9721, 9722, 9723, 9724, 9725, 9726, 9727, 9728, 9729, 9730, 9731, 9732, 9733, 9734, 9735, 9736, 9737, 9738, 9739, 9740, 9741, 9742, 9743, 9744, 9745, 9746, 9747, 9748, 9749, 9750, 9751, 9752, 9753, 9754, 9755, 9756, 9757, 9758, 9759, 9760, 9761, 9762, 9763} + + else return flatten(S(all_ids:key_filter(windower.wc_match-{name}))) From d828596a5c5cb4f21f65431f898fe9b27f22a01b Mon Sep 17 00:00:00 2001 From: Kyle Ricks <55457469+kylericks@users.noreply.github.com> Date: Wed, 24 Mar 2021 11:12:40 -0700 Subject: [PATCH 0574/1002] Update Treasury.lua removed extra carriage return --- addons/Treasury/Treasury.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/Treasury/Treasury.lua b/addons/Treasury/Treasury.lua index 68ad971af9..9f4b9f311d 100644 --- a/addons/Treasury/Treasury.lua +++ b/addons/Treasury/Treasury.lua @@ -174,7 +174,6 @@ function find_id(name) elseif name == 'papers' then return S{9544, 9545, 9546, 9547, 9548, 9549, 9550, 9551, 9552, 9553, 9554, 9555, 9556, 9557, 9558, 9559, 9560, 9561, 9562, 9563, 9564, 9565, 9566, 9567, 9568, 9569, 9570, 9571, 9572, 9573, 9574, 9575, 9576, 9577, 9578, 9579, 9580, 9581, 9582, 9583, 9584, 9585, 9586, 9587, 9588, 9589, 9590, 9591, 9592, 9593, 9594, 9595, 9596, 9597, 9598, 9599, 9600, 9601, 9602, 9603, 9604, 9605, 9606, 9607, 9608, 9609, 9610, 9611, 9612, 9613, 9614, 9615, 9616, 9617, 9618, 9619, 9620, 9621, 9622, 9623, 9624, 9625, 9626, 9627, 9628, 9629, 9630, 9631, 9632, 9633, 9634, 9635, 9636, 9637, 9638, 9639, 9640, 9641, 9642, 9643, 9644, 9645, 9646, 9647, 9648, 9649, 9650, 9651, 9652, 9653, 9654, 9655, 9656, 9657, 9658, 9659, 9660, 9661, 9662, 9663, 9664, 9665, 9666, 9667, 9668, 9669, 9670, 9671, 9672, 9673, 9674, 9675, 9676, 9677, 9678, 9679, 9680, 9681, 9682, 9683, 9684, 9685, 9686, 9687, 9688, 9689, 9690, 9691, 9692, 9693, 9694, 9695, 9696, 9697, 9698, 9699, 9700, 9701, 9702, 9703, 9704, 9705, 9706, 9707, 9708, 9709, 9710, 9711, 9712, 9713, 9714, 9715, 9716, 9717, 9718, 9719, 9720, 9721, 9722, 9723, 9724, 9725, 9726, 9727, 9728, 9729, 9730, 9731, 9732, 9733, 9734, 9735, 9736, 9737, 9738, 9739, 9740, 9741, 9742, 9743, 9744, 9745, 9746, 9747, 9748, 9749, 9750, 9751, 9752, 9753, 9754, 9755, 9756, 9757, 9758, 9759, 9760, 9761, 9762, 9763} - else return flatten(S(all_ids:key_filter(windower.wc_match-{name}))) From 318c06c7d98ca360af6debe15f47b1034f17492b Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Wed, 24 Mar 2021 14:24:54 -0600 Subject: [PATCH 0575/1002] various whitespace fixes, and author adjustment --- addons/equipviewer/equipviewer.lua | 810 ++++++++++++++--------------- 1 file changed, 405 insertions(+), 405 deletions(-) diff --git a/addons/equipviewer/equipviewer.lua b/addons/equipviewer/equipviewer.lua index a605c3860c..edcd404ba1 100644 --- a/addons/equipviewer/equipviewer.lua +++ b/addons/equipviewer/equipviewer.lua @@ -1,6 +1,6 @@ _addon.name = 'EquipViewer' _addon.version = '3.2.4' -_addon.author = 'Project Tako, Rubenator, Trv' +_addon.author = 'Project Tako, Rubenator' _addon.commands = { 'equipviewer', 'ev' } require('luau') @@ -15,226 +15,226 @@ local icon_extractor = require('icon_extractor') require('ui_settings') local equipment_data = { - [0] = { slot_name = 'main', slot_id = 0, display_pos = 0, item_id = 0, image = nil }, - [1] = { slot_name = 'sub', slot_id = 1, display_pos = 1, item_id = 0, image = nil }, - [2] = { slot_name = 'range', slot_id = 2, display_pos = 2, item_id = 0, image = nil }, - [3] = { slot_name = 'ammo', slot_id = 3, display_pos = 3, item_id = 0, image = nil }, - [4] = { slot_name = 'head', slot_id = 4, display_pos = 4, item_id = 0, image = nil }, - [5] = { slot_name = 'body', slot_id = 5, display_pos = 8, item_id = 0, image = nil }, - [6] = { slot_name = 'hands', slot_id = 6, display_pos = 9, item_id = 0, image = nil }, - [7] = { slot_name = 'legs', slot_id = 7, display_pos = 14, item_id = 0, image = nil }, - [8] = { slot_name = 'feet', slot_id = 8, display_pos = 15, item_id = 0, image = nil }, - [9] = { slot_name = 'neck', slot_id = 9, display_pos = 5, item_id = 0, image = nil }, - [10] = { slot_name = 'waist', slot_id = 10, display_pos = 13, item_id = 0, image = nil }, - [11] = { slot_name = 'left_ear', slot_id = 11, display_pos = 6, item_id = 0, image = nil }, - [12] = { slot_name = 'right_ear', slot_id = 12, display_pos = 7, item_id = 0, image = nil }, - [13] = { slot_name = 'left_ring', slot_id = 13, display_pos = 10, item_id = 0, image = nil }, - [14] = { slot_name = 'right_ring', slot_id = 14, display_pos = 11, item_id = 0, image = nil }, - [15] = { slot_name = 'back', slot_id = 15, display_pos = 12, item_id = 0, image = nil }, + [0] = {slot_name = 'main', slot_id = 0, display_pos = 0, item_id = 0, image = nil}, + [1] = {slot_name = 'sub', slot_id = 1, display_pos = 1, item_id = 0, image = nil}, + [2] = {slot_name = 'range', slot_id = 2, display_pos = 2, item_id = 0, image = nil}, + [3] = {slot_name = 'ammo', slot_id = 3, display_pos = 3, item_id = 0, image = nil}, + [4] = {slot_name = 'head', slot_id = 4, display_pos = 4, item_id = 0, image = nil}, + [5] = {slot_name = 'body', slot_id = 5, display_pos = 8, item_id = 0, image = nil}, + [6] = {slot_name = 'hands', slot_id = 6, display_pos = 9, item_id = 0, image = nil}, + [7] = {slot_name = 'legs', slot_id = 7, display_pos = 14, item_id = 0, image = nil}, + [8] = {slot_name = 'feet', slot_id = 8, display_pos = 15, item_id = 0, image = nil}, + [9] = {slot_name = 'neck', slot_id = 9, display_pos = 5, item_id = 0, image = nil}, + [10] = {slot_name = 'waist', slot_id = 10, display_pos = 13, item_id = 0, image = nil}, + [11] = {slot_name = 'left_ear', slot_id = 11, display_pos = 6, item_id = 0, image = nil}, + [12] = {slot_name = 'right_ear', slot_id = 12, display_pos = 7, item_id = 0, image = nil}, + [13] = {slot_name = 'left_ring', slot_id = 13, display_pos = 10, item_id = 0, image = nil}, + [14] = {slot_name = 'right_ring', slot_id = 14, display_pos = 11, item_id = 0, image = nil}, + [15] = {slot_name = 'back', slot_id = 15, display_pos = 12, item_id = 0, image = nil}, } local encumbrance_data = {} for i=0,15 do - encumbrance_data[i] = { slot_name = 'encumbrance', slot_id = i, display_pos = equipment_data[i].display_pos, image = nil } + encumbrance_data[i] = { slot_name = 'encumbrance', slot_id = i, display_pos = equipment_data[i].display_pos, image = nil } end local ammo_count_text = nil local bg_image = nil local defaults = T{ - pos = T{ - x = 500, - y = 500 - }, - size = 32, - alpha = 230, - show_encumbrance = true, - show_ammo_count = true, - hide_on_zone = true, - hide_on_cutscene = true, - left_justify = false, + pos = T{ + x = 500, + y = 500 + }, + size = 32, + alpha = 230, + show_encumbrance = true, + show_ammo_count = true, + hide_on_zone = true, + hide_on_cutscene = true, + left_justify = false, } settings = nil local last_encumbrance_bitfield = 0 -- gets the currently equipped item data for the slot information provided local function get_equipped_item(slotName, slotId, bag, index) - if not bag or not index then -- from memory - local equipment = windower.ffxi.get_items().equipment - bag = equipment[string.format('%s_bag', slotName)] - index = equipment[slotName] - if equipment_data[slotId] then - equipment_data[slotId].bag_id = bag - equipment_data[slotId].index = index - end - end - if index == 0 then -- empty equipment slot - return 0, 0 - end - local item_data = windower.ffxi.get_items(bag, index) - return item_data.id, item_data.count + if not bag or not index then -- from memory + local equipment = windower.ffxi.get_items().equipment + bag = equipment[string.format('%s_bag', slotName)] + index = equipment[slotName] + if equipment_data[slotId] then + equipment_data[slotId].bag_id = bag + equipment_data[slotId].index = index + end + end + if index == 0 then -- empty equipment slot + return 0, 0 + end + local item_data = windower.ffxi.get_items(bag, index) + return item_data.id, item_data.count end -- desc: Updates the ui object(s) for the given slot local function update_equipment_slot(source, slot, bag, index, item, count) - local slot_data = equipment_data[slot] - slot_data.bag_id = bag or slot_data.bag_id - slot_data.index = index or slot_data.index - if not item then - item, count = get_equipped_item(slot_data.slot_name, slot_data.slot_id, bag, index) - end - if evdebug then - bag = slot_data.bag_id - index = slot_data.index - log("%s %s %d %d %d":format(source, slot_data.slot_name, item, bag or -1, index or -1)) - print("%s %s %d %d %d":format(source, slot_data.slot_name, item, bag or -1, index or -1)) - end - if slot_data.slot_name == 'ammo' then - slot_data.count = count or slot_data.count or 0 - end - if slot_data.image and item ~= nil then - if item == 0 or item == 65535 then -- empty slot - slot_data.image:hide() - slot_data.image:clear() - slot_data.item_id = 0 - slot_data.count = nil - slot_data.image:update() - elseif slot_data.item_id ~= item then - slot_data.item_id = item - local icon_path = string.format('%sicons/%s.bmp', windower.addon_path, slot_data.item_id) - - if not windower.file_exists(icon_path) then - icon_extractor.item_by_id(slot_data.item_id, icon_path) - end - if windower.file_exists(icon_path) then - slot_data.image:path(icon_path) - slot_data.image:alpha(settings.alpha) - slot_data.image:show() - end - end - if slot_data.slot_name == 'ammo' then - display_ammo_count(slot_data.count) - end - slot_data.image:update() - end + local slot_data = equipment_data[slot] + slot_data.bag_id = bag or slot_data.bag_id + slot_data.index = index or slot_data.index + if not item then + item, count = get_equipped_item(slot_data.slot_name, slot_data.slot_id, bag, index) + end + if evdebug then + bag = slot_data.bag_id + index = slot_data.index + log("%s %s %d %d %d":format(source, slot_data.slot_name, item, bag or -1, index or -1)) + print("%s %s %d %d %d":format(source, slot_data.slot_name, item, bag or -1, index or -1)) + end + if slot_data.slot_name == 'ammo' then + slot_data.count = count or slot_data.count or 0 + end + if slot_data.image and item ~= nil then + if item == 0 or item == 65535 then -- empty slot + slot_data.image:hide() + slot_data.image:clear() + slot_data.item_id = 0 + slot_data.count = nil + slot_data.image:update() + elseif slot_data.item_id ~= item then + slot_data.item_id = item + local icon_path = string.format('%sicons/%s.bmp', windower.addon_path, slot_data.item_id) + + if not windower.file_exists(icon_path) then + icon_extractor.item_by_id(slot_data.item_id, icon_path) + end + if windower.file_exists(icon_path) then + slot_data.image:path(icon_path) + slot_data.image:alpha(settings.alpha) + slot_data.image:show() + end + end + if slot_data.slot_name == 'ammo' then + display_ammo_count(slot_data.count) + end + slot_data.image:update() + end end -- Updates the texture for all slots if it's a different piece of equipment local function update_equipment_slots(source) - for slot in pairs(equipment_data) do - update_equipment_slot(source, slot) - end + for slot in pairs(equipment_data) do + update_equipment_slot(source, slot) + end end -- Sets up the image and text ui objects for our equipment local function setup_ui() - refresh_ui_settings() - destroy() - - bg_image = images.new(bg_image_settings) - bg_image:show() - - for key, slot in pairs(equipment_data) do - slot.item_id = 0 - slot.image = images.new(equipment_image_settings) - position(slot) - end - update_equipment_slots("setup_ui") - - for key, slot in pairs(encumbrance_data) do - slot.image = images.new(encumbrance_image_settings) - slot.image:path(windower.addon_path..'encumbrance.png') - slot.image:hide() - position(slot) - end - display_encumbrance() - - ammo_count_text = texts.new(settings.left_justify and ammo_count_text_settings_left_justify or ammo_count_text_settings) - display_ammo_count() + refresh_ui_settings() + destroy() + + bg_image = images.new(bg_image_settings) + bg_image:show() + + for key, slot in pairs(equipment_data) do + slot.item_id = 0 + slot.image = images.new(equipment_image_settings) + position(slot) + end + update_equipment_slots("setup_ui") + + for key, slot in pairs(encumbrance_data) do + slot.image = images.new(encumbrance_image_settings) + slot.image:path(windower.addon_path..'encumbrance.png') + slot.image:hide() + position(slot) + end + display_encumbrance() + + ammo_count_text = texts.new(settings.left_justify and ammo_count_text_settings_left_justify or ammo_count_text_settings) + display_ammo_count() end -- Called when the addon is first loaded. windower.register_event('load', function() - if settings then - config.reload(settings) - else - settings = config.load(defaults) - end - --Make sure icons directory exists - if not windower.dir_exists(string.format('%sicons', windower.addon_path)) then - windower.create_dir(string.format('%sicons', windower.addon_path)) - end - - if windower.ffxi.get_info().logged_in then - setup_ui() - end + if settings then + config.reload(settings) + else + settings = config.load(defaults) + end + --Make sure icons directory exists + if not windower.dir_exists(string.format('%sicons', windower.addon_path)) then + windower.create_dir(string.format('%sicons', windower.addon_path)) + end + + if windower.ffxi.get_info().logged_in then + setup_ui() + end end) -- Called whenever character logs out. windower.register_event('logout', function() - clear_all_equipment_slots() - destroy() + clear_all_equipment_slots() + destroy() end) -- Called whenever character logs in. windower.register_event('login', function() - if settings then - config.reload(settings) - else - settings = config.load(defaults) - end - setup_ui() - update_equipment_slots('login') + if settings then + config.reload(settings) + else + settings = config.load(defaults) + end + setup_ui() + update_equipment_slots('login') end) -- Called when our addon receives an incoming chunk. windower.register_event('incoming chunk', function(id, original, modified, injected, blocked) - if id == 0x050 then --Equip/Unequip - local packet = packets.parse('incoming', original) - local index = packet['Inventory Index'] - local slot = packet['Equipment Slot'] - local bag = packet['Inventory Bag'] - equipment_data[slot].bag_id = bag - equipment_data[slot].index = index - update_equipment_slot:schedule(0, '0x050', slot, bag, index) - elseif id == 0x020 or id == 0x01F or id == 0x01E then --Item Update / Item Assign (ammo consumption) / 0x01E item count/last ammo shot - local packet = packets.parse('incoming', original) - local bag = packet['Bag'] - local index = packet['Index'] - - local slot = nil - for _,slot_data in pairs(equipment_data) do - if slot_data.bag_id == bag and slot_data.index == index then - slot = slot_data.slot_id - break - end - end - - if slot then - if packet['Status'] ~= 5 then --item not equipped - update_equipment_slot:schedule(0, "0x%x":format(id), slot, 0, 0, 0) - return - end - if slot == 3 then --ammo - local count = packet['Count'] or 0 - display_ammo_count(count) - end - local item = packet['Item'] - update_equipment_slot:schedule(0,"0x%x":format(id), slot, bag, index, item, count) - end - elseif id == 0x01B then -- Job Info (Encumbrance Flags) - local packet = packets.parse('incoming', original) - display_encumbrance(packet['Encumbrance Flags']) - elseif id == 0x0A then -- Finish Zone - show() - elseif id == 0x0B then -- Zone - if settings.hide_on_zone then - hide() - end - end + if id == 0x050 then --Equip/Unequip + local packet = packets.parse('incoming', original) + local index = packet['Inventory Index'] + local slot = packet['Equipment Slot'] + local bag = packet['Inventory Bag'] + equipment_data[slot].bag_id = bag + equipment_data[slot].index = index + update_equipment_slot:schedule(0, '0x050', slot, bag, index) + elseif id == 0x020 or id == 0x01F or id == 0x01E then --Item Update / Item Assign (ammo consumption) / 0x01E item count/last ammo shot + local packet = packets.parse('incoming', original) + local bag = packet['Bag'] + local index = packet['Index'] + + local slot = nil + for _,slot_data in pairs(equipment_data) do + if slot_data.bag_id == bag and slot_data.index == index then + slot = slot_data.slot_id + break + end + end + + if slot then + if packet['Status'] ~= 5 then --item not equipped + update_equipment_slot:schedule(0, "0x%x":format(id), slot, 0, 0, 0) + return + end + if slot == 3 then --ammo + local count = packet['Count'] or 0 + display_ammo_count(count) + end + local item = packet['Item'] + update_equipment_slot:schedule(0,"0x%x":format(id), slot, bag, index, item, count) + end + elseif id == 0x01B then -- Job Info (Encumbrance Flags) + local packet = packets.parse('incoming', original) + display_encumbrance(packet['Encumbrance Flags']) + elseif id == 0x0A then -- Finish Zone + show() + elseif id == 0x0B then -- Zone + if settings.hide_on_zone then + hide() + end + end end) -- Called when our addon receives an outgoing chunk. windower.register_event('outgoing chunk', function(id, original, modified, injected, blocked) - if id == 0x100 then -- Job Change Request + if id == 0x100 then -- Job Change Request clear_all_equipment_slots() end end) @@ -242,123 +242,123 @@ end) -- Destroys all created ui objects function destroy() - if bg_image then - bg_image:destroy() - bg_image = nil - end - for key, slot_data in pairs(equipment_data) do - if slot_data.image ~= nil then - slot_data.image:destroy() - slot_data.image = nil - end - end - for key, slot_data in pairs(encumbrance_data) do - if slot_data.image ~= nil then - slot_data.image:destroy() - slot_data.image = nil - end - end - if ammo_count_text then - ammo_count_text:destroy() - ammo_count_text = nil - end + if bg_image then + bg_image:destroy() + bg_image = nil + end + for key, slot_data in pairs(equipment_data) do + if slot_data.image ~= nil then + slot_data.image:destroy() + slot_data.image = nil + end + end + for key, slot_data in pairs(encumbrance_data) do + if slot_data.image ~= nil then + slot_data.image:destroy() + slot_data.image = nil + end + end + if ammo_count_text then + ammo_count_text:destroy() + ammo_count_text = nil + end end -- Shows appropriate ui objects function show() - if bg_image then - bg_image:show() - end - for key, slot_data in pairs(equipment_data) do - if slot_data.item_id ~= 0 and slot_data.image then - slot_data.image:show() - end - end - display_encumbrance() - display_ammo_count() + if bg_image then + bg_image:show() + end + for key, slot_data in pairs(equipment_data) do + if slot_data.item_id ~= 0 and slot_data.image then + slot_data.image:show() + end + end + display_encumbrance() + display_ammo_count() end -- Hides all ui objects function hide() - if bg_image then - bg_image:hide() - end - for key, slot_data in pairs(equipment_data) do - if slot_data.image then - slot_data.image:hide() - end - end - for key, slot_data in pairs(encumbrance_data) do - if slot_data.image then - slot_data.image:hide() - end - end - if ammo_count_text then - ammo_count_text:hide() - end + if bg_image then + bg_image:hide() + end + for key, slot_data in pairs(equipment_data) do + if slot_data.image then + slot_data.image:hide() + end + end + for key, slot_data in pairs(encumbrance_data) do + if slot_data.image then + slot_data.image:hide() + end + end + if ammo_count_text then + ammo_count_text:hide() + end end -- Moves ui object to correct spot based on 'display_pos' field function position(slot) - local pos_x = settings.pos.x + ((slot.display_pos % 4) * settings.size) - local pos_y = settings.pos.y + (math.floor(slot.display_pos / 4) * settings.size) - slot.image:pos(pos_x, pos_y) + local pos_x = settings.pos.x + ((slot.display_pos % 4) * settings.size) + local pos_y = settings.pos.y + (math.floor(slot.display_pos / 4) * settings.size) + slot.image:pos(pos_x, pos_y) end -- Clears all equipment slot data and hides ui object function clear_slot(slot) - local slot_data = equipment_data[slot] - slot_data.image:hide() - slot_data.image:clear() - slot_data.item_id = 0 - slot_data.bag_id = nil - slot_data.index = nil - slot_data.count = nil - slot_data.image:update() - - display_ammo_count() + local slot_data = equipment_data[slot] + slot_data.image:hide() + slot_data.image:clear() + slot_data.item_id = 0 + slot_data.bag_id = nil + slot_data.index = nil + slot_data.count = nil + slot_data.image:update() + + display_ammo_count() end -- Clears all equipment slot data and hides equipment slot ui objects function clear_all_equipment_slots() - for slot in pairs(equipment_data) do - clear_slot(slot) - end + for slot in pairs(equipment_data) do + clear_slot(slot) + end end -- Shows and hides appropriate encumbrance ui objects and possibly updates encumbrance -- flags based on provided bitfield number function display_encumbrance(bitfield) - bitfield = bitfield or last_encumbrance_bitfield - last_encumbrance_bitfield = bitfield - for key, slot in pairs(encumbrance_data) do - if slot.image then - if not settings.show_encumbrance or bit.band(bitfield, bit.lshift(1,key)) == 0 then - slot.image:hide() - else - slot.image:show() - end - end - end + bitfield = bitfield or last_encumbrance_bitfield + last_encumbrance_bitfield = bitfield + for key, slot in pairs(encumbrance_data) do + if slot.image then + if not settings.show_encumbrance or bit.band(bitfield, bit.lshift(1,key)) == 0 then + slot.image:hide() + else + slot.image:show() + end + end + end end -- Displays appropriatly and possibly updates ammo count and ui object function display_ammo_count(count) - if not ammo_count_text then return end - count = count or equipment_data[3] and equipment_data[3].count -- 3 == Ammo - equipment_data[3].count = count - if not settings.show_ammo_count or not count or count <= 1 then - ammo_count_text:hide() - else - ammo_count_text:text(count and tostring(count) or "") - ammo_count_text:show() - end + if not ammo_count_text then return end + count = count or equipment_data[3] and equipment_data[3].count -- 3 == Ammo + equipment_data[3].count = count + if not settings.show_ammo_count or not count or count <= 1 then + ammo_count_text:hide() + else + ammo_count_text:text(count and tostring(count) or "") + ammo_count_text:show() + end end -- Called when player status changes. windower.register_event('status change', function(new_status_id) - if new_status_id == 4 and settings.hide_on_cutscene then --Cutscene/Menu - hide() + if new_status_id == 4 and settings.hide_on_cutscene then --Cutscene/Menu + hide() else show() end @@ -366,156 +366,156 @@ end) -- Called when our addon is unloaded. windower.register_event('unload', function() - destroy() + destroy() end) -- Called when the addon receives a command. windower.register_event('addon command', function (...) - config.reload(settings) - coroutine.sleep(0.5) - local cmd = (...) and (...):lower() or "" - local cmd_args = { select(2, ...) } + config.reload(settings) + coroutine.sleep(0.5) + local cmd = (...) and (...):lower() or "" + local cmd_args = {select(2, ...)} if cmd == 'position' or cmd == 'pos' then - if #cmd_args < 2 then - error("Not enough arguments.") - log("Current position: "..settings.pos.x.." "..settings.pos.y) - return - end - - settings.pos.x = tonumber(cmd_args[1]) - settings.pos.y = tonumber(cmd_args[2]) - config.save(settings) - - setup_ui() - - log('Position changed to '..settings.pos.x..', '..settings.pos.y) - elseif cmd == 'size' then - if #cmd_args < 1 then - error("Not enough arguments.") - log("Current size: "..settings.size) - return - end - - settings.size = tonumber(cmd_args[1]) - config.save(settings) - - setup_ui() - - log('Size changed to '..settings.size) - elseif cmd == 'scale' then - if #cmd_args < 1 then - error("Not enough arguments.") - log("Current scale: "..settings.size/32) - return - end - local size = tonumber(cmd_args[1])*32 - if size > 100 then - error('Size too large') - end - settings.size = size - config.save(settings) - - setup_ui() - - log('Size changed to '..settings.size) - elseif cmd == 'alpha' or cmd == "opacity" then - if #cmd_args < 1 then - error("Not enough arguments.") - log("Current alpha/opacity: "..settings.alpha.."/255 = "..settings.alpha/255) - return - end - local alpha = tonumber(cmd_args[1]) - if alpha <= 1 and alpha > 0 then - settings.alpha = math.floor(255 * (alpha)) - else - settings.alpha = math.floor(alpha) - end - config.save(settings) - - setup_ui() - - log('Alpha/Opacity changed to '..settings.alpha..'/255') - elseif cmd:contains('transpar') then - if #cmd_args < 1 then - error("Not enough arguments.") - log("Current transparency: "..(255-settings.alpha).."/255 = "..(255-settings.alpha)/255) - return - end - local transparency = tonumber(cmd_args[1]) - if transparency <= 1 and transparency > 0 then - settings.alpha = math.floor(255 * (1-transparency)) - else - settings.alpha = math.floor(255-transparency) - end - config.save(settings) - - setup_ui() - - log('Transparency changed to '..255-settings.alpha..'/255') - elseif cmd:contains('encumb') then - settings.show_encumbrance = not settings.show_encumbrance - config.save(settings) - - display_encumbrance() - - log('show_encumbrance changed to '..tostring(settings.show_encumbrance)) - elseif cmd:contains('ammo') or cmd:contains('count') then - settings.show_ammo_count = not settings.show_ammo_count - config.save(settings) - - display_ammo_count() - - log('show_ammo_count changed to '..tostring(settings.show_ammo_count)) - elseif cmd == 'hideonzone' or cmd == 'zone' then - settings.hide_on_zone = not settings.hide_on_zone - config.save(settings) - - log('hide_on_zone changed to '..tostring(settings.hide_on_zone)) - elseif cmd == 'hideoncutscene' or cmd == 'cutscene' then - settings.hide_on_cutscene = not settings.hide_on_cutscene - config.save(settings) - - log('hide_on_cutscene changed to '..tostring(settings.hide_on_cutscene)) - elseif cmd == 'justify' then - settings.left_justify = not settings.left_justify - config.save(settings) - - setup_ui() - - log('Ammo text justification changed to '..tostring(settings.left_justify and "Left" or "Right")) - elseif cmd == "testenc" then - display_encumbrance(0xffff) - elseif cmd == "debug" then - if #cmd_args < 1 then - local items = windower.ffxi.get_items() - local e = windower.ffxi.get_items().equipment - for i=0,15 do - local v = equipment_data[i] - local b = e[string.format('%s_bag', v.slot_name)] - local eb = v.bag_id - local ind = v.index - local eind = e[v.slot_name] - local it = v.item_id - local eit = windower.ffxi.get_items(eb, eind).id - log("%s[%d] it=%d eit=%d b=%d eb=%d i=%d ei=%d":format(v.slot_name,i, it, eit, b, eb, ind, eind)) - end - elseif S{"1", "on", "true"}:contains(cmd_args[1]) then - evdebug = true - elseif S{"0", "off", "false"}:contains(cmd_args[1]) then - evdebug = false - end - else - log("HELP:") - log("ev position : move to position (from top left)") - log("ev size : set pixel size of each item slot") - log("ev scale : scale multiplier each item slot (from 32px)") - log("ev alpha : set opacity of display (out of 255)") - log("ev transparency : inverse of alpha (out of 255)") - log("ev ammocount: toggles showing current ammo count") - log("ev encumbrance: toggles showing encumbrance Xs") - log("ev hideonzone: toggles hiding while crossing zone line") - log("ev hideoncutscene: toggles hiding when in cutscene/npc menu/etc") - log("ev justify: toggles between ammo text left and right justify") + if #cmd_args < 2 then + error("Not enough arguments.") + log("Current position: "..settings.pos.x.." "..settings.pos.y) + return + end + + settings.pos.x = tonumber(cmd_args[1]) + settings.pos.y = tonumber(cmd_args[2]) + config.save(settings) + + setup_ui() + + log('Position changed to '..settings.pos.x..', '..settings.pos.y) + elseif cmd == 'size' then + if #cmd_args < 1 then + error("Not enough arguments.") + log("Current size: "..settings.size) + return + end + + settings.size = tonumber(cmd_args[1]) + config.save(settings) + + setup_ui() + + log('Size changed to '..settings.size) + elseif cmd == 'scale' then + if #cmd_args < 1 then + error("Not enough arguments.") + log("Current scale: "..settings.size/32) + return + end + local size = tonumber(cmd_args[1])*32 + if size > 100 then + error('Size too large') + end + settings.size = size + config.save(settings) + + setup_ui() + + log('Size changed to '..settings.size) + elseif cmd == 'alpha' or cmd == "opacity" then + if #cmd_args < 1 then + error("Not enough arguments.") + log("Current alpha/opacity: "..settings.alpha.."/255 = "..settings.alpha/255) + return + end + local alpha = tonumber(cmd_args[1]) + if alpha <= 1 and alpha > 0 then + settings.alpha = math.floor(255 * (alpha)) + else + settings.alpha = math.floor(alpha) + end + config.save(settings) + + setup_ui() + + log('Alpha/Opacity changed to '..settings.alpha..'/255') + elseif cmd:contains('transpar') then + if #cmd_args < 1 then + error("Not enough arguments.") + log("Current transparency: "..(255-settings.alpha).."/255 = "..(255-settings.alpha)/255) + return + end + local transparency = tonumber(cmd_args[1]) + if transparency <= 1 and transparency > 0 then + settings.alpha = math.floor(255 * (1-transparency)) + else + settings.alpha = math.floor(255-transparency) + end + config.save(settings) + + setup_ui() + + log('Transparency changed to '..255-settings.alpha..'/255') + elseif cmd:contains('encumb') then + settings.show_encumbrance = not settings.show_encumbrance + config.save(settings) + + display_encumbrance() + + log('show_encumbrance changed to '..tostring(settings.show_encumbrance)) + elseif cmd:contains('ammo') or cmd:contains('count') then + settings.show_ammo_count = not settings.show_ammo_count + config.save(settings) + + display_ammo_count() + + log('show_ammo_count changed to '..tostring(settings.show_ammo_count)) + elseif cmd == 'hideonzone' or cmd == 'zone' then + settings.hide_on_zone = not settings.hide_on_zone + config.save(settings) + + log('hide_on_zone changed to '..tostring(settings.hide_on_zone)) + elseif cmd == 'hideoncutscene' or cmd == 'cutscene' then + settings.hide_on_cutscene = not settings.hide_on_cutscene + config.save(settings) + + log('hide_on_cutscene changed to '..tostring(settings.hide_on_cutscene)) + elseif cmd == 'justify' then + settings.left_justify = not settings.left_justify + config.save(settings) + + setup_ui() + + log('Ammo text justification changed to '..tostring(settings.left_justify and "Left" or "Right")) + elseif cmd == "testenc" then + display_encumbrance(0xffff) + elseif cmd == "debug" then + if #cmd_args < 1 then + local items = windower.ffxi.get_items() + local e = windower.ffxi.get_items().equipment + for i=0,15 do + local v = equipment_data[i] + local b = e[string.format('%s_bag', v.slot_name)] + local eb = v.bag_id + local ind = v.index + local eind = e[v.slot_name] + local it = v.item_id + local eit = windower.ffxi.get_items(eb, eind).id + log("%s[%d] it=%d eit=%d b=%d eb=%d i=%d ei=%d":format(v.slot_name,i, it, eit, b, eb, ind, eind)) + end + elseif S{"1", "on", "true"}:contains(cmd_args[1]) then + evdebug = true + elseif S{"0", "off", "false"}:contains(cmd_args[1]) then + evdebug = false + end + else + log("HELP:") + log("ev position : move to position (from top left)") + log("ev size : set pixel size of each item slot") + log("ev scale : scale multiplier each item slot (from 32px)") + log("ev alpha : set opacity of display (out of 255)") + log("ev transparency : inverse of alpha (out of 255)") + log("ev ammocount: toggles showing current ammo count") + log("ev encumbrance: toggles showing encumbrance Xs") + log("ev hideonzone: toggles hiding while crossing zone line") + log("ev hideoncutscene: toggles hiding when in cutscene/npc menu/etc") + log("ev justify: toggles between ammo text left and right justify") end -end) \ No newline at end of file +end) From 7ed5899c9cccabf2571a509e216e7bc387e9573a Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Wed, 24 Mar 2021 14:29:18 -0600 Subject: [PATCH 0576/1002] comment header --- addons/equipviewer/equipviewer.lua | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/addons/equipviewer/equipviewer.lua b/addons/equipviewer/equipviewer.lua index edcd404ba1..0ebce5b389 100644 --- a/addons/equipviewer/equipviewer.lua +++ b/addons/equipviewer/equipviewer.lua @@ -1,3 +1,30 @@ +--[[ + Copyright © 2021, Rubenator + 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 NagMeNot 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 Rubenator 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.name = 'EquipViewer' _addon.version = '3.2.4' _addon.author = 'Project Tako, Rubenator' From a95d56fe088be048ef8f6132d9cf5ecd603c6445 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Wed, 24 Mar 2021 14:30:41 -0600 Subject: [PATCH 0577/1002] whitespace fix --- addons/equipviewer/ui_settings.lua | 230 ++++++++++++++--------------- 1 file changed, 115 insertions(+), 115 deletions(-) diff --git a/addons/equipviewer/ui_settings.lua b/addons/equipviewer/ui_settings.lua index ff6d37d50f..463943dd65 100644 --- a/addons/equipviewer/ui_settings.lua +++ b/addons/equipviewer/ui_settings.lua @@ -1,116 +1,116 @@ function refresh_ui_settings() - --Image and text settings - bg_image_settings = { - color = { - alpha = math.floor(80*settings.alpha/255), - red = 0, - blue = 0, - green = 0 - }, - pos = { - x = settings.pos.x, - y = settings.pos.y, - }, - size = { - width = settings.size * 4, - height = settings.size * 4, - }, - draggable = false, - } - equipment_image_settings = { - color = { - alpha = settings.alpha, - red = 255, - blue = 255, - green = 255, - }, - texture = { - fit = true, - }, - size = { - width = settings.size, - height = settings.size, - }, - draggable = false, - } - encumbrance_image_settings = { - color = { - alpha = settings.alpha*0.8, - red = 255, - blue = 255, - green = 255, - }, - texture = { - fit = true, - }, - size = { - width = settings.size, - height = settings.size, - }, - draggable = false, - } - ammo_count_text_settings = { - text = { - size = settings.size*0.27, - alpha = settings.alpha, - red = 255, - blue = 255, - green = 255, - stroke = { - width = 1, - alpha = 127, - red = 0, - green = 0, - blue = 0, - }, - }, - bg = { - alpha = 0, - red = 255, - blue = 255, - green = 255, - }, - pos = { - x = (windower.get_windower_settings().ui_x_res - (settings.pos.x + settings.size*4))*-1, - y = settings.pos.y + settings.size*0.58, - }, - flags = { - draggable = false, - right = true, - bold = true, - italic = true, - }, - } - ammo_count_text_settings_left_justify = { - text = { - size = settings.size*0.27, - alpha = settings.alpha, - red = 255, - blue = 255, - green = 255, - stroke = { - width = 1, - alpha = 127, - red = 0, - green = 0, - blue = 0 - }, - }, - bg = { - alpha = 0, - red = 255, - blue = 255, - green = 255 - }, - pos = { - x = settings.pos.x + settings.size*3, - y = settings.pos.y + settings.size*0.58 - }, - flags = { - draggable = false, - right = false, - bold = true, - italic = true, - }, - } -end \ No newline at end of file + --Image and text settings + bg_image_settings = { + color = { + alpha = math.floor(80*settings.alpha/255), + red = 0, + blue = 0, + green = 0 + }, + pos = { + x = settings.pos.x, + y = settings.pos.y, + }, + size = { + width = settings.size * 4, + height = settings.size * 4, + }, + draggable = false, + } + equipment_image_settings = { + color = { + alpha = settings.alpha, + red = 255, + blue = 255, + green = 255, + }, + texture = { + fit = true, + }, + size = { + width = settings.size, + height = settings.size, + }, + draggable = false, + } + encumbrance_image_settings = { + color = { + alpha = settings.alpha*0.8, + red = 255, + blue = 255, + green = 255, + }, + texture = { + fit = true, + }, + size = { + width = settings.size, + height = settings.size, + }, + draggable = false, + } + ammo_count_text_settings = { + text = { + size = settings.size*0.27, + alpha = settings.alpha, + red = 255, + blue = 255, + green = 255, + stroke = { + width = 1, + alpha = 127, + red = 0, + green = 0, + blue = 0, + }, + }, + bg = { + alpha = 0, + red = 255, + blue = 255, + green = 255, + }, + pos = { + x = (windower.get_windower_settings().ui_x_res - (settings.pos.x + settings.size*4))*-1, + y = settings.pos.y + settings.size*0.58, + }, + flags = { + draggable = false, + right = true, + bold = true, + italic = true, + }, + } + ammo_count_text_settings_left_justify = { + text = { + size = settings.size*0.27, + alpha = settings.alpha, + red = 255, + blue = 255, + green = 255, + stroke = { + width = 1, + alpha = 127, + red = 0, + green = 0, + blue = 0 + }, + }, + bg = { + alpha = 0, + red = 255, + blue = 255, + green = 255 + }, + pos = { + x = settings.pos.x + settings.size*3, + y = settings.pos.y + settings.size*0.58 + }, + flags = { + draggable = false, + right = false, + bold = true, + italic = true, + }, + } +end From ed27828a5ace63d54669d64617f2b838d0362b93 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Wed, 24 Mar 2021 14:32:29 -0600 Subject: [PATCH 0578/1002] header update --- addons/equipviewer/icon_extractor.lua | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/addons/equipviewer/icon_extractor.lua b/addons/equipviewer/icon_extractor.lua index 07cc09a264..d14fdff4ee 100644 --- a/addons/equipviewer/icon_extractor.lua +++ b/addons/equipviewer/icon_extractor.lua @@ -1,6 +1,30 @@ +--[[ + Copyright © 2021, Rubenator + 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 NagMeNot 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 Rubenator 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. +]] -- icon_extractor v1.0.1 -- Written by Rubenator of Leviathan --- Base Code graciously provided by Trv of Windower discord +-- Base Extraction Code graciously provided by Trv of Windower discord local icon_extractor = {} local game_path = windower.pol_path.."\/..\/FINAL FANTASY XI" From 8898ee717e15f77bae9121cbe258b10a70b05b42 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Wed, 24 Mar 2021 14:32:52 -0600 Subject: [PATCH 0579/1002] header update --- addons/equipviewer/ui_settings.lua | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/addons/equipviewer/ui_settings.lua b/addons/equipviewer/ui_settings.lua index 463943dd65..88a5172683 100644 --- a/addons/equipviewer/ui_settings.lua +++ b/addons/equipviewer/ui_settings.lua @@ -1,3 +1,27 @@ +--[[ + Copyright © 2021, Rubenator + 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 NagMeNot 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 Rubenator 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 refresh_ui_settings() --Image and text settings bg_image_settings = { From 5266cf61d911af1451d499a4b797d21068e0f1af Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Wed, 24 Mar 2021 14:47:34 -0600 Subject: [PATCH 0580/1002] header fix --- addons/equipviewer/equipviewer.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/equipviewer/equipviewer.lua b/addons/equipviewer/equipviewer.lua index 0ebce5b389..34172904df 100644 --- a/addons/equipviewer/equipviewer.lua +++ b/addons/equipviewer/equipviewer.lua @@ -10,7 +10,7 @@ * 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 NagMeNot nor the + * Neither the name of EquipViewer nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. From 840f311010e6965ddd17a3fd27d0df00a7b2bb82 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Wed, 24 Mar 2021 14:48:05 -0600 Subject: [PATCH 0581/1002] header fix --- addons/equipviewer/icon_extractor.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/equipviewer/icon_extractor.lua b/addons/equipviewer/icon_extractor.lua index d14fdff4ee..cfefd4acc8 100644 --- a/addons/equipviewer/icon_extractor.lua +++ b/addons/equipviewer/icon_extractor.lua @@ -8,7 +8,7 @@ * 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 NagMeNot nor the + * Neither the name of EquipViewer 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 From f10ba66b98ecf9f4514e00662caa281505314f84 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Wed, 24 Mar 2021 14:48:28 -0600 Subject: [PATCH 0582/1002] header fix --- addons/equipviewer/ui_settings.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/equipviewer/ui_settings.lua b/addons/equipviewer/ui_settings.lua index 88a5172683..37ca71a8c9 100644 --- a/addons/equipviewer/ui_settings.lua +++ b/addons/equipviewer/ui_settings.lua @@ -8,7 +8,7 @@ * 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 NagMeNot nor the + * Neither the name of EquipViewer 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 From 52b8e11089514379b789215ce9d547c99bff5e98 Mon Sep 17 00:00:00 2001 From: Kyle Ricks Date: Wed, 24 Mar 2021 15:13:37 -0700 Subject: [PATCH 0583/1002] Update to Treasury ReadMe.md Updated list of special names to reflect new options (detritus, heroism, moldy, dynad, papers) --- addons/Treasury/ReadMe.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/addons/Treasury/ReadMe.md b/addons/Treasury/ReadMe.md index 769f9ef18c..0b23864f50 100644 --- a/addons/Treasury/ReadMe.md +++ b/addons/Treasury/ReadMe.md @@ -20,6 +20,11 @@ There are a few special key words for `name`: * `avatarites` matches all geode items (HQ) * `currency` matches all Dynamis currency (all three tiers of all three kinds) * `seals` matches the standard seals found in the field (BS, KS, KC, HKC, SKC) +* `detritus` matches Swart Astral Detritus and Murky Astral Detritus +* `heroism` matches Heroism Crystal and Heroism Aggregate +* `moldy` matches all Moldy weapons and neck items from Dynamis Divergence +* `dynad` matches all three card types, all three medal types, and the crafting materials from Dynamis Divergence +* `papers` matches all shards and all void items from Dynamis Divergence * `pool` matches your current treasure pool '//treasury lot|pass|drop clear|list` From 380bab58010fe39b60808b06df73342f815b29e2 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Wed, 24 Mar 2021 23:29:09 +0100 Subject: [PATCH 0584/1002] more fixes more fixes --- addons/battlemod/battlemod.lua | 27 ++++++----- addons/battlemod/generic_helpers.lua | 7 +-- addons/battlemod/parse_action_packet.lua | 57 +++++++++++++++++------- 3 files changed, 60 insertions(+), 31 deletions(-) diff --git a/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index ca551b9827..12b768eb5f 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -418,16 +418,18 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec end end outstr = (clean_msg(outstr - :gsub('$\123actor\125',actor_article..color_it((actor.name or '') .. (actor.owner_name or ""),color_arr[actor.owner or actor.type])) - :gsub('$\123status\125',status or '') - :gsub('$\123item\125',color_it(item or '',color_arr.itemcol)) - :gsub('$\123target\125',target_article..color_it(target.name or '',color_arr[target.owner or target.type])) - :gsub('$\123spell\125',color_it(spell or '',color_arr.spellcol)) - :gsub('$\123skill\125',color_it(skill or '',color_arr.abilcol)) - :gsub('$\123number\125',number or '') - :gsub('$\123number2\125',number2 or '') - :gsub('$\123skill\125',skill or '') - :gsub('$\123lb\125','\7'))) + :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'))) 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 @@ -479,8 +481,9 @@ function multi_packet(...) 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]) or res.action_messages[multi_msg[ind]][language] outstr = clean_msg(outstr - :gsub('$\123target\125',targets) - :gsub('$\123status\125',ind)) + :gsub('${target}\'s',targets) + :gsub('${target}',targets) + :gsub('${status}',ind)) windower.add_to_chat(res.action_messages[multi_msg[ind]].color,outstr) multi_targs[ind] = nil multi_msg[ind] = nil diff --git a/addons/battlemod/generic_helpers.lua b/addons/battlemod/generic_helpers.lua index 1759cafcef..c3677a0eb2 100644 --- a/addons/battlemod/generic_helpers.lua +++ b/addons/battlemod/generic_helpers.lua @@ -39,9 +39,10 @@ end function colconv(str,key) -- Used in the options_load() function local out - strnum = tonumber(str) + 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) @@ -134,7 +135,7 @@ function plural_actor(msg) :gsub('${actor} attains ', '${actor} attain ') :gsub('${actor} loses ', '${actor} lose ') :gsub('${actor} falls ', '${actor} fall ') - :gsub("${actor}'s ", '${actor} ') + :gsub("${actor}'s ", "${actor}' ") :gsub('${actor} misses ' , '${actor} miss ') :gsub('${actor} calls ' , '${actor} call ') :gsub('${actor} learns ' , '${actor} learn ') @@ -177,7 +178,7 @@ function plural_target(msg) :gsub('${target} takes ', '${target} take ') :gsub('${target} is ', '${target} are ') :gsub('${target} recovers ', '${target} recover ') - :gsub("${target}'s ", '${target} ') + :gsub("${target}'s ", targets_condensed and '${target} ' or "${target}' ") :gsub('${target} falls ', '${target} fall ') :gsub('${target} uses ', '${target} use ') :gsub('${target} resists', '${target} resist') diff --git a/addons/battlemod/parse_action_packet.lua b/addons/battlemod/parse_action_packet.lua index 596ac6e2f1..21bc48d486 100644 --- a/addons/battlemod/parse_action_packet.lua +++ b/addons/battlemod/parse_action_packet.lua @@ -10,7 +10,7 @@ function parse_action_packet(act) 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)) --fix for ffxi chat splits on trusts with - + 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 @@ -329,7 +329,9 @@ function parse_action_packet(act) :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 or 'ERROR 116') - :gsub('${actor}',color_it((act.actor.name or 'ERROR 117' ) .. (act.actor.owner_name or "") ,color_arr[act.actor.owner or act.actor.type])) + :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) @@ -358,8 +360,16 @@ function parse_action_packet(act) else m.simp_add_name = 'AE' end local msg,numb = simplify_message(m.add_effect_message) - if not simplify and common_nouns:contains(act.actor.id) then - msg = actor_noun(msg) + if not simplify then + 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) + end + if targets_condensed or plural_entities:contains(v.target[1].id) then + msg = plural_target(msg) + 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 @@ -372,7 +382,9 @@ function parse_action_packet(act) :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}',color_it(act.actor.name,color_arr[act.actor.owner or act.actor.type])) + :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) @@ -406,8 +418,16 @@ function parse_action_packet(act) end local msg = simplify_message(m.spike_effect_message) - if not simplify and common_nouns:contains(act.actor.id) then - msg = actor_noun(msg) + if not simplify then + 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) + end + if targets_condensed or plural_entities:contains(v.target[1].id) then + msg = plural_target(msg) + 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 @@ -417,7 +437,9 @@ function parse_action_packet(act) :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((simplify and '${target}' or '${actor}'),color_it(act.actor.name,color_arr[act.actor.owner or act.actor.type])) + :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) @@ -569,20 +591,23 @@ function assemble_targets(actor,targs,category,msg) end for i,v in pairs(targets) do - local name - local article = common_nouns:contains(v.id) and not simplify and 'The ' or '' + 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(v.name,color_arr[v.owner or v.type]) - out_str = out_str..article..name..numb + 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 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(v.name,color_arr[v.owner or v.type]) + 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 @@ -637,7 +662,7 @@ function player_info(id) dmg = 'mydmg' end owner = i - owner_name = showownernames and ' (' .. v.mob.name .. ')' + 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 @@ -646,7 +671,7 @@ function player_info(id) dmg = 'mydmg' end owner = i - owner_name = showownernames and ' (' .. v.mob.name .. ')' + owner_name = showownernames and ' ('..color_it(v.mob.name, color_arr[owner or typ])..')' break end end @@ -682,7 +707,7 @@ function player_info(id) end end if not typ then typ = 'debug' end - return {name=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 nil),race = player_table.race} + return {name=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) From b6ca5b56e427e360029ba98663353e9f6205676e Mon Sep 17 00:00:00 2001 From: funkworkz Date: Fri, 26 Mar 2021 15:38:57 -0500 Subject: [PATCH 0585/1002] Update setbgm.lua Official song name currently unknown. Added in March 2021 update. --- addons/setbgm/setbgm.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/setbgm/setbgm.lua b/addons/setbgm/setbgm.lua index ca6917db10..0edd4548b9 100644 --- a/addons/setbgm/setbgm.lua +++ b/addons/setbgm/setbgm.lua @@ -50,7 +50,7 @@ music_types = { } songs = { - [25]='Voracious Resurgence Unknown 1', [26]='Voracious Resurgence Unknown 2', [27]='Voracious Resurgence Unknown 3', [28]='Voracious Resurgence Unknown 4', [29]="Devils' Delight", + [25]='Voracious Resurgence Unknown 1', [26]='Voracious Resurgence Unknown 2', [27]='Voracious Resurgence Unknown 3', [28]='Voracious Resurgence Unknown 4', [29]="Devils' Delight", [30]="Odyssey - Bumba", [40]='Cloister of Time and Souls', [41]='Royal Wanderlust', [42]='Snowdrift Waltz', [43]='Troubled Shadows', [44]='Where Lords Rule Not', [45]='Summers Lost', [46]='Goddess Divine', [47]='Echoes of Creation', [48]='Main Theme', [49]='Luck of the Mog', [50]='Feast of the Ladies', [51]='Abyssea - Scarlet Skies, Shadowed Plains', [52]='Melodies Errant', [53]='Shinryu', [54]='Everlasting Bonds', [55]='Provenance Watcher', [56]='Where it All Begins', [57]='Steel Sings, Blades Dance', [58]='A New Direction', [59]='The Pioneers', [60]='Into Lands Primeval - Ulbuka', [61]="Water's Umbral Knell", [62]='Keepers of the Wild', [63]='The Sacred City of Adoulin', [64]='Breaking Ground', [65]='Hades', [66]='Arciela', [67]='Mog Resort', [68]='Worlds Away', [69]="Distant Worlds (Nanaa Mihgo's version)", From adbe5713f59f0188bc223bf19aab8380e06926a5 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Mon, 29 Mar 2021 11:30:56 -0600 Subject: [PATCH 0586/1002] moved to main lua --- addons/equipviewer/ui_settings.lua | 140 ----------------------------- 1 file changed, 140 deletions(-) delete mode 100644 addons/equipviewer/ui_settings.lua diff --git a/addons/equipviewer/ui_settings.lua b/addons/equipviewer/ui_settings.lua deleted file mode 100644 index 37ca71a8c9..0000000000 --- a/addons/equipviewer/ui_settings.lua +++ /dev/null @@ -1,140 +0,0 @@ ---[[ - Copyright © 2021, Rubenator - 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 EquipViewer 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 Rubenator 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 refresh_ui_settings() - --Image and text settings - bg_image_settings = { - color = { - alpha = math.floor(80*settings.alpha/255), - red = 0, - blue = 0, - green = 0 - }, - pos = { - x = settings.pos.x, - y = settings.pos.y, - }, - size = { - width = settings.size * 4, - height = settings.size * 4, - }, - draggable = false, - } - equipment_image_settings = { - color = { - alpha = settings.alpha, - red = 255, - blue = 255, - green = 255, - }, - texture = { - fit = true, - }, - size = { - width = settings.size, - height = settings.size, - }, - draggable = false, - } - encumbrance_image_settings = { - color = { - alpha = settings.alpha*0.8, - red = 255, - blue = 255, - green = 255, - }, - texture = { - fit = true, - }, - size = { - width = settings.size, - height = settings.size, - }, - draggable = false, - } - ammo_count_text_settings = { - text = { - size = settings.size*0.27, - alpha = settings.alpha, - red = 255, - blue = 255, - green = 255, - stroke = { - width = 1, - alpha = 127, - red = 0, - green = 0, - blue = 0, - }, - }, - bg = { - alpha = 0, - red = 255, - blue = 255, - green = 255, - }, - pos = { - x = (windower.get_windower_settings().ui_x_res - (settings.pos.x + settings.size*4))*-1, - y = settings.pos.y + settings.size*0.58, - }, - flags = { - draggable = false, - right = true, - bold = true, - italic = true, - }, - } - ammo_count_text_settings_left_justify = { - text = { - size = settings.size*0.27, - alpha = settings.alpha, - red = 255, - blue = 255, - green = 255, - stroke = { - width = 1, - alpha = 127, - red = 0, - green = 0, - blue = 0 - }, - }, - bg = { - alpha = 0, - red = 255, - blue = 255, - green = 255 - }, - pos = { - x = settings.pos.x + settings.size*3, - y = settings.pos.y + settings.size*0.58 - }, - flags = { - draggable = false, - right = false, - bold = true, - italic = true, - }, - } -end From 4976f5e244053caeb4699b69935e4e44c75633a8 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Mon, 29 Mar 2021 11:31:42 -0600 Subject: [PATCH 0587/1002] Added bg settings and commands and other fixes --- addons/equipviewer/equipviewer.lua | 274 ++++++++++++++++++++++++----- 1 file changed, 230 insertions(+), 44 deletions(-) diff --git a/addons/equipviewer/equipviewer.lua b/addons/equipviewer/equipviewer.lua index 34172904df..17bcbeb31c 100644 --- a/addons/equipviewer/equipviewer.lua +++ b/addons/equipviewer/equipviewer.lua @@ -39,7 +39,6 @@ local functions = require('functions') local packets = require('packets') local icon_extractor = require('icon_extractor') --icon_extractor.ffxi_path('C:/Program Files (x86)/PlayOnline/SquareEnix/FINAL FANTASY XI') -require('ui_settings') local equipment_data = { [0] = {slot_name = 'main', slot_id = 0, display_pos = 0, item_id = 0, image = nil}, @@ -72,7 +71,35 @@ local defaults = T{ y = 500 }, size = 32, - alpha = 230, + ammo_text = T{ + alpha = 230, + red = 255, + green = 255, + blue = 255, + stroke = T{ + width = 1, + alpha = 127, + red = 0, + green = 0, + blue = 0, + }, + flags = T{ + bold = true, + italic = true, + } + }, + icon = T{ + alpha = 230, + red = 255, + green = 255, + blue = 255, + }, + bg = T{ + alpha = 72, + red = 0, + green = 0, + blue = 0, + }, show_encumbrance = true, show_ammo_count = true, hide_on_zone = true, @@ -111,8 +138,8 @@ local function update_equipment_slot(source, slot, bag, index, item, count) if evdebug then bag = slot_data.bag_id index = slot_data.index - log("%s %s %d %d %d":format(source, slot_data.slot_name, item, bag or -1, index or -1)) - print("%s %s %d %d %d":format(source, slot_data.slot_name, item, bag or -1, index or -1)) + log('%s %s %d %d %d':format(source, slot_data.slot_name, item, bag or -1, index or -1)) + print('%s %s %d %d %d':format(source, slot_data.slot_name, item, bag or -1, index or -1)) end if slot_data.slot_name == 'ammo' then slot_data.count = count or slot_data.count or 0 @@ -133,7 +160,7 @@ local function update_equipment_slot(source, slot, bag, index, item, count) end if windower.file_exists(icon_path) then slot_data.image:path(icon_path) - slot_data.image:alpha(settings.alpha) + slot_data.image:alpha(settings.icon.alpha) slot_data.image:show() end end @@ -164,7 +191,7 @@ local function setup_ui() slot.image = images.new(equipment_image_settings) position(slot) end - update_equipment_slots("setup_ui") + update_equipment_slots('setup_ui') for key, slot in pairs(encumbrance_data) do slot.image = images.new(encumbrance_image_settings) @@ -184,6 +211,7 @@ windower.register_event('load', function() config.reload(settings) else settings = config.load(defaults) + config.save(settings) end --Make sure icons directory exists if not windower.dir_exists(string.format('%sicons', windower.addon_path)) then @@ -207,6 +235,7 @@ windower.register_event('login', function() config.reload(settings) else settings = config.load(defaults) + config.save(settings) end setup_ui() update_equipment_slots('login') @@ -237,7 +266,7 @@ windower.register_event('incoming chunk', function(id, original, modified, injec if slot then if packet['Status'] ~= 5 then --item not equipped - update_equipment_slot:schedule(0, "0x%x":format(id), slot, 0, 0, 0) + update_equipment_slot:schedule(0, '0x%x':format(id), slot, 0, 0, 0) return end if slot == 3 then --ammo @@ -245,7 +274,7 @@ windower.register_event('incoming chunk', function(id, original, modified, injec display_ammo_count(count) end local item = packet['Item'] - update_equipment_slot:schedule(0,"0x%x":format(id), slot, bag, index, item, count) + update_equipment_slot:schedule(0,'0x%x':format(id), slot, bag, index, item, count) end elseif id == 0x01B then -- Job Info (Encumbrance Flags) local packet = packets.parse('incoming', original) @@ -377,7 +406,7 @@ function display_ammo_count(count) if not settings.show_ammo_count or not count or count <= 1 then ammo_count_text:hide() else - ammo_count_text:text(count and tostring(count) or "") + ammo_count_text:text(count and tostring(count) or '') ammo_count_text:show() end end @@ -400,13 +429,13 @@ end) windower.register_event('addon command', function (...) config.reload(settings) coroutine.sleep(0.5) - local cmd = (...) and (...):lower() or "" + local cmd = (...) and (...):lower() or '' local cmd_args = {select(2, ...)} if cmd == 'position' or cmd == 'pos' then if #cmd_args < 2 then - error("Not enough arguments.") - log("Current position: "..settings.pos.x.." "..settings.pos.y) + error('Not enough arguments.') + log('Current position: '..settings.pos.x..' '..settings.pos.y) return end @@ -419,8 +448,8 @@ windower.register_event('addon command', function (...) log('Position changed to '..settings.pos.x..', '..settings.pos.y) elseif cmd == 'size' then if #cmd_args < 1 then - error("Not enough arguments.") - log("Current size: "..settings.size) + error('Not enough arguments.') + log('Current size: '..settings.size) return end @@ -432,8 +461,8 @@ windower.register_event('addon command', function (...) log('Size changed to '..settings.size) elseif cmd == 'scale' then if #cmd_args < 1 then - error("Not enough arguments.") - log("Current scale: "..settings.size/32) + error('Not enough arguments.') + log('Current scale: '..settings.size/32) return end local size = tonumber(cmd_args[1])*32 @@ -446,40 +475,78 @@ windower.register_event('addon command', function (...) setup_ui() log('Size changed to '..settings.size) - elseif cmd == 'alpha' or cmd == "opacity" then + elseif cmd == 'alpha' or cmd == 'opacity' then if #cmd_args < 1 then - error("Not enough arguments.") - log("Current alpha/opacity: "..settings.alpha.."/255 = "..settings.alpha/255) + error('Not enough arguments.') + log('Current alpha/opacity: %d/255 = %d%%':format( + settings.icon.alpha, math.floor(settings.icon.alpha/255*100) + )) return end local alpha = tonumber(cmd_args[1]) if alpha <= 1 and alpha > 0 then - settings.alpha = math.floor(255 * (alpha)) + settings.icon.alpha = math.floor(255 * (alpha)) else - settings.alpha = math.floor(alpha) + settings.icon.alpha = math.floor(alpha) end config.save(settings) setup_ui() - log('Alpha/Opacity changed to '..settings.alpha..'/255') + log('Alpha/Opacity changed to '..settings.icon.alpha..'/255') elseif cmd:contains('transpar') then if #cmd_args < 1 then - error("Not enough arguments.") - log("Current transparency: "..(255-settings.alpha).."/255 = "..(255-settings.alpha)/255) + error('Not enough arguments.') + log('Current transparency: %d/255 = %d%%':format( + (255-settings.icon.alpha), math.floor((255-settings.icon.alpha)/255)*100 + )) return end local transparency = tonumber(cmd_args[1]) if transparency <= 1 and transparency > 0 then - settings.alpha = math.floor(255 * (1-transparency)) + settings.icon.alpha = math.floor(255 * (1-transparency)) else - settings.alpha = math.floor(255-transparency) + settings.icon.alpha = math.floor(255-transparency) end config.save(settings) setup_ui() - log('Transparency changed to '..255-settings.alpha..'/255') + log('Transparency changed to '..255-settings.icon.alpha..'/255') + elseif cmd == 'background' or cmd == 'bg' then + if #cmd_args < 1 then + error('Not enough arguments.') + log('Current BG color: RED:%d/255 GREEN:%d/255 BLUE:%d/255 ALPHA:%d/255 = %d%%':format( + settings.bg.red, settings.bg.green, settings.bg.blue, settings.bg.alpha, math.floor(settings.bg.alpha/255*100) + )) + return + elseif #cmd_args == 1 then + local alpha = tonumber(cmd_args[1]) + if alpha <= 1 and alpha > 0 then + settings.bg.alpha = math.floor(255 * (alpha)) + else + settings.bg.alpha = math.floor(alpha) + end + elseif #cmd_args >= 3 then + settings.bg.red = tonumber(cmd_args[1]) + settings.bg.green = tonumber(cmd_args[2]) + settings.bg.blue = tonumber(cmd_args[3]) + if #cmd_args == 4 then + local alpha = tonumber(cmd_args[4]) + if alpha <= 1 and alpha > 0 then + settings.bg.alpha = math.floor(255 * (alpha)) + else + settings.bg.alpha = math.floor(alpha) + end + end + end + config.save(settings) + + setup_ui() + + log('BG color changed to: RED:%d/255 GREEN:%d/255 BLUE:%d/255 ALPHA:%d/255 = %d%%':format( + settings.bg.red, settings.bg.green, settings.bg.blue, settings.bg.alpha, math.floor(settings.bg.alpha/255*100) + )) elseif cmd:contains('encumb') then settings.show_encumbrance = not settings.show_encumbrance config.save(settings) @@ -510,10 +577,10 @@ windower.register_event('addon command', function (...) setup_ui() - log('Ammo text justification changed to '..tostring(settings.left_justify and "Left" or "Right")) - elseif cmd == "testenc" then + log('Ammo text justification changed to '..tostring(settings.left_justify and 'Left' or 'Right')) + elseif cmd == 'testenc' then display_encumbrance(0xffff) - elseif cmd == "debug" then + elseif cmd == 'debug' then if #cmd_args < 1 then local items = windower.ffxi.get_items() local e = windower.ffxi.get_items().equipment @@ -525,24 +592,143 @@ windower.register_event('addon command', function (...) local eind = e[v.slot_name] local it = v.item_id local eit = windower.ffxi.get_items(eb, eind).id - log("%s[%d] it=%d eit=%d b=%d eb=%d i=%d ei=%d":format(v.slot_name,i, it, eit, b, eb, ind, eind)) + log('%s[%d] it=%d eit=%d b=%d eb=%d i=%d ei=%d':format(v.slot_name,i, it, eit, b, eb, ind, eind)) end - elseif S{"1", "on", "true"}:contains(cmd_args[1]) then + elseif S{'1', 'on', 'true'}:contains(cmd_args[1]) then evdebug = true - elseif S{"0", "off", "false"}:contains(cmd_args[1]) then + elseif S{'0', 'off', 'false'}:contains(cmd_args[1]) then evdebug = false end else - log("HELP:") - log("ev position : move to position (from top left)") - log("ev size : set pixel size of each item slot") - log("ev scale : scale multiplier each item slot (from 32px)") - log("ev alpha : set opacity of display (out of 255)") - log("ev transparency : inverse of alpha (out of 255)") - log("ev ammocount: toggles showing current ammo count") - log("ev encumbrance: toggles showing encumbrance Xs") - log("ev hideonzone: toggles hiding while crossing zone line") - log("ev hideoncutscene: toggles hiding when in cutscene/npc menu/etc") - log("ev justify: toggles between ammo text left and right justify") + log('HELP:') + log('ev position : move to position (from top left)') + log('ev size : set pixel size of each item slot') + log('ev scale : scale multiplier each item slot (from 32px)') + log('ev alpha : set opacity of icons (out of 255)') + log('ev transparency : inverse of alpha (out of 255)') + log('ev background : sets color and transparency of background (out of 255)') + log('ev ammocount: toggles showing current ammo count') + log('ev encumbrance: toggles showing encumbrance Xs') + log('ev hideonzone: toggles hiding while crossing zone line') + log('ev hideoncutscene: toggles hiding when in cutscene/npc menu/etc') + log('ev justify: toggles between ammo text left and right justify') end end) + +function refresh_ui_settings() + --Image and text settings + bg_image_settings = { + alpha = settings.bg.alpha, + color = { + alpha = settings.bg.alpha, + red = settings.bg.red, + green = settings.bg.green, + blue = settings.bg.blue, + }, + pos = { + x = settings.pos.x, + y = settings.pos.y, + }, + size = { + width = settings.size * 4, + height = settings.size * 4, + }, + draggable = false, + } + equipment_image_settings = { + color = { + alpha = settings.icon.alpha, + red = settings.icon.red, + green = settings.icon.green, + blue = settings.icon.blue, + }, + texture = { + fit = true, + }, + size = { + width = settings.size, + height = settings.size, + }, + draggable = false, + } + encumbrance_image_settings = { + color = { + alpha = settings.icon.alpha*0.8, + red = settings.icon.red, + green = settings.icon.green, + blue = settings.icon.blue, + }, + texture = { + fit = true, + }, + size = { + width = settings.size, + height = settings.size, + }, + draggable = false, + } + ammo_count_text_settings = { + text = { + size = settings.size*0.27, + alpha = settings.ammo_text.alpha, + red = settings.ammo_text.red, + green = settings.ammo_text.green, + blue = settings.ammo_text.blue, + stroke = { + width = settings.ammo_text.stroke.width, + alpha = settings.ammo_text.stroke.alpha, + red = settings.ammo_text.stroke.red, + green = settings.ammo_text.stroke.green, + blue = settings.ammo_text.stroke.blue, + }, + }, + bg = { + alpha = 0, + red = 255, + blue = 255, + green = 255 + }, + pos = { + x = (windower.get_windower_settings().ui_x_res - (settings.pos.x + settings.size*4))*-1, + y = settings.pos.y + settings.size*0.58, + }, + flags = { + draggable = false, + right = true, + bold = settings.ammo_text.flags.bold, + italic = settings.ammo_text.flags.italic, + }, + } + ammo_count_text_settings_left_justify = { + text = { + size = settings.size*0.27, + alpha = settings.ammo_text.alpha, + red = settings.ammo_text.red, + green = settings.ammo_text.green, + blue = settings.ammo_text.blue, + stroke = { + width = settings.ammo_text.stroke.width, + alpha = settings.ammo_text.stroke.alpha, + red = settings.ammo_text.stroke.red, + green = settings.ammo_text.stroke.green, + blue = settings.ammo_text.stroke.blue, + }, + }, + bg = { + alpha = 0, + red = 255, + blue = 255, + green = 255 + }, + pos = { + x = settings.pos.x + settings.size*3, + y = settings.pos.y + settings.size*0.58 + }, + flags = { + draggable = false, + right = true, + bold = settings.ammo_text.flags.bold, + italic = settings.ammo_text.flags.italic, + }, + } +end From 955e60834d41be3dfd7ad40af640af60037eb760 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Mon, 29 Mar 2021 11:32:37 -0600 Subject: [PATCH 0588/1002] tab fixes and require parentheses --- addons/equipviewer/icon_extractor.lua | 56 +++++++++++++-------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/addons/equipviewer/icon_extractor.lua b/addons/equipviewer/icon_extractor.lua index cfefd4acc8..cd4443265c 100644 --- a/addons/equipviewer/icon_extractor.lua +++ b/addons/equipviewer/icon_extractor.lua @@ -27,11 +27,11 @@ -- Base Extraction Code graciously provided by Trv of Windower discord local icon_extractor = {} -local game_path = windower.pol_path.."\/..\/FINAL FANTASY XI" +local game_path = windower.pol_path..'\/..\/FINAL FANTASY XI' -local string = require 'string' -local io = require 'io' -local math = require 'math' +local string = require('string') +local io = require('io') +local math = require('math') local concat = table.concat local floor = math.floor @@ -80,7 +80,7 @@ local color_lookup = {} local bmp_segments = {} for i = 0, 255 do - color_lookup[string.char(i)] = '' + color_lookup[string.char(i)] = '' end --[[ @@ -135,9 +135,9 @@ function open_dat(dat_stats) icon_file = dat_stats.file else if not game_path then - error("ffxi_path must be set before using icon_extractor library") + error('ffxi_path must be set before using icon_extractor library') end - filename = game_path .. '/ROM/' .. tostring(dat_stats.dat_path) .. ".DAT" + filename = game_path .. '/ROM/' .. tostring(dat_stats.dat_path) .. '.DAT' icon_file = io.open(filename, 'rb') if not icon_file then return end dat_stats.file = icon_file @@ -151,29 +151,29 @@ local encoded_byte_to_rgba = {} local alpha_encoded_to_decoded_adjusted_char = {} local decoded_byte_to_encoded_char = {} for i = 0, 255 do - encoded_byte_to_rgba[i] = '' - local n = (i % 32) * 8 + floor(i / 32) - encoded_to_decoded_char[char(i)] = char(n) - decoded_byte_to_encoded_char[n] = char(i) - n = n * 2 - n = n < 256 and n or 255 - alpha_encoded_to_decoded_adjusted_char[char(i)] = char(n) + encoded_byte_to_rgba[i] = '' + local n = (i % 32) * 8 + floor(i / 32) + encoded_to_decoded_char[char(i)] = char(n) + decoded_byte_to_encoded_char[n] = char(i) + n = n * 2 + n = n < 256 and n or 255 + alpha_encoded_to_decoded_adjusted_char[char(i)] = char(n) end local decoder = function(a, b, c, d) - return encoded_to_decoded_char[a].. - encoded_to_decoded_char[b].. - encoded_to_decoded_char[c].. - alpha_encoded_to_decoded_adjusted_char[d] + return encoded_to_decoded_char[a].. + encoded_to_decoded_char[b].. + encoded_to_decoded_char[c].. + alpha_encoded_to_decoded_adjusted_char[d] end function convert_item_icon_to_bmp(data) - local color_palette = string.gsub(sub(data, 1, 1024), '(.)(.)(.)(.)', decoder) - -- rather than decoding all 2048 bytes, decode only the palette and index it by encoded byte - for i = 0, 255 do - local offset = i * 4 + 1 - encoded_byte_to_rgba[decoded_byte_to_encoded_char[i]] = sub(color_palette, offset, offset + 3) - end - - return header .. string.gsub(sub(data, 1025, 2048), '(.)', function(a) return encoded_byte_to_rgba[a] end) + local color_palette = string.gsub(sub(data, 1, 1024), '(.)(.)(.)(.)', decoder) + -- rather than decoding all 2048 bytes, decode only the palette and index it by encoded byte + for i = 0, 255 do + local offset = i * 4 + 1 + encoded_byte_to_rgba[decoded_byte_to_encoded_char[i]] = sub(color_palette, offset, offset + 3) + end + + return header .. string.gsub(sub(data, 1025, 2048), '(.)', function(a) return encoded_byte_to_rgba[a] end) end @@ -216,7 +216,7 @@ icon_extractor.ffxi_path = ffxi_path -- Offsets defined specifically for status icons -- * some maps use this format as well, but at 512 x 512 function convert_buff_icon_to_bmp(data) - local length = byte(data, 0x282) -- The length is technically sub(0x281, 0x284), but only 0x282 is unique + local length = byte(data, 0x282) -- The length is technically sub(0x281, 0x284), but only 0x282 is unique if length == 16 then -- uncompressed data = sub(data, 0x2BE, 0x12BD) @@ -236,7 +236,7 @@ function convert_buff_icon_to_bmp(data) data = sub(data, 0x2BE, 0x12BD) end - return header .. data + return header .. data end windower.register_event('unload', function() From e42e631fd24025c1eb50a51904a903757025db7d Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Thu, 1 Apr 2021 04:46:14 +0200 Subject: [PATCH 0589/1002] more fixes more fixes --- addons/battlemod/parse_action_packet.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/battlemod/parse_action_packet.lua b/addons/battlemod/parse_action_packet.lua index 21bc48d486..8261adac3c 100644 --- a/addons/battlemod/parse_action_packet.lua +++ b/addons/battlemod/parse_action_packet.lua @@ -268,7 +268,7 @@ function parse_action_packet(act) 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.cparam or m.param),m.message,act.actor.damage,col) 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 @@ -599,7 +599,7 @@ function assemble_targets(actor,targs,category,msg) if samename[v.name] > 1 then targets_condensed = true else - if (not simplify or msg == 206) and string.find(res.action_messages[msg][language], '${target}\'s') then + 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 From 46485838f7ea9ba43c73d50a6f5676e3fc414616 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Mon, 12 Apr 2021 11:00:43 -0600 Subject: [PATCH 0590/1002] equipviewer bugfix fix ammo left justify display issue and parentheses error --- addons/equipviewer/equipviewer.lua | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/addons/equipviewer/equipviewer.lua b/addons/equipviewer/equipviewer.lua index 17bcbeb31c..64db090b2c 100644 --- a/addons/equipviewer/equipviewer.lua +++ b/addons/equipviewer/equipviewer.lua @@ -479,8 +479,8 @@ windower.register_event('addon command', function (...) if #cmd_args < 1 then error('Not enough arguments.') log('Current alpha/opacity: %d/255 = %d%%':format( - settings.icon.alpha, math.floor(settings.icon.alpha/255*100) - )) + settings.icon.alpha, math.floor(settings.icon.alpha/255*100) + )) return end local alpha = tonumber(cmd_args[1]) @@ -498,8 +498,8 @@ windower.register_event('addon command', function (...) if #cmd_args < 1 then error('Not enough arguments.') log('Current transparency: %d/255 = %d%%':format( - (255-settings.icon.alpha), math.floor((255-settings.icon.alpha)/255)*100 - )) + (255-settings.icon.alpha), math.floor((255-settings.icon.alpha)/255)*100 + )) return end local transparency = tonumber(cmd_args[1]) @@ -517,8 +517,8 @@ windower.register_event('addon command', function (...) if #cmd_args < 1 then error('Not enough arguments.') log('Current BG color: RED:%d/255 GREEN:%d/255 BLUE:%d/255 ALPHA:%d/255 = %d%%':format( - settings.bg.red, settings.bg.green, settings.bg.blue, settings.bg.alpha, math.floor(settings.bg.alpha/255*100) - )) + settings.bg.red, settings.bg.green, settings.bg.blue, settings.bg.alpha, math.floor(settings.bg.alpha/255*100) + )) return elseif #cmd_args == 1 then local alpha = tonumber(cmd_args[1]) @@ -545,8 +545,8 @@ windower.register_event('addon command', function (...) setup_ui() log('BG color changed to: RED:%d/255 GREEN:%d/255 BLUE:%d/255 ALPHA:%d/255 = %d%%':format( - settings.bg.red, settings.bg.green, settings.bg.blue, settings.bg.alpha, math.floor(settings.bg.alpha/255*100) - )) + settings.bg.red, settings.bg.green, settings.bg.blue, settings.bg.alpha, math.floor(settings.bg.alpha/255*100) + )) elseif cmd:contains('encumb') then settings.show_encumbrance = not settings.show_encumbrance config.save(settings) @@ -726,7 +726,7 @@ function refresh_ui_settings() }, flags = { draggable = false, - right = true, + right = false, bold = settings.ammo_text.flags.bold, italic = settings.ammo_text.flags.italic, }, From 604d2886e7b50e6693e16f479e154ed60da74413 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Tue, 13 Apr 2021 09:12:49 -0600 Subject: [PATCH 0591/1002] Equipviewer Various Fixes --- addons/equipviewer/equipviewer.lua | 58 ++++++++++++------------------ 1 file changed, 23 insertions(+), 35 deletions(-) diff --git a/addons/equipviewer/equipviewer.lua b/addons/equipviewer/equipviewer.lua index 64db090b2c..a039e21c70 100644 --- a/addons/equipviewer/equipviewer.lua +++ b/addons/equipviewer/equipviewer.lua @@ -65,36 +65,36 @@ end local ammo_count_text = nil local bg_image = nil -local defaults = T{ - pos = T{ +local defaults = { + pos = { x = 500, y = 500 }, size = 32, - ammo_text = T{ + ammo_text = { alpha = 230, red = 255, green = 255, blue = 255, - stroke = T{ + stroke = { width = 1, alpha = 127, red = 0, green = 0, blue = 0, }, - flags = T{ + flags = { bold = true, italic = true, } }, - icon = T{ + icon = { alpha = 230, red = 255, green = 255, blue = 255, }, - bg = T{ + bg = { alpha = 72, red = 0, green = 0, @@ -106,13 +106,14 @@ local defaults = T{ hide_on_cutscene = true, left_justify = false, } -settings = nil +settings = config.load(defaults) +config.save(settings) local last_encumbrance_bitfield = 0 -- gets the currently equipped item data for the slot information provided -local function get_equipped_item(slotName, slotId, bag, index) +function get_equipped_item(slotName, slotId, bag, index) if not bag or not index then -- from memory - local equipment = windower.ffxi.get_items().equipment + local equipment = windower.ffxi.get_items('equipment') bag = equipment[string.format('%s_bag', slotName)] index = equipment[slotName] if equipment_data[slotId] then @@ -128,7 +129,7 @@ local function get_equipped_item(slotName, slotId, bag, index) end -- desc: Updates the ui object(s) for the given slot -local function update_equipment_slot(source, slot, bag, index, item, count) +function update_equipment_slot(source, slot, bag, index, item, count) local slot_data = equipment_data[slot] slot_data.bag_id = bag or slot_data.bag_id slot_data.index = index or slot_data.index @@ -172,14 +173,14 @@ local function update_equipment_slot(source, slot, bag, index, item, count) end -- Updates the texture for all slots if it's a different piece of equipment -local function update_equipment_slots(source) +function update_equipment_slots(source) for slot in pairs(equipment_data) do update_equipment_slot(source, slot) end end -- Sets up the image and text ui objects for our equipment -local function setup_ui() +function setup_ui() refresh_ui_settings() destroy() @@ -207,12 +208,6 @@ end -- Called when the addon is first loaded. windower.register_event('load', function() - if settings then - config.reload(settings) - else - settings = config.load(defaults) - config.save(settings) - end --Make sure icons directory exists if not windower.dir_exists(string.format('%sicons', windower.addon_path)) then windower.create_dir(string.format('%sicons', windower.addon_path)) @@ -231,12 +226,6 @@ end) -- Called whenever character logs in. windower.register_event('login', function() - if settings then - config.reload(settings) - else - settings = config.load(defaults) - config.save(settings) - end setup_ui() update_equipment_slots('login') end) @@ -479,8 +468,8 @@ windower.register_event('addon command', function (...) if #cmd_args < 1 then error('Not enough arguments.') log('Current alpha/opacity: %d/255 = %d%%':format( - settings.icon.alpha, math.floor(settings.icon.alpha/255*100) - )) + settings.icon.alpha, math.floor(settings.icon.alpha/255*100) + )) return end local alpha = tonumber(cmd_args[1]) @@ -498,8 +487,8 @@ windower.register_event('addon command', function (...) if #cmd_args < 1 then error('Not enough arguments.') log('Current transparency: %d/255 = %d%%':format( - (255-settings.icon.alpha), math.floor((255-settings.icon.alpha)/255)*100 - )) + (255-settings.icon.alpha), math.floor((255-settings.icon.alpha)/255)*100 + )) return end local transparency = tonumber(cmd_args[1]) @@ -517,8 +506,8 @@ windower.register_event('addon command', function (...) if #cmd_args < 1 then error('Not enough arguments.') log('Current BG color: RED:%d/255 GREEN:%d/255 BLUE:%d/255 ALPHA:%d/255 = %d%%':format( - settings.bg.red, settings.bg.green, settings.bg.blue, settings.bg.alpha, math.floor(settings.bg.alpha/255*100) - )) + settings.bg.red, settings.bg.green, settings.bg.blue, settings.bg.alpha, math.floor(settings.bg.alpha/255*100) + )) return elseif #cmd_args == 1 then local alpha = tonumber(cmd_args[1]) @@ -545,8 +534,8 @@ windower.register_event('addon command', function (...) setup_ui() log('BG color changed to: RED:%d/255 GREEN:%d/255 BLUE:%d/255 ALPHA:%d/255 = %d%%':format( - settings.bg.red, settings.bg.green, settings.bg.blue, settings.bg.alpha, math.floor(settings.bg.alpha/255*100) - )) + settings.bg.red, settings.bg.green, settings.bg.blue, settings.bg.alpha, math.floor(settings.bg.alpha/255*100) + )) elseif cmd:contains('encumb') then settings.show_encumbrance = not settings.show_encumbrance config.save(settings) @@ -582,8 +571,7 @@ windower.register_event('addon command', function (...) display_encumbrance(0xffff) elseif cmd == 'debug' then if #cmd_args < 1 then - local items = windower.ffxi.get_items() - local e = windower.ffxi.get_items().equipment + local e = windower.ffxi.get_items('equipment') for i=0,15 do local v = equipment_data[i] local b = e[string.format('%s_bag', v.slot_name)] From 635318e894dea3f76338cd4996224e979cf714e7 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Tue, 13 Apr 2021 09:14:14 -0600 Subject: [PATCH 0592/1002] Equipviewer Various Fixes --- addons/equipviewer/icon_extractor.lua | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/addons/equipviewer/icon_extractor.lua b/addons/equipviewer/icon_extractor.lua index cd4443265c..97d9302b18 100644 --- a/addons/equipviewer/icon_extractor.lua +++ b/addons/equipviewer/icon_extractor.lua @@ -90,17 +90,17 @@ end --]] local item_dat_map = { - [1]={min=1, max=4095, dat_path='118/106', offset=-1}, - [2]={min=4096, max=8191, dat_path='118/107', offset=0}, - [3]={min=8192, max=8703, dat_path='118/110', offset=0}, - [4]={min=8704, max=10239, dat_path='301/115', offset=0}, - [5]={min=10240, max=16383, dat_path='118/109', offset=0}, - [6]={min=16384, max=23039, dat_path='118/108', offset=0}, - [7]={min=23040, max=28671, dat_path='286/73', offset=0}, - [8]={min=28672, max=29695, dat_path='217/21', offset=0}, - [9]={min=29696, max=30719, dat_path='288/80', offset=0}, - [10]={min=61440, max=61951, dat_path='288/67', offset=0}, - [11]={min=65535, max=65535, dat_path='174/48', offset=0}, + [1]={min=0x0001, max=0x0FFF, dat_path='118/106', offset=-1}, -- General Items + [2]={min=0x1000, max=0x1FFF, dat_path='118/107', offset=0}, -- Usable Items + [3]={min=0x2000, max=0x21FF, dat_path='118/110', offset=0}, -- Automaton Items + [4]={min=0x2200, max=0x27FF, dat_path='301/115', offset=0}, -- General Items 2 + [5]={min=0x2800, max=0x3FFF, dat_path='118/109', offset=0}, -- Armor Items + [6]={min=0x4000, max=0x59FF, dat_path='118/108', offset=0}, -- Weapon Items + [7]={min=0x5A00, max=0x6FFF, dat_path='286/73', offset=0}, -- Armor Items 2 + [8]={min=0x7000, max=0x73FF, dat_path='217/21', offset=0}, -- Maze Items, Basic Items + [9]={min=0x7400, max=0x77FF, dat_path='288/80', offset=0}, -- Instinct Items + [10]={min=0xF000, max=0xF1FF, dat_path='288/67', offset=0}, -- Monipulator Items + [11]={min=0xFFFF, max=0xFFFF, dat_path='174/48', offset=0}, -- Gil } local item_by_id = function (id, output_path) From 96f3852c6b6cb369b2541dbb0250174cc8966b6b Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Tue, 13 Apr 2021 09:20:55 -0600 Subject: [PATCH 0593/1002] Add Equipviewer --- addons/addons.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/addons/addons.xml b/addons/addons.xml index e28a2d6b5a..b7ba191326 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -233,6 +233,13 @@ https://github.com/Windower/Lua/issues http://www.ffxiah.com/player/Phoenix/Zohno + + Equipviewer + Tako, Rubenator + Displays current equipment grid on screen. Also can show current Ammo count and current Encumbrance. + https://github.com/Windower/Lua/issues + https://discord.gg/b275nMv + eval Aureus From 23af7587c420be09ade94498ee4dd717f61e3f1b Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Tue, 13 Apr 2021 09:40:38 -0600 Subject: [PATCH 0594/1002] Create README.md --- addons/equipviewer/README.md | 44 ++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 addons/equipviewer/README.md diff --git a/addons/equipviewer/README.md b/addons/equipviewer/README.md new file mode 100644 index 0000000000..7de7a56619 --- /dev/null +++ b/addons/equipviewer/README.md @@ -0,0 +1,44 @@ +**Author:** Tako, Rubenator
    +**Version:** 3.3.0
    +**Date:** April 13, 2021
    + +* Displays current equipment grid on screen. Also can show current Ammo count and current Encumbrance. + +## Settings + +* Most settings can be modified via commands, but you can edit the settings.xml directly for a few uncommon settings. + +**Abbreviation:** `//ev` + +## Commands +1. position : move display to position (from top left) +2. size : set pixel size of each item slot (defaults to 32 -- same as the size of the item icons) +3. scale : scale multiplier for size of each item slot (1 is 32px) -- modifies same setting as size +4. alpha : set opacity of icons (out of 255) +5. transparency : inverse of alpha (out of 255) -- modifies same setting as alpha +6. background : sets color and opacity of background (out of 255) +7. ammocount: toggles showing current ammo count (defaults to on/true) +8. encumbrance: toggles showing encumbrance Xs (defaultis on/true) +9. hideonzone: toggles hiding while crossing zone lines (default is on/true) +10. hideoncutscene: toggles hiding when in cutscene/npc menu/etc (default is on/true) +11. justify: toggles between ammo text being right or left justifed (default is right justified) +12. help: displays explanations of each command + +### Example Commands +``` +//ev pos 700 400 +//ev size 64 +//ev scale 1.5 +//ev alpha 255 +//ev transparency 200 +//ev background 0 0 0 72 +//ev ammocount +//ev encumbrance +//ev hideonzone +//ev hideoncutscene +//ev justify +//ev help +``` + +## Source +The latest source and information for this addon can be found on [GitHub](https://github.com/Windower/Lua/tree/live/addons/equipviewer). From 2457d40d6d6d7b0d42e74b8c4620be74300ea796 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Tue, 13 Apr 2021 09:41:04 -0600 Subject: [PATCH 0595/1002] Update README.md --- addons/equipviewer/README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/addons/equipviewer/README.md b/addons/equipviewer/README.md index 7de7a56619..992f70438a 100644 --- a/addons/equipviewer/README.md +++ b/addons/equipviewer/README.md @@ -39,6 +39,3 @@ //ev justify //ev help ``` - -## Source -The latest source and information for this addon can be found on [GitHub](https://github.com/Windower/Lua/tree/live/addons/equipviewer). From 8d994690d03b8bf34e8d7635f23d6ac6ef80bbfd Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Tue, 13 Apr 2021 10:08:44 -0600 Subject: [PATCH 0596/1002] Equipviewer Icon Extractor Hex Changes --- addons/equipviewer/icon_extractor.lua | 34 +++++++++++++-------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/addons/equipviewer/icon_extractor.lua b/addons/equipviewer/icon_extractor.lua index 97d9302b18..f4ef8dcbac 100644 --- a/addons/equipviewer/icon_extractor.lua +++ b/addons/equipviewer/icon_extractor.lua @@ -22,7 +22,7 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] --- icon_extractor v1.0.1 +-- icon_extractor v1.1.0 -- Written by Rubenator of Leviathan -- Base Extraction Code graciously provided by Trv of Windower discord local icon_extractor = {} @@ -79,7 +79,7 @@ local header = 'BM' .. file_size .. reserved1 .. reserved2 .. starting_address local color_lookup = {} local bmp_segments = {} -for i = 0, 255 do +for i = 0x000, 0x0FF do color_lookup[string.char(i)] = '' end @@ -109,7 +109,7 @@ local item_by_id = function (id, output_path) local id_offset = dat_stats.min + dat_stats.offset icon_file:seek('set', (id - id_offset) * 0xC00 + 0x2BD) - local data = icon_file:read(2048) + local data = icon_file:read(0x800) bmp = convert_item_icon_to_bmp(data) @@ -150,13 +150,13 @@ local encoded_to_decoded_char = {} local encoded_byte_to_rgba = {} local alpha_encoded_to_decoded_adjusted_char = {} local decoded_byte_to_encoded_char = {} -for i = 0, 255 do +for i = 0x000, 0x0FF do encoded_byte_to_rgba[i] = '' - local n = (i % 32) * 8 + floor(i / 32) + local n = (i % 0x20) * 0x8 + floor(i / 0x20) encoded_to_decoded_char[char(i)] = char(n) decoded_byte_to_encoded_char[n] = char(i) - n = n * 2 - n = n < 256 and n or 255 + n = n * 0x2 + n = n < 0x100 and n or 0x0FF alpha_encoded_to_decoded_adjusted_char[char(i)] = char(n) end local decoder = function(a, b, c, d) @@ -166,19 +166,19 @@ local decoder = function(a, b, c, d) alpha_encoded_to_decoded_adjusted_char[d] end function convert_item_icon_to_bmp(data) - local color_palette = string.gsub(sub(data, 1, 1024), '(.)(.)(.)(.)', decoder) + local color_palette = string.gsub(sub(data, 0x001, 0x400), '(.)(.)(.)(.)', decoder) -- rather than decoding all 2048 bytes, decode only the palette and index it by encoded byte - for i = 0, 255 do - local offset = i * 4 + 1 - encoded_byte_to_rgba[decoded_byte_to_encoded_char[i]] = sub(color_palette, offset, offset + 3) + for i = 0x000, 0x0FF do + local offset = i * 0x4 + 0x1 + encoded_byte_to_rgba[decoded_byte_to_encoded_char[i]] = sub(color_palette, offset, offset + 0x3) end - return header .. string.gsub(sub(data, 1025, 2048), '(.)', function(a) return encoded_byte_to_rgba[a] end) + return header .. string.gsub(sub(data, 0x401, 0x800), '(.)', function(a) return encoded_byte_to_rgba[a] end) end local buff_dat_map = { - [1]={min=0, max=1024, dat_path='119/57', offset=0}, + [1]={min=0x000, max=0x400, dat_path='119/57', offset=0}, } function find_buff_dat_map(id) for _,stats in pairs(buff_dat_map) do @@ -220,13 +220,13 @@ function convert_buff_icon_to_bmp(data) if length == 16 then -- uncompressed data = sub(data, 0x2BE, 0x12BD) - data = string.gsub(data, '(...)\128', '%1\255') -- All of the alpha bytes are currently 0 or 0x80. + data = string.gsub(data, '(...)\x80', '%1\xFF') -- All of the alpha bytes are currently 0 or 0x80. elseif length == 08 then -- color table local color_palette = sub(data, 0x2BE, 0x6BD) - color_palette = string.gsub(color_palette, '(...)\128', '%1\255') + color_palette = string.gsub(color_palette, '(...)\x80', '%1\xFF') - local n = 0 - for i = 1, 1024, 4 do + local n = 0x0 + for i = 1, 0x400, 0x4 do color_lookup[char(n)] = sub(color_palette, i, i + 3) n = n + 1 end From 7e1b6993fb67404d56679db25e581eac7675d495 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Tue, 13 Apr 2021 10:10:06 -0600 Subject: [PATCH 0597/1002] Equipviewer finishing touches --- addons/equipviewer/equipviewer.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/addons/equipviewer/equipviewer.lua b/addons/equipviewer/equipviewer.lua index a039e21c70..90acbfb38b 100644 --- a/addons/equipviewer/equipviewer.lua +++ b/addons/equipviewer/equipviewer.lua @@ -25,9 +25,9 @@ (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.name = 'EquipViewer' -_addon.version = '3.2.4' -_addon.author = 'Project Tako, Rubenator' +_addon.name = 'Equipviewer' +_addon.version = '3.3.0' +_addon.author = 'Tako, Rubenator' _addon.commands = { 'equipviewer', 'ev' } require('luau') @@ -591,10 +591,10 @@ windower.register_event('addon command', function (...) log('HELP:') log('ev position : move to position (from top left)') log('ev size : set pixel size of each item slot') - log('ev scale : scale multiplier each item slot (from 32px)') + log('ev scale : scale multiplier for each item slot (from 32px)') log('ev alpha : set opacity of icons (out of 255)') log('ev transparency : inverse of alpha (out of 255)') - log('ev background : sets color and transparency of background (out of 255)') + log('ev background : sets color and opacity of background (out of 255)') log('ev ammocount: toggles showing current ammo count') log('ev encumbrance: toggles showing encumbrance Xs') log('ev hideonzone: toggles hiding while crossing zone line') From 45ed71746eaab9b0004fc9e9c0d86ca790c8bea1 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Tue, 13 Apr 2021 11:34:13 -0600 Subject: [PATCH 0598/1002] Update Equipviewer re-localize functions functions --- addons/equipviewer/equipviewer.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/equipviewer/equipviewer.lua b/addons/equipviewer/equipviewer.lua index 90acbfb38b..d175ab65ed 100644 --- a/addons/equipviewer/equipviewer.lua +++ b/addons/equipviewer/equipviewer.lua @@ -111,7 +111,7 @@ config.save(settings) local last_encumbrance_bitfield = 0 -- gets the currently equipped item data for the slot information provided -function get_equipped_item(slotName, slotId, bag, index) +local function get_equipped_item(slotName, slotId, bag, index) if not bag or not index then -- from memory local equipment = windower.ffxi.get_items('equipment') bag = equipment[string.format('%s_bag', slotName)] @@ -129,7 +129,7 @@ function get_equipped_item(slotName, slotId, bag, index) end -- desc: Updates the ui object(s) for the given slot -function update_equipment_slot(source, slot, bag, index, item, count) +local function update_equipment_slot(source, slot, bag, index, item, count) local slot_data = equipment_data[slot] slot_data.bag_id = bag or slot_data.bag_id slot_data.index = index or slot_data.index @@ -173,14 +173,14 @@ function update_equipment_slot(source, slot, bag, index, item, count) end -- Updates the texture for all slots if it's a different piece of equipment -function update_equipment_slots(source) +local function update_equipment_slots(source) for slot in pairs(equipment_data) do update_equipment_slot(source, slot) end end -- Sets up the image and text ui objects for our equipment -function setup_ui() +local function setup_ui() refresh_ui_settings() destroy() From 47c8acc7ecde0e6ab3a2edda2958273bc8973051 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Thu, 15 Apr 2021 18:53:59 -0600 Subject: [PATCH 0599/1002] image fit bugfix and new game_path option --- addons/equipviewer/equipviewer.lua | 32 +++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/addons/equipviewer/equipviewer.lua b/addons/equipviewer/equipviewer.lua index d175ab65ed..23793f7baf 100644 --- a/addons/equipviewer/equipviewer.lua +++ b/addons/equipviewer/equipviewer.lua @@ -26,7 +26,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] _addon.name = 'Equipviewer' -_addon.version = '3.3.0' +_addon.version = '3.3.1' _addon.author = 'Tako, Rubenator' _addon.commands = { 'equipviewer', 'ev' } @@ -38,7 +38,6 @@ local texts = require('texts') local functions = require('functions') local packets = require('packets') local icon_extractor = require('icon_extractor') ---icon_extractor.ffxi_path('C:/Program Files (x86)/PlayOnline/SquareEnix/FINAL FANTASY XI') local equipment_data = { [0] = {slot_name = 'main', slot_id = 0, display_pos = 0, item_id = 0, image = nil}, @@ -108,6 +107,9 @@ local defaults = { } settings = config.load(defaults) config.save(settings) +if settings.game_path then + icon_extractor.ffxi_path(settings.game_path) +end local last_encumbrance_bitfield = 0 -- gets the currently equipped item data for the slot information provided @@ -420,8 +422,28 @@ windower.register_event('addon command', function (...) coroutine.sleep(0.5) local cmd = (...) and (...):lower() or '' local cmd_args = {select(2, ...)} + print(cmd) + if cmd == "gamepath" or cmd == "game_path" then + if #cmd_args == 0 then + error("Must provide path.") + log('Current Path: %s':format( + "\""..settings.game_path.."\"" or "(Default): \""..windower.pol_path.."\/..\/FINAL FANTASY XI\"" + )) + return + end + local path = table.concat(cmd_args, " ") + if path:lower() == "default" then + settings.game_path = nil + else + settings.game_path = table.concat(cmd_args, " ") + end + config.save(settings) + icon_extractor.ffxi_path(settings.game_path) + + setup_ui() - if cmd == 'position' or cmd == 'pos' then + log('game_path set to "%s"':format(path)) + elseif cmd == 'position' or cmd == 'pos' then if #cmd_args < 2 then error('Not enough arguments.') log('Current position: '..settings.pos.x..' '..settings.pos.y) @@ -631,7 +653,7 @@ function refresh_ui_settings() blue = settings.icon.blue, }, texture = { - fit = true, + fit = false, }, size = { width = settings.size, @@ -647,7 +669,7 @@ function refresh_ui_settings() blue = settings.icon.blue, }, texture = { - fit = true, + fit = false, }, size = { width = settings.size, From 0b74ca05f1f5459cb78620f1d3a3e8c22a0a769e Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Thu, 15 Apr 2021 18:55:43 -0600 Subject: [PATCH 0600/1002] equipviewer game_path fix --- addons/equipviewer/icon_extractor.lua | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/addons/equipviewer/icon_extractor.lua b/addons/equipviewer/icon_extractor.lua index f4ef8dcbac..36b3ff2e49 100644 --- a/addons/equipviewer/icon_extractor.lua +++ b/addons/equipviewer/icon_extractor.lua @@ -22,12 +22,13 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] --- icon_extractor v1.1.0 +-- icon_extractor v1.1.1 -- Written by Rubenator of Leviathan -- Base Extraction Code graciously provided by Trv of Windower discord local icon_extractor = {} -local game_path = windower.pol_path..'\/..\/FINAL FANTASY XI' +local game_path_default = windower.pol_path..'\/..\/FINAL FANTASY XI' +local game_path = game_path_default local string = require('string') local io = require('io') @@ -138,8 +139,12 @@ function open_dat(dat_stats) error('ffxi_path must be set before using icon_extractor library') end filename = game_path .. '/ROM/' .. tostring(dat_stats.dat_path) .. '.DAT' - icon_file = io.open(filename, 'rb') - if not icon_file then return end + icon_file, err = io.open(filename, 'rb') + if not icon_file then + print(err) + error(err) + return + end dat_stats.file = icon_file end return icon_file @@ -207,7 +212,8 @@ icon_extractor.buff_by_id = buff_by_id local ffxi_path = function(location) - game_path = location + game_path = location or game_path_default + close_dats() end icon_extractor.ffxi_path = ffxi_path @@ -239,17 +245,23 @@ function convert_buff_icon_to_bmp(data) return header .. data end -windower.register_event('unload', function() +function close_dats() for _,dat in pairs(item_dat_map) do if dat and dat.file then dat.file:close() + dat.file = nil end end for _,dat in pairs(buff_dat_map) do if dat and dat.file then dat.file:close() + dat.file = nil end end +end + +windower.register_event('unload', function() + close_dats() end); return icon_extractor From baacbcf04c994e7c7ba0e4df0cae2d16d19a8d75 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Thu, 15 Apr 2021 19:00:00 -0600 Subject: [PATCH 0601/1002] equipviewer add game_path --- addons/equipviewer/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/equipviewer/README.md b/addons/equipviewer/README.md index 992f70438a..cd17da9c15 100644 --- a/addons/equipviewer/README.md +++ b/addons/equipviewer/README.md @@ -22,7 +22,8 @@ 9. hideonzone: toggles hiding while crossing zone lines (default is on/true) 10. hideoncutscene: toggles hiding when in cutscene/npc menu/etc (default is on/true) 11. justify: toggles between ammo text being right or left justifed (default is right justified) -12. help: displays explanations of each command +12. game_path : sets path to FFXI folder where you want dats extracted from. Defaults to the "Final Fantasy XI" folder next to the folder containing the launcher (ussually POL.exe). +13. help: displays explanations of each command ### Example Commands ``` From dbefed6b714ab6d11a834a315c5f88cddc441b6f Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Thu, 15 Apr 2021 19:08:35 -0600 Subject: [PATCH 0602/1002] equipviewer remove extra print --- addons/equipviewer/icon_extractor.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/equipviewer/icon_extractor.lua b/addons/equipviewer/icon_extractor.lua index 36b3ff2e49..f5b71853a5 100644 --- a/addons/equipviewer/icon_extractor.lua +++ b/addons/equipviewer/icon_extractor.lua @@ -141,7 +141,6 @@ function open_dat(dat_stats) filename = game_path .. '/ROM/' .. tostring(dat_stats.dat_path) .. '.DAT' icon_file, err = io.open(filename, 'rb') if not icon_file then - print(err) error(err) return end From 0cfab9b81b4c633d6168e8f8717b8a8c9a5d50d4 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Thu, 15 Apr 2021 19:09:18 -0600 Subject: [PATCH 0603/1002] equipviewer remove extra print --- addons/equipviewer/equipviewer.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/equipviewer/equipviewer.lua b/addons/equipviewer/equipviewer.lua index 23793f7baf..24d2078e24 100644 --- a/addons/equipviewer/equipviewer.lua +++ b/addons/equipviewer/equipviewer.lua @@ -422,7 +422,6 @@ windower.register_event('addon command', function (...) coroutine.sleep(0.5) local cmd = (...) and (...):lower() or '' local cmd_args = {select(2, ...)} - print(cmd) if cmd == "gamepath" or cmd == "game_path" then if #cmd_args == 0 then error("Must provide path.") From 04ca84cfa7f789a3b9865f86f905e2724653f0b0 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Fri, 16 Apr 2021 11:41:56 -0600 Subject: [PATCH 0604/1002] equipviewer ffxi_path update DO NOT ACCEPT/MERGE THIS till the luacore patch adding `windower.ffxi_path` is deployed --- addons/equipviewer/icon_extractor.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/equipviewer/icon_extractor.lua b/addons/equipviewer/icon_extractor.lua index f5b71853a5..0424e7b58d 100644 --- a/addons/equipviewer/icon_extractor.lua +++ b/addons/equipviewer/icon_extractor.lua @@ -22,12 +22,12 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] --- icon_extractor v1.1.1 +-- icon_extractor v1.1.2 -- Written by Rubenator of Leviathan -- Base Extraction Code graciously provided by Trv of Windower discord local icon_extractor = {} -local game_path_default = windower.pol_path..'\/..\/FINAL FANTASY XI' +local game_path_default = windower.ffxi_path local game_path = game_path_default local string = require('string') From a6f4394d940f0c171bf03da8d77d651981a26c9f Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Fri, 16 Apr 2021 11:47:26 -0600 Subject: [PATCH 0605/1002] update equipviewer ffxi_path --- addons/equipviewer/equipviewer.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/equipviewer/equipviewer.lua b/addons/equipviewer/equipviewer.lua index 24d2078e24..5e76923075 100644 --- a/addons/equipviewer/equipviewer.lua +++ b/addons/equipviewer/equipviewer.lua @@ -426,7 +426,7 @@ windower.register_event('addon command', function (...) if #cmd_args == 0 then error("Must provide path.") log('Current Path: %s':format( - "\""..settings.game_path.."\"" or "(Default): \""..windower.pol_path.."\/..\/FINAL FANTASY XI\"" + "\""..settings.game_path.."\"" or "(Default): \""..windower.ffxi_path )) return end From 2c9d0e650864923baccc9365ff1ccb6393f112f8 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Sat, 17 Apr 2021 16:03:10 +0200 Subject: [PATCH 0606/1002] requested changes requested changes --- addons/battlemod/battlemod.lua | 47 ++-- addons/battlemod/generic_helpers.lua | 283 ++++++++++++++++------- addons/battlemod/parse_action_packet.lua | 77 +++--- addons/battlemod/statics.lua | 55 +++++ 4 files changed, 316 insertions(+), 146 deletions(-) diff --git a/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index 12b768eb5f..904570df19 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -253,8 +253,8 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec ------- 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) + 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..' ' @@ -262,9 +262,9 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec ------- 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) + 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) @@ -286,14 +286,14 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec ------- 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 + 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) @@ -318,16 +318,17 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec 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) + msg = plural_actor(msg, am.message_id) end if plural_entities:contains(am.target_id) then - msg = plural_target(msg) + 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 '')) + :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 @@ -363,10 +364,10 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec 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) + outstr = plural_actor(outstr, am.message_id) end if plural_entities:contains(am.target_id) then - outstr = plural_target(outstr) + outstr = plural_target(outstr, am.message_id) end local fields = fieldsearch(outstr) @@ -429,7 +430,7 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec :gsub('${number}',number or '') :gsub('${number2}',number2 or '') :gsub('${skill}',skill or '') - :gsub('${lb}','\7'))) + :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 @@ -445,8 +446,8 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec ------------ 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 + 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..') -------------') @@ -479,11 +480,11 @@ 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]) or res.action_messages[multi_msg[ind]][language] + 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)) + :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 diff --git a/addons/battlemod/generic_helpers.lua b/addons/battlemod/generic_helpers.lua index c3677a0eb2..1f015ae554 100644 --- a/addons/battlemod/generic_helpers.lua +++ b/addons/battlemod/generic_helpers.lua @@ -84,7 +84,7 @@ end function fieldsearch(message) local fieldarr = {} - string.gsub(message,"{(.-)}", function(a) fieldarr[a] = true end) + string.gsub(message,'{(.-)}', function(a) fieldarr[a] = true end) return fieldarr end @@ -124,114 +124,223 @@ function actor_noun(msg) return msg end -function plural_actor(msg) +function plural_actor(msg, msg_id) if msg then - msg = msg - :gsub('${actor} hits ', '${actor} hit ') - :gsub('${actor} casts ', '${actor} cast ') - :gsub('${actor} starts ', '${actor} start ') - :gsub('${actor} defeats ', '${actor} defeat ') - :gsub('${actor} gains ', '${actor} gain ') - :gsub('${actor} attains ', '${actor} attain ') - :gsub('${actor} loses ', '${actor} lose ') - :gsub('${actor} falls ', '${actor} fall ') - :gsub("${actor}'s ", "${actor}' ") - :gsub('${actor} misses ' , '${actor} miss ') - :gsub('${actor} calls ' , '${actor} call ') - :gsub('${actor} learns ' , '${actor} learn ') - :gsub('${actor} uses ' , '${actor} use ') - :gsub('${actor} is ' , '${actor} are ') - :gsub('${actor} takes ' , '${actor} take ') - :gsub('${actor} does ' , '${actor} do ') - :gsub('${actor} lacks ' , '${actor} lack ') - :gsub('${actor} redies ' , '${actor} ready ') - :gsub('${actor} earns ' , '${actor} earn ') - :gsub('${actor} scores ' , '${actor} score ') - :gsub('${actor} successfully removes ' , '${actor} successfully remove ') - :gsub('${actor} achieves ' , '${actor} achieve ') - :gsub('${actor} mugs ' , '${actor} mug ') - :gsub('${actor} steals ' , '${actor} steal ') - :gsub('${actor} fails ' , '${actor} fail ') - :gsub(' but finds nothing' , ' but find nothing') - :gsub(' and finds ${item}' , ' and find ${item}') - :gsub('${actor} recovers ' , '${actor} recover ') - :gsub('${ability}, but misses' , '${ability}, but miss') - :gsub(' but misses ${target}' , ' but miss ${target}') - :gsub('${actor} covers ' , '${actor} cover ') - :gsub('${actor} already has ' , '${actor} already have ') - :gsub('${actor} attempts ' , '${actor} attempt ') - :gsub(' but lacks ' , ' but lack ') - :gsub('${actor} destroys ' , '${actor} destroy ') - :gsub('${actor} absorbs ' , '${actor} absorb ') - :gsub('${actor} eats ' , '${actor} eat ') - :gsub('${actor} leads ' , '${actor} lead ') - :gsub('${actor} has ' , '${actor} have ') - :gsub('${actor} obtains ' , '${actor} obtain ') - :gsub(' and finds ${number}' , ' and find ${number}') + 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) +function plural_target(msg, msg_id) if msg then - msg = msg - :gsub('${target} takes ', '${target} take ') - :gsub('${target} is ', '${target} are ') - :gsub('${target} recovers ', '${target} recover ') - :gsub("${target}'s ", targets_condensed and '${target} ' or "${target}' ") - :gsub('${target} falls ', '${target} fall ') - :gsub('${target} uses ', '${target} use ') - :gsub('${target} resists', '${target} resist') - :gsub('${target} vanishes', '${target} vanish') - :gsub('${target} receives ', '${target} receive ') - :gsub('${target} seems ${skill}', '${target} seem ${skill}') - :gsub('${lb}It seems to have ', '${lb}They seem to have ') - :gsub('${target} gains ', '${target} gain ') - :gsub('${target} evades', '${target} evade') - :gsub('${target} regains ', '${target} regain ') - :gsub('${target} narrowly escapes ', '${target} narrowly escape ') - :gsub('${target} obtains ', '${target} obtain ') - :gsub('${target} learns ', '${target} learn ') - :gsub('${target} loses ', '${target} lose ') - :gsub('${target} was ', '${target} were ') - :gsub('${target} has ', '${target} have ') - :gsub('${target} completely resists ', '${target} completely resist ') - :gsub('${target} now has ', '${target} now have ') - :gsub('${target} feels ', '${target} feel ') - :gsub('${target} stands ', '${target} stand ') + 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) +function clean_msg(msg, msg_id) if msg then msg = msg :gsub(' The ', ' the ') - 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) +function grammatical_number_fix(msg, number, msg_id) if msg then if number == 1 then - msg = msg - :gsub(' points', ' point') - :gsub('${number} Ballista Points', '${number} Ballista Point') - :gsub('healed of ${number} status ailments', 'healed of ${number} status ailment') - :gsub('magical effects from', 'magical effect from') + 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 - msg = msg - :gsub(' absorbs', ' absorb') - :gsub(' Petra', ' Petras') - :gsub('disappears', 'disappear') - :gsub('attributes is', 'attributes are') - :gsub('status effect is', 'status effects are') - :gsub('piece', 'pieces') - :gsub('Finishing move now ', 'Finishing moves now ') + 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 diff --git a/addons/battlemod/parse_action_packet.lua b/addons/battlemod/parse_action_packet.lua index 8261adac3c..89c21c22f3 100644 --- a/addons/battlemod/parse_action_packet.lua +++ b/addons/battlemod/parse_action_packet.lua @@ -278,10 +278,6 @@ function parse_action_packet(act) end end - if col == 'D' or grammar_numb_msg:contains(m.message) then - msg = grammatical_number_fix(msg, (m.cparam or m.param)) - end - local count = '' if m.message == 377 and act.actor_id == Self.id then parse_quantity = true @@ -290,6 +286,9 @@ function parse_action_packet(act) 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 @@ -297,30 +296,30 @@ function parse_action_packet(act) msg = actor_noun(msg) end if plural_entities:contains(act.actor.id) then - msg = plural_actor(msg) + msg = plural_actor(msg, m.message) end if targets_condensed or plural_entities:contains(v.target[1].id) then - msg = plural_target(msg) + msg = plural_target(msg, m.message) end end 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 S{1,3,4,6,11,13,14,15}:contains(act.category) and (bit.band(m.unknown,1)==1 and "Cover! " or "") - ..(bit.band(m.unknown,4)==4 and "Magic Burst! " or "") --Used on Swipe/Lunge MB - ..(bit.band(m.unknown,8)==8 and "Immunobreak! " or "") --Unused? Displayed directly on message - ..(bit.band(m.unknown,16)==16 and "Critical Hit! " or "") --Unused? Crits have their own message - ..(reaction_lookup == 4 and "Blocked! " or "") - ..(reaction_lookup == 2 and "Guarded! " or "") - ..(reaction_lookup == 3 and S{3,4,6,11,13,14,15}:contains(act.category) and "Parried! " or "") or "" --Unused? They are send the same as missed - local prefix2 = has_line_break and S{1,3,4,6,11,13,14,15}:contains(act.category) and (bit.band(m.unknown,1)==1 and "Cover! " or "") - ..(bit.band(m.unknown,2)==2 and "Resist! " or "") - ..(bit.band(m.unknown,4)==4 and "Magic Burst! " or "") --Used on Swipe/Lunge MB - ..(bit.band(m.unknown,8)==8 and "Immunobreak! " or "") --Unused? Displayed directly on message - ..(bit.band(m.unknown,16)==16 and "Critical Hit! " or "") --Unused? Crits have their own message - ..(reaction_lookup == 4 and "Blocked! " or "") - ..(reaction_lookup == 2 and "Guarded! " or "") - ..(reaction_lookup == 3 and S{3,4,6,11,13,14,15}:contains(act.category) and "Parried! " or "") or "" --Unused? They are send the same as missed + local prefix = (not has_line_break or simplify) and S{1,3,4,6,11,13,14,15}:contains(act.category) and (bit.band(m.unknown,1)==1 and 'Cover! ' or '') + ..(bit.band(m.unknown,4)==4 and 'Magic Burst! ' or '') --Used on Swipe/Lunge MB + ..(bit.band(m.unknown,8)==8 and 'Immunobreak! ' or '') --Unused? Displayed directly on message + ..(bit.band(m.unknown,16)==16 and 'Critical Hit! ' or '') --Unused? Crits have their own message + ..(reaction_lookup == 4 and 'Blocked! ' or '') + ..(reaction_lookup == 2 and 'Guarded! ' or '') + ..(reaction_lookup == 3 and S{3,4,6,11,13,14,15}:contains(act.category) and 'Parried! ' or '') or '' --Unused? They are send the same as missed + local prefix2 = has_line_break and S{1,3,4,6,11,13,14,15}:contains(act.category) and (bit.band(m.unknown,1)==1 and 'Cover! ' or '') + ..(bit.band(m.unknown,2)==2 and 'Resist! ' or '') + ..(bit.band(m.unknown,4)==4 and 'Magic Burst! ' or '') --Used on Swipe/Lunge MB + ..(bit.band(m.unknown,8)==8 and 'Immunobreak! ' or '') --Unused? Displayed directly on message + ..(bit.band(m.unknown,16)==16 and 'Critical Hit! ' or '') --Unused? Crits have their own message + ..(reaction_lookup == 4 and 'Blocked! ' or '') + ..(reaction_lookup == 2 and 'Guarded! ' or '') + ..(reaction_lookup == 3 and S{3,4,6,11,13,14,15}:contains(act.category) and 'Parried! ' or '') or '' --Unused? They are send the same as missed 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)) @@ -336,7 +335,7 @@ function parse_action_packet(act) :gsub('${lb}','\7'..prefix2) :gsub('${number}',act.action.number or m.param) :gsub('${status}',m.status or 'ERROR 120') - :gsub('${gil}',m.param..' gil'))) + :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 @@ -361,14 +360,17 @@ function parse_action_packet(act) 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) + 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) + 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 @@ -388,7 +390,7 @@ function parse_action_packet(act) :gsub('${target}',targ) :gsub('${lb}','\7') :gsub('${number}',m.add_effect_param) - :gsub('${status}',m.add_effect_status or 'ERROR 178')))) + :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 @@ -419,14 +421,17 @@ function parse_action_packet(act) 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) + 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) + 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 @@ -443,7 +448,7 @@ function parse_action_packet(act) :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')))) + :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 @@ -555,9 +560,9 @@ function simplify_message(msg_ID) msg = line_noability elseif line_notarget and fields.actor and fields.number then if msg_ID == 798 then --Maneuver message - msg = line_notarget.."%" + msg = line_notarget..'%' elseif msg_ID == 799 then --Maneuver message with overload - msg = line_notarget.."% (${actor} overloaded)" + msg = line_notarget..'% (${actor} overloaded)' else msg = line_notarget end @@ -862,37 +867,37 @@ function color_filt(col,is_me) --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 col == 'D' then -- Damage if is_me then return 28 else return 20 end - elseif col == "M" then -- Misses + elseif col == 'M' then -- Misses if is_me then return 29 else return 21 end - elseif col == "H" then -- Healing + elseif col == 'H' then -- Healing if is_me then return 30 else return 22 end - elseif col == "B" then -- Beneficial effects + 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) + 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 + elseif col == 'R' then -- Resists if is_me then return 59 else diff --git a/addons/battlemod/statics.lua b/addons/battlemod/statics.lua index 4c64889b2d..17021d9b0d 100644 --- a/addons/battlemod/statics.lua +++ b/addons/battlemod/statics.lua @@ -44,6 +44,61 @@ 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}, + } +} + domain_buffs = S{ 250, -- EF Badge 257, -- Besieged From 97fb5a47e3e9f4e03907b7312c4b477af0783717 Mon Sep 17 00:00:00 2001 From: Ian Anderson Date: Sat, 17 Apr 2021 21:50:28 -0700 Subject: [PATCH 0607/1002] Update addons.xml --- addons/addons.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/addons/addons.xml b/addons/addons.xml index b7ba191326..903c7f5e35 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -648,6 +648,13 @@ https://github.com/Windower/Lua/issues https://discord.gg/b275nMv
    + + Stubborn + Arico + An addon to block accidental calls for help. + https://github.com/ianandersonlol/stubborn/issues + https://discord.gg/b275nMv + subTarget Sebyg666 From 6f9a66d9c2c66af658de03bc8342544c4a1bcd24 Mon Sep 17 00:00:00 2001 From: Ian Anderson Date: Sat, 17 Apr 2021 21:51:14 -0700 Subject: [PATCH 0608/1002] Add files via upload --- addons/Stubborn/Stubborn.lua | 57 ++++++++++++++++++++++++++++++++++++ addons/Stubborn/readme.md | 7 +++++ 2 files changed, 64 insertions(+) create mode 100644 addons/Stubborn/Stubborn.lua create mode 100644 addons/Stubborn/readme.md diff --git a/addons/Stubborn/Stubborn.lua b/addons/Stubborn/Stubborn.lua new file mode 100644 index 0000000000..8363c6efca --- /dev/null +++ b/addons/Stubborn/Stubborn.lua @@ -0,0 +1,57 @@ +--[[Copyright © 2021, Arico +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 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 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.name = 'Stubborn' +_addon.author = 'Arico' +_addon.version = '1' +_addon.command = 'stubborn' + +require('pack') +require('strings') +require('logger') +packets = require('packets') + + +windower.register_event('outgoing chunk', function(id, original, modified, injected, blocked) + if id == 0x01a then + local p = packets.parse('outgoing', original) + if p['Category'] == 5 and not injected then + log('You are too stubborn to call for help! Use //stubborn to call for help.') + return true + end + end +end) + +windower.register_event('addon command', function(...) + local target = windower.ffxi.get_mob_by_target("t") + if target and target.claim_id ~= 0 then + local p = packets.new('outgoing', 0x1a, { + ['Target'] = target['id'], + ['Target Index'] = target['index'], + ['Category'] = 5,}) + packets.inject(p) + end +end) \ No newline at end of file diff --git a/addons/Stubborn/readme.md b/addons/Stubborn/readme.md new file mode 100644 index 0000000000..0efb35447b --- /dev/null +++ b/addons/Stubborn/readme.md @@ -0,0 +1,7 @@ +# Stubborn +A Windower 4 addon to prevent unnecessary "Call for help!" + +Stubborn is a light weight replacement to the old CFHProtect addon. + + +If you need to call for help. Type //stubborn From 47300e29d4aa9dd21a151793928871d32b0c5cc1 Mon Sep 17 00:00:00 2001 From: Ian Anderson Date: Sun, 18 Apr 2021 10:09:44 -0700 Subject: [PATCH 0609/1002] Update addons.xml --- addons/addons.xml | 114 +++++++++++++++++++++++----------------------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/addons/addons.xml b/addons/addons.xml index 903c7f5e35..d5ed626e24 100644 --- a/addons/addons.xml +++ b/addons/addons.xml @@ -15,7 +15,7 @@ AEcho Automatically uses echo drops when you get silenced. Also, uses send to send a message to an alt that you got debuffed. Nitrous (Shiva) - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk https://github.com/nitrous24/Lua/issues @@ -30,13 +30,13 @@ Byrth Stores tells that you receive for later recall. https://github.com/Byrth/Lua-Byrth/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk AutoControl Automated automaton equipment setting and burden tracker. Nitrous (Shiva) - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk https://github.com/nitrous24/Lua/issues @@ -44,7 +44,7 @@ Chiaia Automatically hits the enter key twice when first starting so you don't timeout on the warning message. https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk autoinvite @@ -58,7 +58,7 @@ Arcon Automatically joins or declines party invites. Configurable with blacklist/whitelist mode and auto-decline settings. https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk AutoRA @@ -70,7 +70,7 @@ AzureSets Automated blue magic spell setting. Nitrous (Shiva) - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk https://github.com/nitrous24/Lua/issues @@ -85,14 +85,14 @@ Byrth Customizes battle chat messages. https://github.com/Byrth/Lua-Byrth/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk BattleStations Sjshovan (Apogee) Change or remove the default battle music. https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk Blist @@ -120,13 +120,13 @@ Byrth Mimics the cancel plugin, but also accepts buff names instead of just IDs. https://github.com/Byrth/Lua-Byrth/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk cBlock Blacklist addon for FFOChat. Nitrous (Shiva) - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk https://github.com/nitrous24/Lua/issues @@ -148,7 +148,7 @@ Arcon Allows opening links posted into the FFXI chat. https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk ChatPorter @@ -162,14 +162,14 @@ Arcon Displays an on-screen clock in a custom format with options to display several different time zones. https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk ConsoleBG Arcon Displays a dark (by default) background behind the Windower console to make it more readable. https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk digger @@ -183,14 +183,14 @@ Chiaia Helps warp you to Reisenjima using (Dim) Rings. https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk Distance Arcon Shows the distance to your current target. https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk DistancePlus @@ -204,7 +204,7 @@ Cair Emulates BlinkMeNot functionality. Allows for customization of gear display for you or anyone else. https://github.com/cairface/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk DynamisHelper @@ -238,28 +238,28 @@ Tako, Rubenator Displays current equipment grid on screen. Also can show current Ammo count and current Encumbrance. https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk eval Aureus Allows developers to run arbitrary lua code in the console. https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk FastCS Cair Dramatically speeds up cutscenes by disabling the frame rate cap. Requires the config plugin. https://github.com/cairface/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk FFOColor Nitrous (Shiva) Allows you to show FFOChat text in one of the 5 game chat channels. As well as specify colors for the text https://github.com/nitrous24/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk findAll @@ -293,7 +293,7 @@ Byrth Enables instant linkshell chat after zoning. https://github.com/Byrth/Lua-Byrth/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk InfoBar @@ -307,7 +307,7 @@ Cair Replaces outgoing text prefixed by % with respective game information. https://github.com/cairface/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk Itemizer @@ -335,14 +335,14 @@ Arcon Allows opening links to certain websites from within the game, with an optional search parameter. https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk Logger Arcon Logs the chat log to a file. https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk Lookup @@ -356,26 +356,26 @@ Arcon Automatically passes an item on all accounts if lotted by another. https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk MacroChanger Banggugyangu Automatically switches Macro Book and Page according to job changes. https://github.com/banggugyangu/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk MobCompass A compass to show your position relative to the target (not players) for geo and has a setup for Sneak attack - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk MountMuzzle Sjshovan (Apogee) Change or remove the default mount music. https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk MountRoulette @@ -395,7 +395,7 @@ Nostrum Creates a click-able on-screen macro to help avoid targeting problems while curing. trv - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk https://github.com/trv6/Lua/issues @@ -403,12 +403,12 @@ Glarin of Asura Tracks and displays the Current Floor, Time Remaining, Objective, Floors Completed, Reward Rate, and Potenial Tokens. https://github.com/GlarinAsura/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk obiaway Automatically collect and remove elemental obi based on day/weather/storm conditions. - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk Omen @@ -421,14 +421,14 @@ OhShi Keeps track of various event related things. Such as, VW proc messages, mob casting, mob tp moves, TH procs and cor rolls, as well as others. Nitrous (Shiva) - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk https://github.com/nitrous24/Lua/issues Organizer A multi-purpose inventory management solution. Similar to GearCollector. Byrth, Rooks - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk https://github.com/Byrth/Lua-Byrth/issues @@ -436,21 +436,21 @@ Byrth Temporary addon that fixes a null pointer animation error with pets that is causing crashes. https://github.com/Byrth/Lua-Byrth/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk PetSchool Banggugyangu A helper addon for PUPs using spellcast, it informs spellcast of pet casting (healing or nuking). https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk PetTP SnickySnacks Tracks pet vitals (HP/TP/MP) https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk plasmon @@ -464,14 +464,14 @@ Byrth Allows you to specify which plugins and addons will be used with which characters. https://github.com/Byrth/Lua-Byrth/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk PointWatch Byrth Allows you to monitor your XP/CP gains and keep track of the Dynamis time limit. https://github.com/Byrth/Lua-Byrth/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk porter @@ -506,20 +506,20 @@ Byrth Should request spawn packets for players / mobile NPCs that failed to spawn. https://github.com/Byrth/Lua-Byrth/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk Respond Byrth Respond to tells and FFOchat PMs using //r. https://github.com/Byrth/Lua-Byrth/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk Rhombus Creates a highly customizable, click-able, on-screen menu. trv - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk https://github.com/trv6/Lua/issues @@ -527,7 +527,7 @@ Cair Lets you save your Records of Eminence objectives to profiles for easily swapping out objectives. https://github.com/cairface/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk RollTracker @@ -548,14 +548,14 @@ Banggugyangu Informs Spellcast about changes to Sneak Attack and Trick Attack status. https://github.com/banggugyangu/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk Scoreboard Suji Basic in-game damage parser. It displays live DPS and works even when chat filters are enabled. https://github.com/jerryhebert/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk setbgm @@ -569,7 +569,7 @@ Byrth Applys spellcast-like command completion (interpretation and target completion) to commands. Includes emotes, /check, and /pcmd. https://github.com/Byrth/Lua-Byrth/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk Silence @@ -590,14 +590,14 @@ Byrth Sends commands between windower instances using IPC. https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk SetTarget Arcon Sets the target to a given ID. https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk SpeedChecker @@ -646,14 +646,14 @@ Ihm A simple helper addon for Spellcast for Scholar Stratagems. It will automatically calculate the number of stratagems you have and push them into spellcast variables. https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk Stubborn Arico An addon to block accidental calls for help. https://github.com/ianandersonlol/stubborn/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk subTarget @@ -667,21 +667,21 @@ Arcon Displays information about your current target in memory. https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk Text Arcon Allows creating and manipulating on-screen text objects through Windower commands. https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk Treasury Arcon Lots or passes items based on configurable lists, drops unwanted items from the inventory and automatically stacks items when they drop. https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk thtracker @@ -702,14 +702,14 @@ Arcon Shows a target's HP percentage next to their health bar as well as party/alliance members's TP. https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk translate Byrth Gives a rough JP->EN translation using the resources and custom dictionaries. https://github.com/Byrth/Lua-Byrth/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk TreasurePool @@ -723,7 +723,7 @@ Arcon Updates and reloads all plugins and addons when typing //update. https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk VisibleFavor @@ -751,7 +751,7 @@ Arcon A file-based macro engine https://github.com/Windower/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk zonetimer @@ -814,7 +814,7 @@ Auk Tracks and displays debuffs on your current target. https://github.com/aukon/Lua/issues - https://discord.gg/b275nMv + https://discord.gg/aUrHCvk Tab From 21ad3ea2f98e2a33e5ea2dc2f425b5b56a18ecbc Mon Sep 17 00:00:00 2001 From: Ian Anderson Date: Sun, 18 Apr 2021 10:11:10 -0700 Subject: [PATCH 0610/1002] Update Stubborn.lua --- addons/Stubborn/Stubborn.lua | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/addons/Stubborn/Stubborn.lua b/addons/Stubborn/Stubborn.lua index 8363c6efca..f327c8f2ea 100644 --- a/addons/Stubborn/Stubborn.lua +++ b/addons/Stubborn/Stubborn.lua @@ -9,49 +9,46 @@ modification, are permitted provided that the following conditions are met: * 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 nor the + * Neither the name of Stubborn 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 BE LIABLE FOR ANY +DISCLAIMED. IN NO EVENT SHALL Arico 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. --]] - + b275nMv _addon.name = 'Stubborn' _addon.author = 'Arico' _addon.version = '1' _addon.command = 'stubborn' -require('pack') -require('strings') require('logger') packets = require('packets') - windower.register_event('outgoing chunk', function(id, original, modified, injected, blocked) - if id == 0x01a then + if id == 0x01A and not injected then local p = packets.parse('outgoing', original) - if p['Category'] == 5 and not injected then - log('You are too stubborn to call for help! Use //stubborn to call for help.') + if p['Category'] == 5 then return true end end end) windower.register_event('addon command', function(...) - local target = windower.ffxi.get_mob_by_target("t") + local target = windower.ffxi.get_mob_by_target('t') if target and target.claim_id ~= 0 then - local p = packets.new('outgoing', 0x1a, { - ['Target'] = target['id'], - ['Target Index'] = target['index'], - ['Category'] = 5,}) + local p = packets.new('outgoing', 0x01A, { + ['Target'] = target['id'], + ['Target Index'] = target['index'], + ['Category'] = 5, + }) packets.inject(p) end -end) \ No newline at end of file +end) From 0b78aeba70cf035d6a4c2831b48d2b1e01e34ec1 Mon Sep 17 00:00:00 2001 From: Ian Anderson Date: Sun, 18 Apr 2021 10:28:48 -0700 Subject: [PATCH 0611/1002] Update Stubborn.lua --- addons/Stubborn/Stubborn.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/Stubborn/Stubborn.lua b/addons/Stubborn/Stubborn.lua index f327c8f2ea..0d13cea087 100644 --- a/addons/Stubborn/Stubborn.lua +++ b/addons/Stubborn/Stubborn.lua @@ -23,7 +23,7 @@ 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. --]] - b275nMv + _addon.name = 'Stubborn' _addon.author = 'Arico' _addon.version = '1' From 3c03b0f32844f71380a836862118d34204cee95b Mon Sep 17 00:00:00 2001 From: Ian Anderson Date: Sun, 18 Apr 2021 10:29:05 -0700 Subject: [PATCH 0612/1002] Update readme.md --- addons/Stubborn/readme.md | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/Stubborn/readme.md b/addons/Stubborn/readme.md index 0efb35447b..904d26fb95 100644 --- a/addons/Stubborn/readme.md +++ b/addons/Stubborn/readme.md @@ -3,5 +3,4 @@ A Windower 4 addon to prevent unnecessary "Call for help!" Stubborn is a light weight replacement to the old CFHProtect addon. - If you need to call for help. Type //stubborn From dc7474d18a2ef8e73394a23dfc8441832b042333 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Tue, 20 Apr 2021 23:01:58 +0100 Subject: [PATCH 0613/1002] Update refresh.lua --- addons/GearSwap/refresh.lua | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/addons/GearSwap/refresh.lua b/addons/GearSwap/refresh.lua index 22de974f95..2bd0135211 100644 --- a/addons/GearSwap/refresh.lua +++ b/addons/GearSwap/refresh.lua @@ -79,7 +79,7 @@ function load_user_files(job_id,user_file) end current_file = nil - gearswap_disabled = true + -- gearswap_disabled = true sets = nil user_env = nil unhandled_command_events = {} @@ -108,7 +108,7 @@ function load_user_files(job_id,user_file) if not path then current_file = nil - gearswap_disabled = true + -- gearswap_disabled = true sets = nil return end @@ -151,16 +151,16 @@ function load_user_files(job_id,user_file) user_env['_G'] = user_env -- Try to load data/_
    .lua - local funct, err = loadfile(path) + local funct, err = path and loadfile(path) or function() end -- If the file cannot be loaded, print the error and load the default. - if funct == nil then + if err then print('User file problem: '..err) current_file = nil - gearswap_disabled = true + -- gearswap_disabled = true sets = nil return - else + elseif filename then current_file = filename print('GearSwap: Loaded your '..current_file..' file!') end @@ -172,7 +172,7 @@ function load_user_files(job_id,user_file) if not status then error('GearSwap: File failed to load: \n'..plugin) - gearswap_disabled = true + -- gearswap_disabled = true sets = nil return nil end From f91eb07f652faea65a8ea397783e27b222be63a3 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Tue, 20 Apr 2021 23:16:48 +0100 Subject: [PATCH 0614/1002] Update refresh.lua Reverting some changes from previous commit that were unnecessary. --- addons/GearSwap/refresh.lua | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/addons/GearSwap/refresh.lua b/addons/GearSwap/refresh.lua index 2bd0135211..9fb5e95607 100644 --- a/addons/GearSwap/refresh.lua +++ b/addons/GearSwap/refresh.lua @@ -79,7 +79,6 @@ function load_user_files(job_id,user_file) end current_file = nil - -- gearswap_disabled = true sets = nil user_env = nil unhandled_command_events = {} @@ -108,7 +107,6 @@ function load_user_files(job_id,user_file) if not path then current_file = nil - -- gearswap_disabled = true sets = nil return end @@ -151,16 +149,15 @@ function load_user_files(job_id,user_file) user_env['_G'] = user_env -- Try to load data/_
    .lua - local funct, err = path and loadfile(path) or function() end + local funct, err = loadfile(path) -- If the file cannot be loaded, print the error and load the default. - if err then + if funct == nil then print('User file problem: '..err) current_file = nil - -- gearswap_disabled = true sets = nil return - elseif filename then + else current_file = filename print('GearSwap: Loaded your '..current_file..' file!') end @@ -172,7 +169,6 @@ function load_user_files(job_id,user_file) if not status then error('GearSwap: File failed to load: \n'..plugin) - -- gearswap_disabled = true sets = nil return nil end From c0903587ab35de2b7798c09d90ff0bab517760cf Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Tue, 20 Apr 2021 23:37:59 +0100 Subject: [PATCH 0615/1002] Update statics.lua --- addons/GearSwap/statics.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/GearSwap/statics.lua b/addons/GearSwap/statics.lua index 257058929d..b32e6c982c 100644 --- a/addons/GearSwap/statics.lua +++ b/addons/GearSwap/statics.lua @@ -198,7 +198,7 @@ slot_map.back = 15 -gearswap_disabled = true +gearswap_disabled = false seen_0x063_type9 = false delay_0x063_v9 = false not_sent_out_equip = {} From 3f07f71cda5e75bebefdb5aa04c52962c6d0ac99 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Tue, 20 Apr 2021 23:38:48 +0100 Subject: [PATCH 0616/1002] Update gearswap.lua --- addons/GearSwap/gearswap.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/GearSwap/gearswap.lua b/addons/GearSwap/gearswap.lua index c0ec11c9a4..6e2ee0063d 100644 --- a/addons/GearSwap/gearswap.lua +++ b/addons/GearSwap/gearswap.lua @@ -130,7 +130,6 @@ require 'flow' require 'triggers' initialize_packet_parsing() -gearswap_disabled = false windower.register_event('load',function() windower.debug('load') From e5f19ed2138b0d57e8516219c0e3793de2074049 Mon Sep 17 00:00:00 2001 From: Ian Anderson Date: Wed, 5 May 2021 16:15:20 -0700 Subject: [PATCH 0617/1002] Update Stubborn.lua --- addons/Stubborn/Stubborn.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/Stubborn/Stubborn.lua b/addons/Stubborn/Stubborn.lua index 0d13cea087..a9afce66cd 100644 --- a/addons/Stubborn/Stubborn.lua +++ b/addons/Stubborn/Stubborn.lua @@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --]] _addon.name = 'Stubborn' _addon.author = 'Arico' _addon.version = '1' -_addon.command = 'stubborn' +_addon.command = {'stubborn','cfh'} require('logger') packets = require('packets') From 8bd4324bec7bd069f5953a68aea2d611ce12536f Mon Sep 17 00:00:00 2001 From: Ian Anderson Date: Wed, 12 May 2021 04:58:21 -0700 Subject: [PATCH 0618/1002] Update readme.md --- addons/Stubborn/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/Stubborn/readme.md b/addons/Stubborn/readme.md index 904d26fb95..1ca7d48458 100644 --- a/addons/Stubborn/readme.md +++ b/addons/Stubborn/readme.md @@ -3,4 +3,4 @@ A Windower 4 addon to prevent unnecessary "Call for help!" Stubborn is a light weight replacement to the old CFHProtect addon. -If you need to call for help. Type //stubborn +If you need to call for help. Type //stubborn or //cfh. From 331e0c3049ec441921e0a863e1e6952007427947 Mon Sep 17 00:00:00 2001 From: John Arnfield Date: Wed, 12 May 2021 21:26:59 +0100 Subject: [PATCH 0619/1002] Add support for Gaol in JobChange --- addons/JobChange/jobchange.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/JobChange/jobchange.lua b/addons/JobChange/jobchange.lua index 7b8d41930e..e5068ba14b 100644 --- a/addons/JobChange/jobchange.lua +++ b/addons/JobChange/jobchange.lua @@ -41,8 +41,8 @@ packets = require('packets') res = require ('resources') local temp_jobs = T { 'NIN', 'DNC', 'WAR', 'MNK', 'WHM', 'BLM', 'RDM', 'THF' } -local mog_zones = S { 'Selbina', 'Mhaura', 'Tavnazian Safehold', 'Nashmau', 'Rabao', 'Kazham', 'Norg'} -local moogles = S { 'Moogle', 'Nomad Moogle', 'Green Thumb Moogle' } +local mog_zones = S { 'Selbina', 'Mhaura', 'Tavnazian Safehold', 'Nashmau', 'Rabao', 'Kazham', 'Norg', 'Walk of Echoes [P1]', 'Walk of Echoes [P2]' } +local moogles = S { 'Moogle', 'Nomad Moogle', 'Green Thumb Moogle', 'Pilgrim Moogle' } local log = function(msg) windower.add_to_chat(4,'JobChange: '..msg) From 55b8f9851bd7bc40228733c3e5e1ea1fd4493b95 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 16 May 2021 22:22:42 +0100 Subject: [PATCH 0620/1002] Make organizer work nearby Nomad/Pilgrim Moogles --- addons/organizer/items.lua | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/addons/organizer/items.lua b/addons/organizer/items.lua index b64a264455..6dcff6462a 100644 --- a/addons/organizer/items.lua +++ b/addons/organizer/items.lua @@ -30,9 +30,21 @@ local bags = {} local item_tab = {} local function validate_bag(bag_table) - if (bag_table.access == 'Everywhere' or (bag_table.access == 'Mog House' and windower.ffxi.get_info().mog_house)) and - windower.ffxi.get_bag_info(bag_table.id) then - return true + if type(bag_table) == 'table' and windower.ffxi.get_bag_info(bag_table.id) then + if bag_table.access == 'Everywhere' then + return true + elseif bag_table.access == 'Mog House' then + if windower.ffxi.get_info().mog_house then + return true + end + + for i = 0, 0x3FF do + local t = windower.ffxi.get_mob_by_index(i) + if t and (t.name == 'Nomad Moogle' or t.name == 'Pilgrim Moogle') and t.valid_target and t.distance < 36 then + return true + end + end + end end return false end From b1056430d5218a8e171adad0e29f414785f82620 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 16 May 2021 22:46:22 +0100 Subject: [PATCH 0621/1002] Update items.lua Storage is not available at Nomad/Pilgrim Moogles. --- addons/organizer/items.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/organizer/items.lua b/addons/organizer/items.lua index 6dcff6462a..2d4ed9af7e 100644 --- a/addons/organizer/items.lua +++ b/addons/organizer/items.lua @@ -36,6 +36,8 @@ local function validate_bag(bag_table) elseif bag_table.access == 'Mog House' then if windower.ffxi.get_info().mog_house then return true + elseif bag_table.english == 'Storage' then -- Storage is never available at Nomad/Pilgrim Moogles + return false end for i = 0, 0x3FF do From 6c8b61f81da307aa2ef89d0ca4bd9489563b6b8e Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Tue, 18 May 2021 22:02:22 +0100 Subject: [PATCH 0622/1002] Implemented new functions --- addons/organizer/items.lua | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/addons/organizer/items.lua b/addons/organizer/items.lua index 2d4ed9af7e..c530e56980 100644 --- a/addons/organizer/items.lua +++ b/addons/organizer/items.lua @@ -36,16 +36,20 @@ local function validate_bag(bag_table) elseif bag_table.access == 'Mog House' then if windower.ffxi.get_info().mog_house then return true - elseif bag_table.english == 'Storage' then -- Storage is never available at Nomad/Pilgrim Moogles + elseif bag_table.english == 'Storage' then -- Storage is not available at Nomad Moogles return false end - - for i = 0, 0x3FF do - local t = windower.ffxi.get_mob_by_index(i) - if t and (t.name == 'Nomad Moogle' or t.name == 'Pilgrim Moogle') and t.valid_target and t.distance < 36 then - return true + + local m = {'Nomad Moogle', 'Pilgrim Moogle'} + for _, name in pairs(m) do + for index, _ in pairs(windower.ffxi.get_mob_list(name)) do + local t = windower.ffxi.get_mob_by_index(index) + if t and t.valid_target and t.distance < 36 then + return true + end end end + end end return false From d85fff07882b0adcc6ddab5bb8df2a5ee000278a Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Tue, 18 May 2021 15:45:21 -0600 Subject: [PATCH 0623/1002] windower.ffxi_path game_path changes --- addons/equipviewer/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/addons/equipviewer/README.md b/addons/equipviewer/README.md index cd17da9c15..c528c70563 100644 --- a/addons/equipviewer/README.md +++ b/addons/equipviewer/README.md @@ -22,8 +22,10 @@ 9. hideonzone: toggles hiding while crossing zone lines (default is on/true) 10. hideoncutscene: toggles hiding when in cutscene/npc menu/etc (default is on/true) 11. justify: toggles between ammo text being right or left justifed (default is right justified) -12. game_path : sets path to FFXI folder where you want dats extracted from. Defaults to the "Final Fantasy XI" folder next to the folder containing the launcher (ussually POL.exe). -13. help: displays explanations of each command +12. help: displays explanations of each command + +Legacy Command: +game_path : sets path to FFXI folder where you want dats extracted from. Backslashes `\` must be escaped (like so: `\\`) or use forewardslash `/` instead. (legacy command as of `3.3.1` in which the game path is now pulled from the registry, but this command is still here in case you want to pull from dats that exist elsewhere) ### Example Commands ``` From 8834cef3981ea92c09950eb306f82ac3bd068708 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Fri, 21 May 2021 22:39:12 +0100 Subject: [PATCH 0624/1002] Check for bag availableness. Fixed an issue where Myhome would try to use rings from inside Wardrobe 3 & 4 when these were not available. --- addons/MyHome/MyHome.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/MyHome/MyHome.lua b/addons/MyHome/MyHome.lua index 5116cc3432..c6a0a29566 100644 --- a/addons/MyHome/MyHome.lua +++ b/addons/MyHome/MyHome.lua @@ -54,7 +54,7 @@ function search_item() for index,stats in pairs(item_info) do local item = item_array[stats.id] local set_equip = windower.ffxi.set_equip - if item then + if item and windower.ffxi.get_bag_info(item.bag).enabled then local ext = extdata.decode(item) local enchant = ext.type == 'Enchanted Equipment' local recast = enchant and ext.charges_remaining > 0 and math.max(ext.next_use_time+18000-os.time(),0) From 67125b9b24566ab458f905766845aead3436170a Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Fri, 21 May 2021 22:40:52 +0100 Subject: [PATCH 0625/1002] Update Dimmer.lua --- addons/Dimmer/Dimmer.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/Dimmer/Dimmer.lua b/addons/Dimmer/Dimmer.lua index c8f577d530..6a7aa81f98 100644 --- a/addons/Dimmer/Dimmer.lua +++ b/addons/Dimmer/Dimmer.lua @@ -56,7 +56,7 @@ function search_item() for index,stats in pairs(item_info) do local item = item_array[stats.id] local set_equip = windower.ffxi.set_equip - if item then + if item and windower.ffxi.get_bag_info(item.bag).enabled then local ext = extdata.decode(item) local enchant = ext.type == 'Enchanted Equipment' local recast = enchant and ext.charges_remaining > 0 and math.max(ext.next_use_time+18000-os.time(),0) From b92307f39771852bb869de507920f561a0ca8fb0 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Fri, 21 May 2021 22:50:06 +0100 Subject: [PATCH 0626/1002] Version bump --- addons/MyHome/MyHome.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/MyHome/MyHome.lua b/addons/MyHome/MyHome.lua index c6a0a29566..05098e0520 100644 --- a/addons/MyHome/MyHome.lua +++ b/addons/MyHome/MyHome.lua @@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.]] _addon.name = 'MyHome' _addon.author = 'from20020516' -_addon.version = '1.1' +_addon.version = '1.1.1' _addon.commands = {'myhome','mh','warp'} require('logger') From adea556e55e3772718bdf6baf0ecdbc0bc40c165 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Fri, 21 May 2021 22:50:29 +0100 Subject: [PATCH 0627/1002] Version bump --- addons/Dimmer/Dimmer.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/Dimmer/Dimmer.lua b/addons/Dimmer/Dimmer.lua index 6a7aa81f98..d93d765c74 100644 --- a/addons/Dimmer/Dimmer.lua +++ b/addons/Dimmer/Dimmer.lua @@ -26,7 +26,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.]] _addon.name = 'Dimmer' _addon.author = 'Chiaia' -_addon.version = '1.1' +_addon.version = '1.1.1' _addon.commands = {'dim','dimmer'} From 079a74923dc11ef335fb917e7f3a690fbf5f3283 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Fri, 21 May 2021 23:10:18 +0100 Subject: [PATCH 0628/1002] Version bump. --- addons/organizer/organizer.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/organizer/organizer.lua b/addons/organizer/organizer.lua index 7e04f14b28..1c55011dc1 100644 --- a/addons/organizer/organizer.lua +++ b/addons/organizer/organizer.lua @@ -38,7 +38,7 @@ slips = require 'slips' _addon.name = 'Organizer' _addon.author = 'Byrth, maintainer: Rooks' -_addon.version = 0.20210302 +_addon.version = 0.20210516 _addon.commands = {'organizer','org'} _static = { From 6a4aff48bd9b1e275565a9fdf00330d7d94e2e7a Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sat, 22 May 2021 01:33:17 +0100 Subject: [PATCH 0629/1002] Few more tweaks Added more specific failure status messages. --- addons/Dimmer/Dimmer.lua | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/addons/Dimmer/Dimmer.lua b/addons/Dimmer/Dimmer.lua index d93d765c74..11f95439a3 100644 --- a/addons/Dimmer/Dimmer.lua +++ b/addons/Dimmer/Dimmer.lua @@ -42,12 +42,17 @@ item_info = { } function search_item() + if windower.ffxi.get_player().status > 1 then + log('You cannot use items at this time.') + return + end + local item_array = {} local bags = {0,8,10,11,12} --inventory,wardrobe1-4 local get_items = windower.ffxi.get_items for i=1,#bags do for _,item in ipairs(get_items(bags[i])) do - if item.id > 0 then + if item.id > 0 then item_array[item.id] = item item_array[item.id].bag = bags[i] end @@ -56,7 +61,8 @@ function search_item() for index,stats in pairs(item_info) do local item = item_array[stats.id] local set_equip = windower.ffxi.set_equip - if item and windower.ffxi.get_bag_info(item.bag).enabled then + local bag_enabled = windower.ffxi.get_bag_info(item.bag).enabled + if item and bag_enabled then local ext = extdata.decode(item) local enchant = ext.type == 'Enchanted Equipment' local recast = enchant and ext.charges_remaining > 0 and math.max(ext.next_use_time+18000-os.time(),0) @@ -81,6 +87,8 @@ function search_item() windower.chat.input('/item '..windower.to_shift_jis(stats[lang])..' ') break; end + elseif not bag_enabled then + log('You cannot access '..stats[lang]..' at this time.') else log('You don\'t have '..stats[lang]..'.') end From 1727dbda7b94e0158c533849ab01897923a0120b Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sat, 22 May 2021 01:33:59 +0100 Subject: [PATCH 0630/1002] Few more tweaks Added more specific failure status messages. --- addons/MyHome/MyHome.lua | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/addons/MyHome/MyHome.lua b/addons/MyHome/MyHome.lua index 05098e0520..79bea7ce7f 100644 --- a/addons/MyHome/MyHome.lua +++ b/addons/MyHome/MyHome.lua @@ -40,12 +40,17 @@ item_info = { [3]={id=4181,japanese='呪符デジョン',english='"Instant Warp"'}} function search_item() + if windower.ffxi.get_player().status > 1 then + log('You cannot use items at this time.') + return + end + local item_array = {} local bags = {0,8,10,11,12} --inventory,wardrobe1-4 local get_items = windower.ffxi.get_items for i=1,#bags do for _,item in ipairs(get_items(bags[i])) do - if item.id > 0 then + if item.id > 0 then item_array[item.id] = item item_array[item.id].bag = bags[i] end @@ -54,7 +59,8 @@ function search_item() for index,stats in pairs(item_info) do local item = item_array[stats.id] local set_equip = windower.ffxi.set_equip - if item and windower.ffxi.get_bag_info(item.bag).enabled then + local bag_enabled = windower.ffxi.get_bag_info(item.bag).enabled + if item and bag_enabled then local ext = extdata.decode(item) local enchant = ext.type == 'Enchanted Equipment' local recast = enchant and ext.charges_remaining > 0 and math.max(ext.next_use_time+18000-os.time(),0) @@ -79,6 +85,8 @@ function search_item() windower.chat.input('/item '..windower.to_shift_jis(stats[lang])..' ') break; end + elseif not bag_enabled then + log('You cannot access '..stats[lang]..' at this time.') else log('You don\'t have '..stats[lang]..'.') end From 2cec3f40c07bc1e621de6b16807487c154e5481e Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sat, 22 May 2021 01:35:56 +0100 Subject: [PATCH 0631/1002] Stray space --- addons/MyHome/MyHome.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/MyHome/MyHome.lua b/addons/MyHome/MyHome.lua index 79bea7ce7f..e44c26217d 100644 --- a/addons/MyHome/MyHome.lua +++ b/addons/MyHome/MyHome.lua @@ -50,7 +50,7 @@ function search_item() local get_items = windower.ffxi.get_items for i=1,#bags do for _,item in ipairs(get_items(bags[i])) do - if item.id > 0 then + if item.id > 0 then item_array[item.id] = item item_array[item.id].bag = bags[i] end From 144651f22eb4213cf0fd18f70093d8f4e9c8ea59 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sat, 22 May 2021 01:36:14 +0100 Subject: [PATCH 0632/1002] Stray space --- addons/Dimmer/Dimmer.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/Dimmer/Dimmer.lua b/addons/Dimmer/Dimmer.lua index 11f95439a3..8c509ec67d 100644 --- a/addons/Dimmer/Dimmer.lua +++ b/addons/Dimmer/Dimmer.lua @@ -52,7 +52,7 @@ function search_item() local get_items = windower.ffxi.get_items for i=1,#bags do for _,item in ipairs(get_items(bags[i])) do - if item.id > 0 then + if item.id > 0 then item_array[item.id] = item item_array[item.id].bag = bags[i] end From d2d6865dafd2016fb20e58383f14749d1b5faa26 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sat, 22 May 2021 14:47:22 +0100 Subject: [PATCH 0633/1002] Additional tweaks Added bag name in the error message Minor code cleanups --- addons/Dimmer/Dimmer.lua | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/addons/Dimmer/Dimmer.lua b/addons/Dimmer/Dimmer.lua index 8c509ec67d..2dbe00d222 100644 --- a/addons/Dimmer/Dimmer.lua +++ b/addons/Dimmer/Dimmer.lua @@ -29,9 +29,11 @@ _addon.author = 'Chiaia' _addon.version = '1.1.1' _addon.commands = {'dim','dimmer'} - require('logger') extdata = require('extdata') +res_bags = require('resources').bags + +log_flag = true lang = string.lower(windower.ffxi.get_info().language) item_info = { @@ -48,21 +50,22 @@ function search_item() end local item_array = {} - local bags = {0,8,10,11,12} --inventory,wardrobe1-4 local get_items = windower.ffxi.get_items - for i=1,#bags do - for _,item in ipairs(get_items(bags[i])) do - if item.id > 0 then + local set_equip = windower.ffxi.set_equip + + for bag_id in pairs(res_bags:equippable(true)) do + local bag = get_items(bag_id) + for _,item in ipairs(bag) do + if item.id > 0 then item_array[item.id] = item - item_array[item.id].bag = bags[i] + item_array[item.id].bag = bag_id + item_array[item.id].bag_enabled = windower.ffxi.get_bag_info(bag_id).enabled end end end for index,stats in pairs(item_info) do local item = item_array[stats.id] - local set_equip = windower.ffxi.set_equip - local bag_enabled = windower.ffxi.get_bag_info(item.bag).enabled - if item and bag_enabled then + if item and item.bag_enabled then local ext = extdata.decode(item) local enchant = ext.type == 'Enchanted Equipment' local recast = enchant and ext.charges_remaining > 0 and math.max(ext.next_use_time+18000-os.time(),0) @@ -71,7 +74,6 @@ function search_item() if usable or ext.type == 'General' then if enchant and item.status ~= 5 then --not equipped set_equip(item.slot,stats.slot,item.bag) - log_flag = true repeat --waiting cast delay coroutine.sleep(1) local ext = extdata.decode(get_items(item.bag,item.slot)) @@ -87,8 +89,8 @@ function search_item() windower.chat.input('/item '..windower.to_shift_jis(stats[lang])..' ') break; end - elseif not bag_enabled then - log('You cannot access '..stats[lang]..' at this time.') + elseif item and not item.bag_enabled then + log('You cannot access '..stats[lang]..' from ' .. res_bags[item.bag].name ..' at this time.') else log('You don\'t have '..stats[lang]..'.') end From dff47904d0a5a378e1824a3cf42aa7d1d69eed0d Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sat, 22 May 2021 14:48:31 +0100 Subject: [PATCH 0634/1002] Additional tweaks Added bag name to error message Minor code cleanup --- addons/MyHome/MyHome.lua | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/addons/MyHome/MyHome.lua b/addons/MyHome/MyHome.lua index e44c26217d..c68b979b03 100644 --- a/addons/MyHome/MyHome.lua +++ b/addons/MyHome/MyHome.lua @@ -32,6 +32,9 @@ _addon.commands = {'myhome','mh','warp'} require('logger') extdata = require('extdata') +res_bags = require('resources').bags + +log_flag = true lang = string.lower(windower.ffxi.get_info().language) item_info = { @@ -46,21 +49,22 @@ function search_item() end local item_array = {} - local bags = {0,8,10,11,12} --inventory,wardrobe1-4 local get_items = windower.ffxi.get_items - for i=1,#bags do - for _,item in ipairs(get_items(bags[i])) do - if item.id > 0 then + local set_equip = windower.ffxi.set_equip + + for bag_id in pairs(res_bags:equippable(true)) do + local bag = get_items(bag_id) + for _,item in ipairs(bag) do + if item.id > 0 then item_array[item.id] = item - item_array[item.id].bag = bags[i] + item_array[item.id].bag = bag_id + item_array[item.id].bag_enabled = windower.ffxi.get_bag_info(bag_id).enabled end end end for index,stats in pairs(item_info) do local item = item_array[stats.id] - local set_equip = windower.ffxi.set_equip - local bag_enabled = windower.ffxi.get_bag_info(item.bag).enabled - if item and bag_enabled then + if item and item.bag_enabled then local ext = extdata.decode(item) local enchant = ext.type == 'Enchanted Equipment' local recast = enchant and ext.charges_remaining > 0 and math.max(ext.next_use_time+18000-os.time(),0) @@ -69,7 +73,6 @@ function search_item() if usable or ext.type == 'General' then if enchant and item.status ~= 5 then --not equipped set_equip(item.slot,stats.slot,item.bag) - log_flag = true repeat --waiting cast delay coroutine.sleep(1) local ext = extdata.decode(get_items(item.bag,item.slot)) @@ -85,8 +88,8 @@ function search_item() windower.chat.input('/item '..windower.to_shift_jis(stats[lang])..' ') break; end - elseif not bag_enabled then - log('You cannot access '..stats[lang]..' at this time.') + elseif item and not item.bag_enabled then + log('You cannot access '..stats[lang]..' from ' .. res_bags[item.bag].name ..' at this time.') else log('You don\'t have '..stats[lang]..'.') end From 208af0d4a817b72d0bd761f7758e7adadfe3cbd8 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Fri, 28 May 2021 00:57:42 +0200 Subject: [PATCH 0635/1002] Update fields.lua Adding monstrosity fields to some packets and a few info more for 0x037 and 0x00D --- addons/libs/packets/fields.lua | 70 +++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 19 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 283aded25d..bf4c6006cc 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1367,11 +1367,26 @@ fields.incoming[0x00D] = L{ {ctype='unsigned char', label='Linkshell Red'}, -- 24 {ctype='unsigned char', label='Linkshell Green'}, -- 25 {ctype='unsigned char', label='Linkshell Blue'}, -- 26 - {ctype='unsigned char', label='_unknown5'}, -- 27 Probably junk from the LS color dword - {ctype='data[0x1A]', label='_unknown6'}, -- 28 DSP notes that the 6th bit of byte 54 is the Ballista flag + {ctype='unsigned char', label='_flags1'}, -- 27 0x80 Autogroup flag + {ctype='unsigned char', label='_flags2'}, -- 28 0x01 puts your weapon on hand, 0x02 Request flag, + {ctype='unsigned char', label='Ballista Stuff'}, -- 29 Same pattern than incoming 0x037 packet + {ctype='unsigned char', label='_flags3'}, -- 2A 0x20 Sneak Effect flag, 0x80 New Adventurer flag + {ctype='unsigned char', label='_flags4'}, -- 2B 0x01 Mentor flag + {ctype='data[4]', label='_unknown6'}, -- 2C + {ctype='unsigned short', label='Costume'}, -- 30 ID of the Model + {ctype='data[1]', label='_unknown7'}, -- 32 + {ctype='unsigned char', label='_flags5'}, -- 33 0x02 Trial Account flag, 0x40 Job Master Stars flag + {ctype='unsigned int', label='_unknown8'}, -- 34 Related to mounts + {ctype='data[4]', label='_unknown9'}, -- 38 + {ctype='unsigned short', label='Pet Index', fn=index}, -- 3C + {ctype='unsigned short', label='Monstrosity Species'}, -- 3E High bit is always set while in monstrosity and determines the display of the third name + {ctype='unsigned char', label='Monstrosity Name 1'}, -- 40 + {ctype='unsigned char', label='Monstrosity Name 2'}, -- 41 {ctype='unsigned char', label='Indi Bubble'}, -- 42 Geomancer (GEO) Indi spell effect on players. 0 is no effect. {ctype='unsigned char', label='Face Flags'}, -- 43 0, 3, 4, or 8 - {ctype='data[4]', label='_unknown7'}, -- 44 + {ctype='bit[4]', label='_unknown10'}, -- 44 + {ctype='bit[8]', label='Mount'}, -- 44 Related to Mounts, seems to be mount id + 1, except for chocobo. The value doesn't get zeroed after dismount + {ctype='bit[20]', label='_unknown11'}, -- 45 {ctype='unsigned char', label='Face'}, -- 48 {ctype='unsigned char', label='Race'}, -- 49 {ctype='unsigned short', label='Head'}, -- 4A @@ -2078,9 +2093,12 @@ enums.indi = { -- 0x0040 -- San d'Oria ballista flag -- 0x0060 -- Bastok ballista flag -- 0x0080 -- Windurst Ballista flag - -- 0x0100 -- Participation icon? + -- 0x00A0 -- Wyverns team icon + -- 0x00C0 -- Gryphons team icon + -- 0x0100 -- Belligerency icon (used in monstrosity) -- 0x0200 -- Has some effect - -- 0x0400 -- I don't know anything about ballista + -- 0x0400 -- Some red icon, I don't know where is used (ballista related?) + -- 0x0420 -- Some blue icon, I don't know where is used (ballista related?) -- 0x0800 -- and I still don't D:< -- 0x1000 -- and I still don't D:< @@ -2091,7 +2109,7 @@ enums.indi = { -- 0x0100 -- No obvious effect -- 0x0200 -- Trial Account emblem -- 0x0400 -- No obvious effect - -- 0x0800 -- Question mark icon + -- 0x0800 -- New Adventurer icon -- 0x1000 -- Mentor icon ]] fields.incoming[0x037] = L{ @@ -2108,21 +2126,32 @@ fields.incoming[0x037] = L{ {ctype='unsigned char', label='LS Color Red'}, -- 31 {ctype='unsigned char', label='LS Color Green'}, -- 32 {ctype='unsigned char', label='LS Color Blue'}, -- 33 - {ctype='bit[3]', label='_flags5'}, -- 34 - {ctype='bit[16]', label='Pet Index'}, -- 34 From 0x08 of byte 0x34 to 0x04 of byte 0x36 - {ctype='bit[2]', label='_flags6'}, -- 36 - {ctype='bit[9]', label='Ballista Stuff'}, -- 36 The first few bits seem to determine the icon, but the icon appears to be tied to the type of fight, so it's more than just an icon. - {ctype='bit[8]', label='_flags7'}, -- 37 This is probably tied up in the Ballista stuff too + {ctype='bit[3]', label='_flags5'}, -- 34 + {ctype='bit[16]', label='Pet Index', fn=index}, -- 34 From 0x08 of byte 0x34 to 0x04 of byte 0x36 + {ctype='bit[2]', label='_flags6'}, -- 36 + {ctype='bit[9]', label='Ballista Stuff'}, -- 36 Ballista flags here also makes appear the score, but it is probably modified in a ballista specific packet. + {ctype='bit[8]', label='_flags7'}, -- 37 0x04 Request Flag, 0x08 Trial Flag, x10 Sneak Effect, 0x20 New Adventurer Flag, 0x40 Mentor Flag {ctype='bit[26]', label='_unknown1'}, -- 38 No obvious effect from any of these {ctype='unsigned int', label='Time offset?', fn=time}, -- 3C For me, this is the number of seconds in 66 hours {ctype='unsigned int', label='Timestamp', fn=time}, -- 40 This is 32 years off of JST at the time the packet is sent. - {ctype='data[8]', label='_unknown3'}, -- 44 + {ctype='unsigned short', label='Costume'}, -- 44 ID of the Model + {ctype='data[2]', label='_unknown3'}, -- 46 + {ctype='unsigned short', label='Fellow Index', fn=index}, -- 48 + {ctype='unsigned char', label='Fishing Start Animation'}, -- 4A mostly 0x0D value and sometimes 0x0C observed + {ctype='data[1]', label='_unknown4'}, -- 4B {ctype='data[8]', label='Bit Mask'}, -- 4C - {ctype='data[4]', label='_unknown4'}, -- 54 + {ctype='unsigned short', label='Monstrosity Species'}, -- 54 High bit is always set while in monstrosity and determines the display of the third name + {ctype='unsigned char', label='Monstrosity Name 1'}, -- 56 + {ctype='unsigned char', label='Monstrosity Name 2'}, -- 57 {ctype='bit[7]', label='Indi Buff', fn=e+{'indi'}}, -- 58 - {ctype='bit[9]', label='_unknown5'}, -- 58 - {ctype='unsigned short', label='_junk1'}, -- 5A - {ctype='unsigned int', label='_flags8'}, -- 5C Two least significant bits seem to indicate whether Wardrobes 3 and 4, respectively, are enabled + {ctype='boolbit', label='Job Master Flag'}, -- 58 + {ctype='unsigned char', label='Face Flags'}, -- 59 + {ctype='unsigned char', label='_unknown5'}, -- 5A + {ctype='unsigned char', label='Mount'}, -- 5B Related to Mounts, seems to be mount id + 1, except for chocobo. The value doesn't get zeroed after dismount + {ctype='boolbit', label='Wardrobe 3'}, -- 5C + {ctype='boolbit', label='Wardrobe 4'}, -- 5C + {ctype='bit[6]', label='_flags8'}, -- 5C + {ctype='data[3]', label='_junk1'}, -- 5D } -- Entity Animation @@ -2304,8 +2333,9 @@ func.incoming[0x044][0x17] = L{ {ctype='unsigned short', label='Species'}, -- 08 {ctype='unsigned short', label='_unknown2'}, -- 0A {ctype='unsigned short[12]',label='Instinct'}, -- 0C Instinct assignments are based off their position in the equipment list. - {ctype='unsigned short', label='_unknown3'}, -- 24 - {ctype='data[118]', label='_unknown4'}, -- 26 Zeroing everything beyond this point has no notable effect. + {ctype='unsigned char', label='Monstrosity Name 1'}, -- 24 + {ctype='unsigned char', label='Monstrosity Name 2'}, -- 25 + {ctype='data[118]', label='_unknown3'}, -- 26 Zeroing everything beyond this point has no notable effect. } -- Translate Response @@ -3447,7 +3477,9 @@ fields.incoming[0x0DF] = L{ {ctype='unsigned char', label='MPP', fn=percent}, -- 17 {ctype='unsigned short', label='_unknown1'}, -- 18 {ctype='unsigned short', label='_unknown2'}, -- 1A - {ctype='unsigned int', label='_unknown3'}, -- 1C + {ctype='unsigned short', label='Monstrosity Species'}, -- 1C High bit is always set while in monstrosity and determines the display of the third name + {ctype='unsigned char', label='Monstrosity Name 1'}, -- 1E + {ctype='unsigned char', label='Monstrosity Name 2'}, -- 1F {ctype='unsigned char', label='Main job', fn=job}, -- 20 {ctype='unsigned char', label='Main job level'}, -- 21 {ctype='unsigned char', label='Sub job', fn=job}, -- 22 From f123740757b7eca9baab56089100c394b129d0ae Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Fri, 28 May 2021 02:02:40 +0200 Subject: [PATCH 0636/1002] Update fields.lua Changing Ballista denomination to PvP --- addons/libs/packets/fields.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index bf4c6006cc..01c9fdabfc 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1369,7 +1369,7 @@ fields.incoming[0x00D] = L{ {ctype='unsigned char', label='Linkshell Blue'}, -- 26 {ctype='unsigned char', label='_flags1'}, -- 27 0x80 Autogroup flag {ctype='unsigned char', label='_flags2'}, -- 28 0x01 puts your weapon on hand, 0x02 Request flag, - {ctype='unsigned char', label='Ballista Stuff'}, -- 29 Same pattern than incoming 0x037 packet + {ctype='unsigned char', label='PvP Stuff'}, -- 29 Same pattern than incoming 0x037 packet {ctype='unsigned char', label='_flags3'}, -- 2A 0x20 Sneak Effect flag, 0x80 New Adventurer flag {ctype='unsigned char', label='_flags4'}, -- 2B 0x01 Mentor flag {ctype='data[4]', label='_unknown6'}, -- 2C @@ -2088,7 +2088,7 @@ enums.indi = { -- 0x08 -- Terror flag -- 0x10 -- No obvious effect - Ballista stuff: + PvP stuff: -- 0x0020 -- No obvious effect -- 0x0040 -- San d'Oria ballista flag -- 0x0060 -- Bastok ballista flag @@ -2097,8 +2097,8 @@ enums.indi = { -- 0x00C0 -- Gryphons team icon -- 0x0100 -- Belligerency icon (used in monstrosity) -- 0x0200 -- Has some effect - -- 0x0400 -- Some red icon, I don't know where is used (ballista related?) - -- 0x0420 -- Some blue icon, I don't know where is used (ballista related?) + -- 0x0400 -- Pankration red icon + -- 0x0420 -- Pankration blue icon -- 0x0800 -- and I still don't D:< -- 0x1000 -- and I still don't D:< @@ -2129,7 +2129,7 @@ fields.incoming[0x037] = L{ {ctype='bit[3]', label='_flags5'}, -- 34 {ctype='bit[16]', label='Pet Index', fn=index}, -- 34 From 0x08 of byte 0x34 to 0x04 of byte 0x36 {ctype='bit[2]', label='_flags6'}, -- 36 - {ctype='bit[9]', label='Ballista Stuff'}, -- 36 Ballista flags here also makes appear the score, but it is probably modified in a ballista specific packet. + {ctype='bit[9]', label='PvP Stuff'}, -- 36 Ballista flags here also makes appear the score, but it is probably modified in a ballista specific packet. {ctype='bit[8]', label='_flags7'}, -- 37 0x04 Request Flag, 0x08 Trial Flag, x10 Sneak Effect, 0x20 New Adventurer Flag, 0x40 Mentor Flag {ctype='bit[26]', label='_unknown1'}, -- 38 No obvious effect from any of these {ctype='unsigned int', label='Time offset?', fn=time}, -- 3C For me, this is the number of seconds in 66 hours From 8137c01a6285515884895eb37e96e239d289c72d Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Fri, 28 May 2021 02:12:43 +0200 Subject: [PATCH 0637/1002] Update fields.lua Some changes to redundant info --- addons/libs/packets/fields.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 01c9fdabfc..50ca3db24d 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2106,9 +2106,9 @@ enums.indi = { -- 0x0020 -- No obvious effect -- 0x0040 -- Individually, this bit has no effect. When combined with 0x20, it prevents you from returning to a walking animation after you stop (sliding along the ground while bound) -- 0x0080 -- No obvious effect - -- 0x0100 -- No obvious effect + -- 0x0100 -- Request icon -- 0x0200 -- Trial Account emblem - -- 0x0400 -- No obvious effect + -- 0x0400 -- Sneak Effect -- 0x0800 -- New Adventurer icon -- 0x1000 -- Mentor icon ]] @@ -2130,7 +2130,7 @@ fields.incoming[0x037] = L{ {ctype='bit[16]', label='Pet Index', fn=index}, -- 34 From 0x08 of byte 0x34 to 0x04 of byte 0x36 {ctype='bit[2]', label='_flags6'}, -- 36 {ctype='bit[9]', label='PvP Stuff'}, -- 36 Ballista flags here also makes appear the score, but it is probably modified in a ballista specific packet. - {ctype='bit[8]', label='_flags7'}, -- 37 0x04 Request Flag, 0x08 Trial Flag, x10 Sneak Effect, 0x20 New Adventurer Flag, 0x40 Mentor Flag + {ctype='bit[8]', label='_flags7'}, -- 37 {ctype='bit[26]', label='_unknown1'}, -- 38 No obvious effect from any of these {ctype='unsigned int', label='Time offset?', fn=time}, -- 3C For me, this is the number of seconds in 66 hours {ctype='unsigned int', label='Timestamp', fn=time}, -- 40 This is 32 years off of JST at the time the packet is sent. From 99de2f31daa9a3cfed8a5c1f28d8a84ba1943e2e Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Fri, 28 May 2021 02:50:23 +0200 Subject: [PATCH 0638/1002] Update action packet Fixed animation field, divided stagger field and added some info --- addons/libs/packets/fields.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 283aded25d..f96d8dbfdf 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1759,9 +1759,10 @@ func.incoming[0x028].target_base = L{ func.incoming[0x028].action_base = L{ {ctype='bit[5]', label='Reaction'}, -- 00:0 - {ctype='bit[11]', label='Animation'}, -- 00:5 - {ctype='bit[5]', label='Effect'}, -- 02:0 - {ctype='bit[6]', label='Stagger'}, -- 02:5 + {ctype='bit[12]', label='Animation'}, -- 00:5 + {ctype='bit[4]', label='Effect'}, -- 02:1 Particle effects: bit 1 finishing blow, bit 2 critical hit, bit 3 hit not connected, bit 4 effect follow up (I have only seen in jishnu's radiance) + {ctype='bit[3]', label='Stagger'}, -- 02:5 head moving animation when getting hit, the value seems to be set based on dmg done, more dmg more bits sets (not sure if raw or percentage) + {ctype='bit[3]', label='Knockback'}, -- 03:0 Knockback effect, the more value the more distance {ctype='bit[17]', label='Param'}, -- 03:3 {ctype='bit[10]', label='Message'}, -- 06:2 {ctype='bit[31]', label='_unknown'}, -- 07:4 --Message Modifier? If you get a complete (Resist!) this is set to 2 otherwise a regular Resist is 0. From 18fe5ab57e1287216686aca62c4bbca582f2a8e2 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Sun, 30 May 2021 01:23:53 +0200 Subject: [PATCH 0639/1002] Update actions.lua Updated actions lib for the last luacore changes --- addons/libs/actions.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/addons/libs/actions.lua b/addons/libs/actions.lua index f55053ef6b..14254ce77c 100644 --- a/addons/libs/actions.lua +++ b/addons/libs/actions.lua @@ -117,9 +117,10 @@ local function act_to_string(original,act) offset = offset + 36 for n = 1,act.targets[i].action_count do react = assemble_bit_packed(react,act.targets[i].actions[n].reaction,offset,offset+5) - react = assemble_bit_packed(react,act.targets[i].actions[n].animation,offset+5,offset+16) - react = assemble_bit_packed(react,act.targets[i].actions[n].effect,offset+16,offset+21) - react = assemble_bit_packed(react,act.targets[i].actions[n].stagger,offset+21,offset+27) + react = assemble_bit_packed(react,act.targets[i].actions[n].animation,offset+5,offset+17) + react = assemble_bit_packed(react,act.targets[i].actions[n].effect,offset+17,offset+21) + react = assemble_bit_packed(react,act.targets[i].actions[n].stagger,offset+21,offset+24) + react = assemble_bit_packed(react,act.targets[i].actions[n].knockback,offset+24,offset+27) react = assemble_bit_packed(react,act.targets[i].actions[n].param,offset+27,offset+44) react = assemble_bit_packed(react,act.targets[i].actions[n].message,offset+44,offset+54) react = assemble_bit_packed(react,act.targets[i].actions[n].unknown,offset+54,offset+85) From 7cabfab64dc1918add67402c638ab07b5a08bab4 Mon Sep 17 00:00:00 2001 From: Ian Anderson Date: Sat, 29 May 2021 22:43:16 -0700 Subject: [PATCH 0640/1002] Update Stubborn.lua --- addons/Stubborn/Stubborn.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/Stubborn/Stubborn.lua b/addons/Stubborn/Stubborn.lua index a9afce66cd..54dac73b9f 100644 --- a/addons/Stubborn/Stubborn.lua +++ b/addons/Stubborn/Stubborn.lua @@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --]] _addon.name = 'Stubborn' _addon.author = 'Arico' _addon.version = '1' -_addon.command = {'stubborn','cfh'} +_addon.commands = {'stubborn','cfh'} require('logger') packets = require('packets') From 4bfb23091c6e43bceb8e07419cccbc607250ae98 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Sat, 5 Jun 2021 11:31:10 -0600 Subject: [PATCH 0641/1002] Fixes player.mp error on load When gearswap is loaded, it is initializing stuff basically by re-parsing stuff from windower.packets.last_incoming() by looping over its handlers for various packets. This includes the last 0x028 which relies on knowing the players MP (for checking if you have enough mp to cast the spell). So if it parses the last 0x028 before it parses 0x0DF or 0x0E2 then an error occurs. So this solution just ignores the last 0x028. --- addons/GearSwap/packet_parsing.lua | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/addons/GearSwap/packet_parsing.lua b/addons/GearSwap/packet_parsing.lua index a9e80567c5..f8cabf325f 100644 --- a/addons/GearSwap/packet_parsing.lua +++ b/addons/GearSwap/packet_parsing.lua @@ -702,13 +702,15 @@ end function initialize_packet_parsing() for i,v in pairs(parse.i) do - local lastpacket = windower.packets.last_incoming(i) - if lastpacket then - v(lastpacket) - end - if i == 0x63 and lastpacket and lastpacket:byte(5) ~= 9 then - -- Not receiving an accurate buff line on load because the wrong 0x063 packet was sent last + if i ~= 0x028 then + local lastpacket = windower.packets.last_incoming(i) + if lastpacket then + v(lastpacket) + end + if i == 0x63 and lastpacket and lastpacket:byte(5) ~= 9 then + -- Not receiving an accurate buff line on load because the wrong 0x063 packet was sent last + end end end end From eda10919f9df78a2f1540f000ca6c60a9fdd81a2 Mon Sep 17 00:00:00 2001 From: Darkdoom22 <43715687+Darkdoom22@users.noreply.github.com> Date: Sat, 5 Jun 2021 15:12:52 -0700 Subject: [PATCH 0642/1002] add additional clarity to pet display --- addons/scoreboard/display.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/scoreboard/display.lua b/addons/scoreboard/display.lua index 8a750abf92..b2582d68fb 100644 --- a/addons/scoreboard/display.lua +++ b/addons/scoreboard/display.lua @@ -109,7 +109,7 @@ function Display:build_scoreboard_header() if self.db:empty() then labels = '\n' else - labels = '%23s%7s%9s\n':format('Tot', 'Pct', 'DPS') + labels = '%32s%7s%9s\n':format('Tot', 'Pct', 'DPS') end local dps_status @@ -201,7 +201,7 @@ function Display:update() else percent = '(0%)' end - display_table:append('%-16s%7d%8s %7s':format(v[1], v[2], percent, dps)) + display_table:append('%-25s%7d%8s %7s':format(v[1], v[2], percent, dps)) end alli_damage = alli_damage + v[2] -- gather this even for players not displayed player_lines = player_lines + 1 @@ -413,7 +413,7 @@ end return Display --[[ -Copyright 2013-2014, Jerry Hebert +Copyright © 2013-2014, Jerry Hebert All rights reserved. Redistribution and use in source and binary forms, with or without From 320e05972235e4d10e501712e71a295d8b4bd49a Mon Sep 17 00:00:00 2001 From: Darkdoom22 <43715687+Darkdoom22@users.noreply.github.com> Date: Sat, 5 Jun 2021 15:14:50 -0700 Subject: [PATCH 0643/1002] add additional clarity to pet display --- addons/scoreboard/scoreboard.lua | 64 ++++++++++++++++---------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/addons/scoreboard/scoreboard.lua b/addons/scoreboard/scoreboard.lua index 1d35ea1590..e1c7f7c960 100644 --- a/addons/scoreboard/scoreboard.lua +++ b/addons/scoreboard/scoreboard.lua @@ -479,44 +479,46 @@ end ActionPacket.open_listener(action_handler) -function find_pet_owner_name(actionpacket) - local pet = windower.ffxi.get_mob_by_id(actionpacket:get_id()) - local party = windower.ffxi.get_party() - - local name = nil - - for _, member in pairs(party) do - if type(member) == 'table' and member.mob then - if member.mob.pet_index and member.mob.pet_index> 0 and pet.index == member.mob.pet_index then - name = member.mob.name - break + function find_pet_owner_name(actionpacket) + local pet = windower.ffxi.get_mob_by_id(actionpacket:get_id()) + local party = windower.ffxi.get_party() + + local name = nil + + for _, member in pairs(party) do + if type(member) == 'table' and member.mob then + if member.mob.pet_index and member.mob.pet_index> 0 and pet.index == member.mob.pet_index then + name = member.mob.name + break + end end end + return name, pet.name end - return name -end -function create_mob_name(actionpacket) - local actor = actionpacket:get_actor_name() - local result = '' - local owner = find_pet_owner_name(actionpacket) - if owner ~= nil then - if string.len(actor) > 8 then - result = string.sub(actor, 1, 7)..'.' - else - result = actor - end - if settings.combinepets then - result = 'Pets' + function create_mob_name(actionpacket) + local actor = actionpacket:get_actor_name() + local result = '' + local owner, pet = find_pet_owner_name(actionpacket) + if owner ~= nil then + if string.len(actor) > 8 then + result = string.sub(actor, 1, 7)..'.' + else + result = actor + end + if settings.combinepets then + result = '' + else + result = actor + end + if(pet)then + result = '('..owner..')'..' '..pet + end else - result = actor + return actor end - result = result..' ('..string.sub(owner, 1, 3)..'.)' - else - return actor + return result end - return result -end config.register(settings, function(settings) update_dps_clock:loop(settings.UpdateFrequency) From 0eb3e3948cb5bf2566f9b7df08ac95aafac49e99 Mon Sep 17 00:00:00 2001 From: Darkdoom22 <43715687+Darkdoom22@users.noreply.github.com> Date: Sat, 5 Jun 2021 15:27:44 -0700 Subject: [PATCH 0644/1002] remove parentheses --- addons/scoreboard/scoreboard.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/scoreboard/scoreboard.lua b/addons/scoreboard/scoreboard.lua index e1c7f7c960..4a73530d36 100644 --- a/addons/scoreboard/scoreboard.lua +++ b/addons/scoreboard/scoreboard.lua @@ -511,7 +511,7 @@ ActionPacket.open_listener(action_handler) else result = actor end - if(pet)then + if pet then result = '('..owner..')'..' '..pet end else From 0de818d1f7f49fff87c329af202af6f6227eaea3 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Sun, 6 Jun 2021 20:47:48 -0600 Subject: [PATCH 0645/1002] Private Server Ammo disappear bandaid For our overlords the private servers --- addons/equipviewer/equipviewer.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/equipviewer/equipviewer.lua b/addons/equipviewer/equipviewer.lua index 5e76923075..ff5e1e1c02 100644 --- a/addons/equipviewer/equipviewer.lua +++ b/addons/equipviewer/equipviewer.lua @@ -256,7 +256,7 @@ windower.register_event('incoming chunk', function(id, original, modified, injec end if slot then - if packet['Status'] ~= 5 then --item not equipped + if packet['Status'] ~= 5 and packet['Count'] == 0 then --item not equipped update_equipment_slot:schedule(0, '0x%x':format(id), slot, 0, 0, 0) return end From 3f3fdc73f05f2c4d14aca1e5b99cdc30279634ed Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Mon, 7 Jun 2021 11:36:44 -0600 Subject: [PATCH 0646/1002] Cap framerate on load if not in a cutscene I'm hella tired of telling ppl how to fix it when they load up the game and framerate is uncapped. --- addons/FastCS/FastCS.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/FastCS/FastCS.lua b/addons/FastCS/FastCS.lua index e3a4e08517..899937255a 100644 --- a/addons/FastCS/FastCS.lua +++ b/addons/FastCS/FastCS.lua @@ -73,6 +73,8 @@ windower.register_event('load',function() if player and player.status == 4 then windower.send_command("config FrameRateDivisor 0") + else + disable() end end) From 16d1fe4a1fdf9b4303da4da093b04ba5dd196e93 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Thu, 10 Jun 2021 01:59:21 -0400 Subject: [PATCH 0647/1002] June 9th 2021 Update --- addons/boxdestroyer/messages.lua | 74 ++++++++++++++++---------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/addons/boxdestroyer/messages.lua b/addons/boxdestroyer/messages.lua index de74eafbe5..dd8de669c0 100644 --- a/addons/boxdestroyer/messages.lua +++ b/addons/boxdestroyer/messages.lua @@ -1,58 +1,58 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination" for the associated zone IDs - [100] = 8075, - [101] = 7506, - [102] = 7926, - [103] = 8101, - [104] = 8666, - [105] = 7717, - [106] = 8091, - [107] = 7552, - [108] = 7621, - [109] = 8484, - [110] = 7608, - [111] = 8585, - [112] = 8187, + [100] = 8078, + [101] = 7509, + [102] = 7929, + [103] = 8104, + [104] = 8669, + [105] = 7720, + [106] = 8094, + [107] = 7555, + [108] = 7624, + [109] = 8487, + [110] = 7611, + [111] = 8588, + [112] = 8190, [113] = 7929, [114] = 7786, - [115] = 7882, - [116] = 7578, - [117] = 7585, - [118] = 8127, - [119] = 8364, - [120] = 7524, + [115] = 7885, + [116] = 7581, + [117] = 7588, + [118] = 8130, + [119] = 8367, + [120] = 7527, [121] = 8104, [122] = 7435, [123] = 7887, [124] = 7838, [125] = 7648, - [126] = 8071, - [127] = 7352, + [126] = 8074, + [127] = 7355, [128] = 7507, [130] = 7571, [153] = 11397, - [158] = 7383, + [158] = 7386, [159] = 8446, [160] = 7410, - [166] = 10579, - [167] = 10593, - [169] = 7540, - [172] = 7413, + [166] = 10582, + [167] = 10596, + [169] = 7543, + [172] = 7416, [173] = 10518, [174] = 11396, [176] = 7605, [177] = 11220, [178] = 11400, - [190] = 8254, - [191] = 8374, - [192] = 7410, - [193] = 8386, - [194] = 8266, - [195] = 7597, - [196] = 8306, - [197] = 7351, - [198] = 8272, - [200] = 7528, - [204] = 7516, + [190] = 8257, + [191] = 8377, + [192] = 7413, + [193] = 8389, + [194] = 8269, + [195] = 7600, + [196] = 8309, + [197] = 7354, + [198] = 8275, + [200] = 7531, + [204] = 7519, [205] = 11483, [208] = 8285, [212] = 10639, From 2037ed128cfcd065e64264452c8e755b7cb17a27 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Thu, 10 Jun 2021 02:04:01 -0400 Subject: [PATCH 0648/1002] June 9th 2021 Update --- addons/boxdestroyer/messages.lua | 74 ++++++++++++++++---------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/addons/boxdestroyer/messages.lua b/addons/boxdestroyer/messages.lua index de74eafbe5..dd8de669c0 100644 --- a/addons/boxdestroyer/messages.lua +++ b/addons/boxdestroyer/messages.lua @@ -1,58 +1,58 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination" for the associated zone IDs - [100] = 8075, - [101] = 7506, - [102] = 7926, - [103] = 8101, - [104] = 8666, - [105] = 7717, - [106] = 8091, - [107] = 7552, - [108] = 7621, - [109] = 8484, - [110] = 7608, - [111] = 8585, - [112] = 8187, + [100] = 8078, + [101] = 7509, + [102] = 7929, + [103] = 8104, + [104] = 8669, + [105] = 7720, + [106] = 8094, + [107] = 7555, + [108] = 7624, + [109] = 8487, + [110] = 7611, + [111] = 8588, + [112] = 8190, [113] = 7929, [114] = 7786, - [115] = 7882, - [116] = 7578, - [117] = 7585, - [118] = 8127, - [119] = 8364, - [120] = 7524, + [115] = 7885, + [116] = 7581, + [117] = 7588, + [118] = 8130, + [119] = 8367, + [120] = 7527, [121] = 8104, [122] = 7435, [123] = 7887, [124] = 7838, [125] = 7648, - [126] = 8071, - [127] = 7352, + [126] = 8074, + [127] = 7355, [128] = 7507, [130] = 7571, [153] = 11397, - [158] = 7383, + [158] = 7386, [159] = 8446, [160] = 7410, - [166] = 10579, - [167] = 10593, - [169] = 7540, - [172] = 7413, + [166] = 10582, + [167] = 10596, + [169] = 7543, + [172] = 7416, [173] = 10518, [174] = 11396, [176] = 7605, [177] = 11220, [178] = 11400, - [190] = 8254, - [191] = 8374, - [192] = 7410, - [193] = 8386, - [194] = 8266, - [195] = 7597, - [196] = 8306, - [197] = 7351, - [198] = 8272, - [200] = 7528, - [204] = 7516, + [190] = 8257, + [191] = 8377, + [192] = 7413, + [193] = 8389, + [194] = 8269, + [195] = 7600, + [196] = 8309, + [197] = 7354, + [198] = 8275, + [200] = 7531, + [204] = 7519, [205] = 11483, [208] = 8285, [212] = 10639, From 3ff86462d92638c157d1d5b14184faf9f36f5a5e Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Thu, 10 Jun 2021 22:03:05 +0100 Subject: [PATCH 0649/1002] Moogles are now cached and wiped on zone --- addons/organizer/items.lua | 57 +++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/addons/organizer/items.lua b/addons/organizer/items.lua index c530e56980..10610679f4 100644 --- a/addons/organizer/items.lua +++ b/addons/organizer/items.lua @@ -29,6 +29,48 @@ local items = {} local bags = {} local item_tab = {} +local nomad_moogle +do + local names = {'Nomad Moogle', 'Pilgrim Moogle'} + local moogles = {} + + nomad_moogle = function(wipe) + if wipe then + moogles = {} + return + end + + if type(next(moogles)) == 'nil' then + for _,name in ipairs(names) do + local npcs = windower.ffxi.get_mob_list(name) + for index in pairs(npcs) do + table.insert(moogles,{['index'] = index}) + end + end + end + + local player = windower.ffxi.get_mob_by_target('me') + for _,moogle in pairs(moogles) do + if not moogle.x then + local t = windower.ffxi.get_mob_by_index(moogle.index) + moogle.x, moogle.y = t.x, t.y + end + if moogle.x then + local dx = player.x - moogle.x + local dy = player.y - moogle.y + if dx*dx+dy*dy < 36 then + return true + end + end + end + return false + end +end + +windower.register_event('zone change',function() + nomad_moogle('wipe') +end) + local function validate_bag(bag_table) if type(bag_table) == 'table' and windower.ffxi.get_bag_info(bag_table.id) then if bag_table.access == 'Everywhere' then @@ -36,20 +78,9 @@ local function validate_bag(bag_table) elseif bag_table.access == 'Mog House' then if windower.ffxi.get_info().mog_house then return true - elseif bag_table.english == 'Storage' then -- Storage is not available at Nomad Moogles - return false - end - - local m = {'Nomad Moogle', 'Pilgrim Moogle'} - for _, name in pairs(m) do - for index, _ in pairs(windower.ffxi.get_mob_list(name)) do - local t = windower.ffxi.get_mob_by_index(index) - if t and t.valid_target and t.distance < 36 then - return true - end - end + elseif nomad_moogle() and bag_table.english ~= 'Storage' then -- Storage is not available at Nomad Moogles + return true end - end end return false From f63d7082015e93f2a19b5ff9e61bf082fbfe2d65 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Thu, 10 Jun 2021 22:29:48 +0100 Subject: [PATCH 0650/1002] Checking for valid_target --- addons/organizer/items.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/organizer/items.lua b/addons/organizer/items.lua index 10610679f4..9491271dae 100644 --- a/addons/organizer/items.lua +++ b/addons/organizer/items.lua @@ -53,9 +53,9 @@ do for _,moogle in pairs(moogles) do if not moogle.x then local t = windower.ffxi.get_mob_by_index(moogle.index) - moogle.x, moogle.y = t.x, t.y + moogle.x, moogle.y, moogle.valid_target = t.x, t.y, t.valid_target end - if moogle.x then + if moogle.x and moogle.valid_target then local dx = player.x - moogle.x local dy = player.y - moogle.y if dx*dx+dy*dy < 36 then From 0979e4fb8a88c62c28056590e9a0bedae823a1eb Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Thu, 10 Jun 2021 22:35:50 +0100 Subject: [PATCH 0651/1002] Better check for valid_target --- addons/organizer/items.lua | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/addons/organizer/items.lua b/addons/organizer/items.lua index 9491271dae..4af9e97dc1 100644 --- a/addons/organizer/items.lua +++ b/addons/organizer/items.lua @@ -53,9 +53,11 @@ do for _,moogle in pairs(moogles) do if not moogle.x then local t = windower.ffxi.get_mob_by_index(moogle.index) - moogle.x, moogle.y, moogle.valid_target = t.x, t.y, t.valid_target + if t.valid_target then + moogle.x, moogle.y = t.x, t.y + end end - if moogle.x and moogle.valid_target then + if moogle.x then local dx = player.x - moogle.x local dy = player.y - moogle.y if dx*dx+dy*dy < 36 then @@ -64,6 +66,7 @@ do end end return false + end end From b5acb933d8db305a6ee7144daefcd1530ea1a6a8 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Thu, 10 Jun 2021 22:50:09 +0100 Subject: [PATCH 0652/1002] Discussed changes --- addons/organizer/items.lua | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/addons/organizer/items.lua b/addons/organizer/items.lua index 4af9e97dc1..fc87c708e5 100644 --- a/addons/organizer/items.lua +++ b/addons/organizer/items.lua @@ -30,48 +30,42 @@ local bags = {} local item_tab = {} local nomad_moogle +local clear_moogles do local names = {'Nomad Moogle', 'Pilgrim Moogle'} local moogles = {} + clear_moogles = function() + moogles = {} + end + nomad_moogle = function(wipe) - if wipe then - moogles = {} - return - end - if type(next(moogles)) == 'nil' then for _,name in ipairs(names) do local npcs = windower.ffxi.get_mob_list(name) for index in pairs(npcs) do - table.insert(moogles,{['index'] = index}) + moogles[index] = true end end end local player = windower.ffxi.get_mob_by_target('me') - for _,moogle in pairs(moogles) do - if not moogle.x then - local t = windower.ffxi.get_mob_by_index(moogle.index) - if t.valid_target then - moogle.x, moogle.y = t.x, t.y - end - end - if moogle.x then - local dx = player.x - moogle.x - local dy = player.y - moogle.y - if dx*dx+dy*dy < 36 then + for index in pairs(moogles) do + local moogle = windower.ffxi.get_mob_by_index(index) + if moogle.valid_target then + local dx = (player.x - moogle.x)^2 + local dy = (player.y - moogle.y)^2 + if dx+dy < 36 then return true end end end return false - end end windower.register_event('zone change',function() - nomad_moogle('wipe') + clear_moogles() end) local function validate_bag(bag_table) From e9af4b34322e335807231282fe2915d3e9c3377a Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Thu, 10 Jun 2021 22:58:15 +0100 Subject: [PATCH 0653/1002] Trimming --- addons/organizer/items.lua | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/addons/organizer/items.lua b/addons/organizer/items.lua index fc87c708e5..aa77caac9e 100644 --- a/addons/organizer/items.lua +++ b/addons/organizer/items.lua @@ -40,26 +40,27 @@ do end nomad_moogle = function(wipe) - if type(next(moogles)) == 'nil' then + if #moogles == 0 then for _,name in ipairs(names) do local npcs = windower.ffxi.get_mob_list(name) for index in pairs(npcs) do - moogles[index] = true + table.insert(moogles,index) end end end - local player = windower.ffxi.get_mob_by_target('me') - for index in pairs(moogles) do - local moogle = windower.ffxi.get_mob_by_index(index) - if moogle.valid_target then - local dx = (player.x - moogle.x)^2 - local dy = (player.y - moogle.y)^2 - if dx+dy < 36 then - return true - end + local player = windower.ffxi.get_moo_by_target('moo') + for _, moo_index in ipairs(moos) do + local moo = windower.ffxi.get_moo_by_moo(moo_index) + if moo and (moo.x - player.x)^2 + (moo.y - player.y)^2 < 36 then + return true end end +-- \ ^__^ +-- \ (oo)\_______ +-- (__)\ )\/\ +-- ||----w | +-- || || return false end end From 44daf4f8d7fde3d998c0d3db284e8ca24ec72f13 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Thu, 10 Jun 2021 23:00:05 +0100 Subject: [PATCH 0654/1002] Removed extra argument and farm animals --- addons/organizer/items.lua | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/addons/organizer/items.lua b/addons/organizer/items.lua index aa77caac9e..90af9df893 100644 --- a/addons/organizer/items.lua +++ b/addons/organizer/items.lua @@ -39,7 +39,7 @@ do moogles = {} end - nomad_moogle = function(wipe) + nomad_moogle = function() if #moogles == 0 then for _,name in ipairs(names) do local npcs = windower.ffxi.get_mob_list(name) @@ -56,11 +56,6 @@ do return true end end --- \ ^__^ --- \ (oo)\_______ --- (__)\ )\/\ --- ||----w | --- || || return false end end From 165d80a48f437313c3d375e9b4c26d08551569a1 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Thu, 10 Jun 2021 23:01:11 +0100 Subject: [PATCH 0655/1002] Fixing Arconities --- addons/organizer/items.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/organizer/items.lua b/addons/organizer/items.lua index 90af9df893..b17c693b72 100644 --- a/addons/organizer/items.lua +++ b/addons/organizer/items.lua @@ -49,8 +49,8 @@ do end end - local player = windower.ffxi.get_moo_by_target('moo') - for _, moo_index in ipairs(moos) do + local player = windower.ffxi.get_moo_by_target('me') + for _, moo_index in ipairs(moogles) do local moo = windower.ffxi.get_moo_by_moo(moo_index) if moo and (moo.x - player.x)^2 + (moo.y - player.y)^2 < 36 then return true From 657a54e4fdc082ee42e5452b48582f0abadc6be3 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Thu, 10 Jun 2021 23:03:39 +0100 Subject: [PATCH 0656/1002] Final cleanup Arcon likes cows. Do cows like acorns? --- addons/organizer/items.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/organizer/items.lua b/addons/organizer/items.lua index b17c693b72..2bb43ebcd5 100644 --- a/addons/organizer/items.lua +++ b/addons/organizer/items.lua @@ -49,9 +49,9 @@ do end end - local player = windower.ffxi.get_moo_by_target('me') + local player = windower.ffxi.get_mob_by_target('me') for _, moo_index in ipairs(moogles) do - local moo = windower.ffxi.get_moo_by_moo(moo_index) + local moo = windower.ffxi.get_mob_by_target(moo_index) if moo and (moo.x - player.x)^2 + (moo.y - player.y)^2 < 36 then return true end From 47a9bb37d3e810cff7c43b90048536b507a2344a Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Thu, 10 Jun 2021 23:08:10 +0100 Subject: [PATCH 0657/1002] Fixed oversight --- addons/organizer/items.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/organizer/items.lua b/addons/organizer/items.lua index 2bb43ebcd5..3a1afea58d 100644 --- a/addons/organizer/items.lua +++ b/addons/organizer/items.lua @@ -51,7 +51,7 @@ do local player = windower.ffxi.get_mob_by_target('me') for _, moo_index in ipairs(moogles) do - local moo = windower.ffxi.get_mob_by_target(moo_index) + local moo = windower.ffxi.get_mob_by_index(moo_index) if moo and (moo.x - player.x)^2 + (moo.y - player.y)^2 < 36 then return true end From 4bc8e2adcb31e2322c956ce51c2284f0ee541bb9 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Thu, 10 Jun 2021 23:09:20 +0100 Subject: [PATCH 0658/1002] Version bump --- addons/organizer/organizer.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/organizer/organizer.lua b/addons/organizer/organizer.lua index 1c55011dc1..9abb43f043 100644 --- a/addons/organizer/organizer.lua +++ b/addons/organizer/organizer.lua @@ -38,7 +38,7 @@ slips = require 'slips' _addon.name = 'Organizer' _addon.author = 'Byrth, maintainer: Rooks' -_addon.version = 0.20210516 +_addon.version = 0.20210610 _addon.commands = {'organizer','org'} _static = { From 95b8f729d1852f607225fd89b38b2dc217578dd4 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Thu, 10 Jun 2021 23:13:23 +0100 Subject: [PATCH 0659/1002] Pulled get_bag_info out of the loop --- addons/MyHome/MyHome.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/MyHome/MyHome.lua b/addons/MyHome/MyHome.lua index c68b979b03..9fda6cfd7c 100644 --- a/addons/MyHome/MyHome.lua +++ b/addons/MyHome/MyHome.lua @@ -54,11 +54,12 @@ function search_item() for bag_id in pairs(res_bags:equippable(true)) do local bag = get_items(bag_id) + local bag_enabled = windower.ffxi.get_bag_info(bag_id).enabled for _,item in ipairs(bag) do if item.id > 0 then item_array[item.id] = item item_array[item.id].bag = bag_id - item_array[item.id].bag_enabled = windower.ffxi.get_bag_info(bag_id).enabled + item_array[item.id].bag_enabled = bag_enabled end end end From 1ed6b3970e8fa424be5fac941e13f332fd559781 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Thu, 10 Jun 2021 23:14:01 +0100 Subject: [PATCH 0660/1002] Pulled get_bag_info out of the loop --- addons/Dimmer/Dimmer.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/Dimmer/Dimmer.lua b/addons/Dimmer/Dimmer.lua index 2dbe00d222..726f521159 100644 --- a/addons/Dimmer/Dimmer.lua +++ b/addons/Dimmer/Dimmer.lua @@ -55,11 +55,12 @@ function search_item() for bag_id in pairs(res_bags:equippable(true)) do local bag = get_items(bag_id) + local bag_enabled = windower.ffxi.get_bag_info(bag_id).enabled for _,item in ipairs(bag) do if item.id > 0 then item_array[item.id] = item item_array[item.id].bag = bag_id - item_array[item.id].bag_enabled = windower.ffxi.get_bag_info(bag_id).enabled + item_array[item.id].bag_enabled = bag_enabled end end end From 334246374fac19a472714d1432b63554e80f22f7 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Fri, 11 Jun 2021 00:15:12 +0100 Subject: [PATCH 0661/1002] Using new luacore's correct bag.enabled value --- addons/Dimmer/Dimmer.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/addons/Dimmer/Dimmer.lua b/addons/Dimmer/Dimmer.lua index 726f521159..7b9f814604 100644 --- a/addons/Dimmer/Dimmer.lua +++ b/addons/Dimmer/Dimmer.lua @@ -55,12 +55,11 @@ function search_item() for bag_id in pairs(res_bags:equippable(true)) do local bag = get_items(bag_id) - local bag_enabled = windower.ffxi.get_bag_info(bag_id).enabled for _,item in ipairs(bag) do if item.id > 0 then item_array[item.id] = item item_array[item.id].bag = bag_id - item_array[item.id].bag_enabled = bag_enabled + item_array[item.id].bag_enabled = bag.enabled end end end From 39fae0b6d994bf43b11ecd180eb3552677f56c7f Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Fri, 11 Jun 2021 00:16:12 +0100 Subject: [PATCH 0662/1002] Switched to luacore's correct bag.enabled value --- addons/MyHome/MyHome.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/addons/MyHome/MyHome.lua b/addons/MyHome/MyHome.lua index 9fda6cfd7c..3c4a6685c5 100644 --- a/addons/MyHome/MyHome.lua +++ b/addons/MyHome/MyHome.lua @@ -54,12 +54,11 @@ function search_item() for bag_id in pairs(res_bags:equippable(true)) do local bag = get_items(bag_id) - local bag_enabled = windower.ffxi.get_bag_info(bag_id).enabled for _,item in ipairs(bag) do if item.id > 0 then item_array[item.id] = item item_array[item.id].bag = bag_id - item_array[item.id].bag_enabled = bag_enabled + item_array[item.id].bag_enabled = bag.enabled end end end From 62f8bea2300a5c03bd04052c0b0e5e0c7ae2e895 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Fri, 11 Jun 2021 22:00:30 +0200 Subject: [PATCH 0663/1002] Update slips.lua Added new items to slips lib --- addons/libs/slips.lua | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 67edbaa3b7..12cb8bfd6d 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -15,7 +15,7 @@ slips.storages = L{29312, 29313, 29314, 29315, 29316, 29317, 29318, 2931 slips.items = { [slips.storages[1]] = L{16084, 14546, 14961, 15625, 15711, 16085, 14547, 14962, 15626, 15712, 16086, 14548, 14963, 15627, 15713, 16087, 14549, 14964, 15628, 15714, 16088, 14550, 14965, 15629, 15715, 16089, 14551, 14966, 15630, 15716, 16090, 14552, 14967, 15631, 15717, 16091, 14553, 14968, 15632, 15718, 16092, 14554, 14969, 15633, 15719, 16093, 14555, 14970, 15634, 15720, 16094, 14556, 14971, 15635, 15721, 16095, 14557, 14972, 15636, 15722, 16096, 14558, 14973, 15637, 15723, 16097, 14559, 14974, 15638, 15724, 16098, 14560, 14975, 15639, 15725, 16099, 14561, 14976, 15640, 15726, 16100, 14562, 14977, 15641, 15727, 16101, 14563, 14978, 15642, 15728, 16102, 14564, 14979, 15643, 15729, 16103, 14565, 14980, 15644, 15730, 16106, 14568, 14983, 15647, 15733, 16107, 14569, 14984, 15648, 15734, 16108, 14570, 14985, 15649, 15735, 16602, 17741, 18425, 18491, 18588, 18717, 18718, 18850, 18943, 16069, 14530, 14940, 15609, 15695, 16062, 14525, 14933, 15604, 15688, 16064, 14527, 14935, 15606, 15690, 18685, 18065, 17851, 18686, 18025, 18435, 18113, 17951, 17715, 18485, 18408, 18365, 18583, 18417, 18388, 16267, 16268, 16269, 16228, 16229, 15911, 15799, 15800, 15990, 17745, 18121, 16117, 14577, 17857}, -- 168 [slips.storages[2]] = L{12421, 12549, 12677, 12805, 12933, 13911, 14370, 14061, 14283, 14163, 12429, 12557, 12685, 12813, 12941, 13924, 14371, 14816, 14296, 14175, 13934, 14387, 14821, 14303, 14184, 13935, 14388, 14822, 14304, 14185, 13876, 13787, 14006, 14247, 14123, 13877, 13788, 14007, 14248, 14124, 13908, 14367, 14058, 14280, 14160, 13909, 14368, 14059, 14281, 14161, 16113, 14573, 14995, 15655, 15740, 16115, 14575, 14997, 15657, 15742, 16114, 14574, 14996, 15656, 15741, 16116, 14576, 14998, 15658, 15743, 12818, 18198, 12946, 18043, 12690, 17659, 12296, 12434, 15471, 15472, 15473, 15508, 15509, 15510, 15511, 15512, 15513, 15514, 17710, 17595, 18397, 18360, 18222, 17948, 18100, 15475, 15476, 15477, 15488, 15961, 14815, 14812, 14813, 15244, 15240, 14488, 14905, 15576, 15661, 15241, 14489, 14906, 15577, 15662, 13927, 14378, 14076, 14308, 14180, 13928, 14379, 14077, 14309, 14181, 10438, 10276, 10320, 10326, 10367, 10439, 10277, 10321, 10327, 10368, 10440, 10278, 10322, 10328, 10369, 10441, 10279, 10323, 10329, 10370, 25734, 25735, 25736, 25737, 25738, 25739, 25740, 25741, 25742, 25743, 25744}, -- 155 - [slips.storages[3]] = L{16155, 11282, 15021, 16341, 11376, 16156, 11283, 15022, 16342, 11377, 16157, 11284, 15023, 16343, 11378, 16148, 14590, 15011, 16317, 15757, 16143, 14591, 15012, 16318, 15758, 16146, 14588, 15009, 16315, 15755, 16147, 14589, 15010, 16316, 15756, 15966, 15967, 19041, 17684, 17685, 11636, 15844, 15934, 16258, 18735, 18734, 16291, 16292, 19042, 15935, 16293, 16294, 15936, 18618, 11588, 11545, 16158, 16159, 16160, 16149, 14583, 15007, 16314, 15751, 16141, 14581, 15005, 16312, 15749, 16142, 14582, 15006, 16313, 15750, 10876, 10450, 10500, 11969, 10600, 10877, 10451, 10501, 11970, 10601, 10878, 10452, 10502, 11971, 10602, 19132, 18551, 11798, 11362, 11363, 11625, 15959, 16259}, -- 97 + [slips.storages[3]] = L{16155, 11282, 15021, 16341, 11376, 16156, 11283, 15022, 16342, 11377, 16157, 11284, 15023, 16343, 11378, 16148, 14590, 15011, 16317, 15757, 16143, 14591, 15012, 16318, 15758, 16146, 14588, 15009, 16315, 15755, 16147, 14589, 15010, 16316, 15756, 15966, 15967, 19041, 17684, 17685, 11636, 15844, 15934, 16258, 18735, 18734, 16291, 16292, 19042, 15935, 16293, 16294, 15936, 18618, 11588, 11545, 16158, 16159, 16160, 16149, 14583, 15007, 16314, 15751, 16141, 14581, 15005, 16312, 15749, 16142, 14582, 15006, 16313, 15750, 10876, 10450, 10500, 11969, 10600, 10877, 10451, 10501, 11970, 10601, 10878, 10452, 10502, 11971, 10602, 19132, 18551, 11798, 11362, 11363, 11625, 15959, 16259, 22299, 26414, 21623, 26219, 21886, 23792, 23793, 23794, 23795, 23796}, -- 107 [slips.storages[4]] = L{12511, 12638, 13961, 14214, 14089, 12512, 12639, 13962, 14215, 14090, 13855, 12640, 13963, 14216, 14091, 13856, 12641, 13964, 14217, 14092, 12513, 12642, 13965, 14218, 14093, 12514, 12643, 13966, 14219, 14094, 12515, 12644, 13967, 14220, 14095, 12516, 12645, 13968, 14221, 14096, 12517, 12646, 13969, 14222, 14097, 13857, 12647, 13970, 14223, 14098, 12518, 12648, 13971, 14099, 14224, 13868, 13781, 13972, 14225, 14100, 13869, 13782, 13973, 14226, 14101, 12519, 12649, 13974, 14227, 14102, 12520, 12650, 13975, 14228, 14103, 15265, 14521, 14928, 15600, 15684, 15266, 14522, 14929, 15601, 15685, 15267, 14523, 14930, 15602, 15686, 16138, 14578, 15002, 15659, 15746, 16139, 14579, 15003, 15660, 15747, 16140, 14580, 15004, 16311, 15748, 16678, 17478, 17422, 17423, 16829, 16764, 17643, 16798, 16680, 16766, 17188, 17812, 17771, 17772, 16887, 17532, 17717, 18702, 17858, 19203, 21461, 21124, 20776, 27786, 27926, 28066, 28206, 28346, 27787, 27927, 28067, 28207, 28347}, -- 138 [slips.storages[5]] = L{15225, 14473, 14890, 15561, 15352, 15226, 14474, 14891, 15562, 15353, 15227, 14475, 14892, 15563, 15354, 15228, 14476, 14893, 15564, 15355, 15229, 14477, 14894, 15565, 15356, 15230, 14478, 14895, 15566, 15357, 15231, 14479, 14896, 15567, 15358, 15232, 14480, 14897, 15568, 15359, 15233, 14481, 14898, 15569, 15360, 15234, 14482, 14899, 15570, 15361, 15235, 14483, 14900, 15362, 15571, 15236, 14484, 14901, 15572, 15363, 15237, 14485, 14902, 15573, 15364, 15238, 14486, 14903, 15574, 15365, 15239, 14487, 14904, 15575, 15366, 11464, 11291, 15024, 16345, 11381, 11467, 11294, 15027, 16348, 11384, 11470, 11297, 15030, 16351, 11387, 11475, 11302, 15035, 16357, 11393, 11476, 11303, 15036, 16358, 11394, 11477, 11304, 15037, 16359, 11395}, -- 105 [slips.storages[6]] = L{15072, 15087, 15102, 15117, 15132, 15871, 15073, 15088, 15103, 15118, 15133, 15478, 15074, 15089, 15104, 15119, 15134, 15872, 15075, 15090, 15105, 15120, 15135, 15874, 15076, 15091, 15106, 15121, 15136, 15873, 15077, 15092, 15107, 15122, 15137, 15480, 15078, 15093, 15108, 15123, 15138, 15481, 15079, 15094, 15109, 15124, 15139, 15479, 15080, 15095, 15110, 15125, 15140, 15875, 15081, 15096, 15111, 15126, 15141, 15482, 15082, 15097, 15112, 15127, 15142, 15876, 15083, 15098, 15113, 15128, 15143, 15879, 15084, 15099, 15114, 15129, 15144, 15877, 15085, 15100, 15115, 15130, 15145, 15878, 15086, 15101, 15116, 15131, 15146, 15484, 11465, 11292, 15025, 16346, 11382, 16244, 11468, 11295, 15028, 16349, 11385, 15920, 11471, 11298, 15031, 16352, 11388, 16245, 11478, 11305, 15038, 16360, 11396, 16248, 11480, 11307, 15040, 16362, 11398, 15925}, -- 120 @@ -31,16 +31,16 @@ slips.items = { [slips.storages[16]] = L{27684, 27828, 27964, 28111, 28244, 27685, 27829, 27965, 28112, 28245, 27686, 27830, 27966, 28113, 28246, 27687, 27831, 27967, 28114, 28247, 27688, 27832, 27968, 28115, 28248, 27689, 27833, 27969, 28116, 28249, 27690, 27834, 27970, 28117, 28250, 27691, 27835, 27971, 28118, 28251, 27692, 27836, 27972, 28119, 28252, 27693, 27837, 27973, 28120, 28253, 27694, 27838, 27974, 28121, 28254, 27695, 27839, 27975, 28122, 28255, 27696, 27840, 27976, 28123, 28256, 27697, 27841, 27977, 28124, 28257, 27698, 27842, 27978, 28125, 28258, 27699, 27843, 27979, 28126, 28259, 27700, 27844, 27980, 28127, 28260, 27701, 27845, 27981, 28128, 28261, 27702, 27846, 27982, 28129, 28262, 27703, 27847, 27983, 28130, 28263, 27704, 27848, 27984, 28131, 28264, 27705, 27849, 27985, 28132, 28265, 27706, 27850, 27986, 28133, 28266}, -- 115 [slips.storages[17]] = L{26624, 26800, 26976, 27152, 27328, 26626, 26802, 26978, 27154, 27330, 26628, 26804, 26980, 27156, 27332, 26630, 26806, 26982, 27158, 27334, 26632, 26808, 26984, 27160, 27336, 26634, 26810, 26986, 27162, 27338, 26636, 26812, 26988, 27164, 27340, 26638, 26814, 26990, 27166, 27342, 26640, 26816, 26992, 27168, 27344, 26642, 26818, 26994, 27170, 27346, 26644, 26820, 26996, 27172, 27348, 26646, 26822, 26998, 27174, 27350, 26648, 26824, 27000, 27176, 27352, 26650, 26826, 27002, 27178, 27354, 26652, 26828, 27004, 27180, 27356, 26654, 26830, 27006, 27182, 27358, 26656, 26832, 27008, 27184, 27360, 26658, 26834, 27010, 27186, 27362, 26660, 26836, 27012, 27188, 27364, 26662, 26838, 27014, 27190, 27366, 26664, 26840, 27016, 27192, 27368, 26666, 26842, 27018, 27194, 27370}, -- 110 [slips.storages[18]] = L{26625, 26801, 26977, 27153, 27329, 26627, 26803, 26979, 27155, 27331, 26629, 26805, 26981, 27157, 27333, 26631, 26807, 26983, 27159, 27335, 26633, 26809, 26985, 27161, 27337, 26635, 26811, 26987, 27163, 27339, 26637, 26813, 26989, 27165, 27341, 26639, 26815, 26991, 27167, 27343, 26641, 26817, 26993, 27169, 27345, 26643, 26819, 26995, 27171, 27347, 26645, 26821, 26997, 27173, 27349, 26647, 26823, 26999, 27175, 27351, 26649, 26825, 27001, 27177, 27353, 26651, 26827, 27003, 27179, 27355, 26653, 26829, 27005, 27181, 27357, 26655, 26831, 27007, 27183, 27359, 26657, 26833, 27009, 27185, 27361, 26659, 26835, 27011, 27187, 27363, 26661, 26837, 27013, 27189, 27365, 26663, 26839, 27015, 27191, 27367, 26665, 26841, 27017, 27193, 27369, 26667, 26843, 27019, 27195, 27371}, -- 110 - [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757}, -- 191 - [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453,}, -- 110 - [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454,}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489}, -- 130 SE Skipped an index hence the 0 as one of the items + [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757, 25909}, -- 192 + [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 + [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066}, -- 137 SE Skipped an index hence the 0 as one of the items [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770}, --174 - [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330,}, --115 - [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665,}, --115 - [slips.storages[26]] = L{23063, 23130, 23197, 23264, 23331, 23064, 23131, 23198, 23265, 23332, 23065, 23132, 23199, 23266, 23333, 23066, 23133, 23200, 23267, 23334, 23067, 23134, 23201, 23268, 23335, 23068, 23135, 23202, 23269, 23336, 23069, 23136, 23203, 23270, 23337, 23070, 23137, 23204, 23271, 23338, 23071, 23138, 23205, 23272, 23339, 23072, 23139, 23206, 23273, 23340, 23073, 23140, 23207, 23274, 23341, 23074, 23141, 23208, 23275, 23342, 23075, 23142, 23209, 23276, 23343, 23076, 23143, 23210, 23277, 23344, 23077, 23144, 23211, 23278, 23345, 23078, 23145, 23212, 23279, 23346, 23079, 23146, 23213, 23280, 23347, 23080, 23147, 23214, 23281, 23348, 23081, 23148, 23215, 23282, 23349, 23082, 23149, 23216, 23283, 23350, 23083, 23150, 23217, 23284, 23351, 23084, 23151, 23218, 23285, 23352,}, --110 - [slips.storages[27]] = L{23398, 23465, 23532, 23599, 23666, 23399, 23466, 23533, 23600, 23667, 23400, 23467, 23534, 23601, 23668, 23401, 23468, 23535, 23602, 23669, 23402, 23469, 23536, 23603, 23670, 23403, 23470, 23537, 23604, 23671, 23404, 23471, 23538, 23605, 23672, 23405, 23472, 23539, 23606, 23673, 23406, 23473, 23540, 23607, 23674, 23407, 23474, 23541, 23608, 23675, 23408, 23475, 23542, 23609, 23676, 23409, 23476, 23543, 23610, 23677, 23410, 23477, 23544, 23611, 23678, 23411, 23478, 23545, 23612, 23679, 23412, 23479, 23546, 23613, 23680, 23413, 23480, 23547, 23614, 23681, 23414, 23481, 23548, 23615, 23682, 23415, 23482, 23549, 23616, 23683, 23416, 23483, 23550, 23617, 23684, 23417, 23484, 23551, 23618, 23685, 23418, 23485, 23552, 23619, 23686, 23419, 23486, 23553, 23620, 23687,}, --110 - [slips.storages[28]] = L{21515, 21561, 21617, 21670, 21718, 21775, 21826, 21879, 21918, 21971, 22027, 22082, 22108, 22214, 21516, 21562, 21618, 21671, 21719, 21776, 21827, 21880, 21919, 21972, 22028, 22083, 22109, 22215, 21517, 21563, 21619, 21672, 21720, 21777, 21828, 21881, 21920, 21973, 22029, 22084, 22110, 22216, 21518, 21564, 21620, 21673, 21721, 21778, 21829, 21882, 21921, 21974, 22030, 22085, 22111, 22217, 21519, 21565, 21621, 21674, 21722, 21779, 21830, 21883, 21922, 21975, 22031, 22086, 22107, 22218}, --70 + [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, --115 + [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, --115 + [slips.storages[26]] = L{23063, 23130, 23197, 23264, 23331, 23064, 23131, 23198, 23265, 23332, 23065, 23132, 23199, 23266, 23333, 23066, 23133, 23200, 23267, 23334, 23067, 23134, 23201, 23268, 23335, 23068, 23135, 23202, 23269, 23336, 23069, 23136, 23203, 23270, 23337, 23070, 23137, 23204, 23271, 23338, 23071, 23138, 23205, 23272, 23339, 23072, 23139, 23206, 23273, 23340, 23073, 23140, 23207, 23274, 23341, 23074, 23141, 23208, 23275, 23342, 23075, 23142, 23209, 23276, 23343, 23076, 23143, 23210, 23277, 23344, 23077, 23144, 23211, 23278, 23345, 23078, 23145, 23212, 23279, 23346, 23079, 23146, 23213, 23280, 23347, 23080, 23147, 23214, 23281, 23348, 23081, 23148, 23215, 23282, 23349, 23082, 23149, 23216, 23283, 23350, 23083, 23150, 23217, 23284, 23351, 23084, 23151, 23218, 23285, 23352}, --110 + [slips.storages[27]] = L{23398, 23465, 23532, 23599, 23666, 23399, 23466, 23533, 23600, 23667, 23400, 23467, 23534, 23601, 23668, 23401, 23468, 23535, 23602, 23669, 23402, 23469, 23536, 23603, 23670, 23403, 23470, 23537, 23604, 23671, 23404, 23471, 23538, 23605, 23672, 23405, 23472, 23539, 23606, 23673, 23406, 23473, 23540, 23607, 23674, 23407, 23474, 23541, 23608, 23675, 23408, 23475, 23542, 23609, 23676, 23409, 23476, 23543, 23610, 23677, 23410, 23477, 23544, 23611, 23678, 23411, 23478, 23545, 23612, 23679, 23412, 23479, 23546, 23613, 23680, 23413, 23480, 23547, 23614, 23681, 23414, 23481, 23548, 23615, 23682, 23415, 23482, 23549, 23616, 23683, 23416, 23483, 23550, 23617, 23684, 23417, 23484, 23551, 23618, 23685, 23418, 23485, 23552, 23619, 23686, 23419, 23486, 23553, 23620, 23687}, --110 + [slips.storages[28]] = L{21515, 21561, 21617, 21670, 21718, 21775, 21826, 21879, 21918, 21971, 22027, 22082, 22108, 22214, 21516, 21562, 21618, 21671, 21719, 21776, 21827, 21880, 21919, 21972, 22028, 22083, 22109, 22215, 21517, 21563, 21619, 21672, 21720, 21777, 21828, 21881, 21920, 21973, 22029, 22084, 22110, 22216, 21518, 21564, 21620, 21673, 21721, 21778, 21829, 21882, 21921, 21974, 22030, 22085, 22111, 22217, 21519, 21565, 21621, 21674, 21722, 21779, 21830, 21883, 21922, 21975, 22031, 22086, 22107, 22218, 22089}, --71 } function slips.get_slip_id(n) From 35b7f3d220f78458840cba3a8e859210091e1f93 Mon Sep 17 00:00:00 2001 From: Ian Anderson Date: Wed, 16 Jun 2021 15:21:55 -0700 Subject: [PATCH 0664/1002] Update jobchange.lua This is a change to job change to allow it to work consistently in Odyssey. The first time you enter Idyssey the server will accept an `0x100`, but once you initiate an NM fight the sever will no longer accept an `0x100` until you poke the Moogle again without the BCNM flag. I added a poke for Nomad Moogles as well since technically there is no manual way to change jobs without poking a Nomad Moogle, and if SE wanted to get banhappy it's something they could easily look for. Note -- changing jobs manually the first time you enter the BC, the last two bytes(unknown 1 & 2) are empty, but once you've killed an NM -- they do contain *some* values, but they don't seem to be related to anything related to the event. The server still accepts a traditional `0x100`. --- addons/JobChange/jobchange.lua | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/addons/JobChange/jobchange.lua b/addons/JobChange/jobchange.lua index e5068ba14b..ad289640d1 100644 --- a/addons/JobChange/jobchange.lua +++ b/addons/JobChange/jobchange.lua @@ -64,6 +64,14 @@ local find_conflict = function(job_name, p) end end +local poke = function(npc) + local p = packets.new('outgoing', 0x1a, { + ["Target"] = npc.id, + ["Target Index"] = npc.index, + }) + packets.inject(p) +end + local find_temp_job = function(p) for _, job_name in ipairs(temp_jobs) do if not find_conflict(job_name, p) and p.jobs[job_name:upper()] > 0 then @@ -191,6 +199,10 @@ windower.register_event('addon command', function(command, ...) local npc = find_job_change_npc() if npc then + if npc.name == 'Nomad Moogle' or npc.name == 'Pilgrim Moogle'then + poke(npc) + coroutine.sleep(1) -- the moogles don't return an 0x032~0x034 so can't job change in response to an incoming menu packet. + end for _, change in ipairs(changes) do if change.is_conflict then log('Conflict with '..(change.is_main and 'main' or 'sub')..' job. Changing to: '..res.jobs[change.job_id].ens) @@ -198,7 +210,6 @@ windower.register_event('addon command', function(command, ...) log('Changing '..(change.is_main and 'main' or 'sub')..' job to: '..res.jobs[change.job_id].ens) end jobchange(change.job_id, change.is_main) - coroutine.sleep(0.5) end else From b5b2cef802cbddf5a02775b9f16762cacd5efd58 Mon Sep 17 00:00:00 2001 From: Ian Anderson Date: Wed, 16 Jun 2021 16:16:34 -0700 Subject: [PATCH 0665/1002] Update jobchange.lua Block mog menu from opening. --- addons/JobChange/jobchange.lua | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/addons/JobChange/jobchange.lua b/addons/JobChange/jobchange.lua index ad289640d1..81e6ff52d8 100644 --- a/addons/JobChange/jobchange.lua +++ b/addons/JobChange/jobchange.lua @@ -64,14 +64,23 @@ local find_conflict = function(job_name, p) end end +injected_poke = false local poke = function(npc) local p = packets.new('outgoing', 0x1a, { ["Target"] = npc.id, ["Target Index"] = npc.index, }) + injected_poke = true packets.inject(p) end - +windower.register_event('incoming chunk',function(id,data,modified,injected,blocked) + local p = packets.parse('incoming',data) + if id == 0x02E and injected_poke then + injected_poke = false + return true + end +end) + local find_temp_job = function(p) for _, job_name in ipairs(temp_jobs) do if not find_conflict(job_name, p) and p.jobs[job_name:upper()] > 0 then From 8ea9cd48c68f550a48624406260b7b139a018461 Mon Sep 17 00:00:00 2001 From: Zach Toogood Date: Fri, 18 Jun 2021 13:23:23 +0300 Subject: [PATCH 0666/1002] Extend soul_plates table --- addons/libs/extdata.lua | 144 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 139 insertions(+), 5 deletions(-) diff --git a/addons/libs/extdata.lua b/addons/libs/extdata.lua index 61f73a2d94..aeae471c95 100644 --- a/addons/libs/extdata.lua +++ b/addons/libs/extdata.lua @@ -1452,13 +1452,147 @@ soul_plates = { [0x15E] = "Magic Acquisition Bonus II", [0x15F] = "Magic Acquisition Level -5", [0x160] = "Magic Acquisition Level -10", -- 00 B0 F8 03 + [0x161] = "Healing Potency Bonus", + [0x162] = "Healing Potency Bonus II", + [0x163] = "Healing Potency +40", + [0x164] = "Healing Potency +80", + [0x165] = "MP Recovery Bonus", + [0x166] = "MP Recovery Bonus II", + [0x167] = "MP Recovery +25", + [0x168] = "MP Recovery +50", + [0x169] = "TP Recovery Bonus", + [0x16A] = "TP Recovery Bonus II", + [0x16B] = "TP Recovery +25", + [0x16C] = "TP Recovery +50", + [0x16D] = "50% MP Conserve Rate Bonus", + [0x16E] = "50% MP Conserve Rate Bonus II", + [0x16F] = "50% MP Conserve Rate +15%", + [0x170] = "50% MP Conserve Rate +30%", + [0x171] = "100% MP Conserve Rate Bonus", + [0x172] = "100% MP Conserve Rate Bonus II", + [0x173] = "100% MP Conserve Rate +15%", + [0x174] = "100% MP Conserve Rate +30%", + [0x175] = "50% TP Conserve Rate Bonus", + [0x176] = "50% TP Conserve Rate Bonus II", + [0x177] = "50% TP Conserve Rate +15%", + [0x178] = "50% TP Conserve Rate +30%", + [0x179] = "100% TP Conserve Rate Bonus", + [0x17A] = "100% TP Conserve Rate Bonus II", + [0x17B] = "100% TP Conserve Rate +15%", + [0x17C] = "100% TP Conserve Rate +30%", + [0x17D] = "EXP Bonus", + [0x17E] = "EXP Bonus II", + [0x17F] = "EXP +15%", + [0x180] = "EXP +30%", + [0x181] = "Skill Improvement Rate Bonus", + [0x182] = "Skill Improvement Rate Bonus II", + [0x183] = "Skill Improvement Rate +15%", + [0x184] = "Skill Improvement Rate +30%", + [0x185] = "Trust Bonus", + [0x186] = "Trust Bonus II", + [0x187] = "Trust +15", + [0x188] = "Trust +30", + + [0x195] = "Embiggen", + [0x196] = "Embiggen II", + [0x197] = "Minimize", + [0x198] = "Minimize II", + + [0x19D] = "Gradual HP Max Bonus", + [0x19E] = "Diminishing HP Max Bonus", + [0x19F] = "Gradual MP Max Bonus", + [0x1A0] = "Diminishing MP Max Bonus", + [0x1A1] = "Gradual Attack Bonus", + [0x1A2] = "Diminishing Attack Bonus", + [0x1A3] = "Gradual Defense Bonus", + [0x1A4] = "Diminishing Defense Bonus", + [0x1A5] = "Gradual Magic Attack Bonus", + [0x1A6] = "Diminishing Magic Attack Bonus", + [0x1A7] = "Gradual Magic Defense Bonus", + [0x1A8] = "Diminishing Magic Defense Bonus", + [0x1A9] = "Gradual Accuracy Bonus", + [0x1B0] = "Diminishing Accuracy Bonus", + [0x1B1] = "Gradual Magic Accuracy Bonus", + [0x1B2] = "Diminishing Magic Accuracy Bonus", + [0x1B3] = "Gradual Evasion Bonus", + [0x1B4] = "Diminishing Evasion Bonus", + [0x1B5] = "Gradual Critial Hit Rate Bonus", + [0x1B6] = "Diminishing Critial Hit Rate Bonus", + [0x1B7] = "Gradual Interruption Rate Bonus", + [0x1B8] = "Diminishing Interruption Rate Bonus", + [0x1B9] = "Gradual EXP Bonus", + [0x1BA] = "Diminishing EXP Bonus", + [0x1BB] = "Resist Poison", + [0x1BC] = "Resist Sleep", + [0x1BD] = "Resist Blind", + [0x1BE] = "Resist Slow", + [0x1BF] = "Resist Paralysis", + [0x1C0] = "Resist Bind", + [0x1C1] = "Resist Silence", + [0x1C2] = "Bird Killer", + [0x1C3] = "Amorph Killer", + [0x1C4] = "Lizard Killer", + [0x1C5] = "Aquan Killer", + [0x1C6] = "Plantoid Killer", + [0x1C7] = "Beast Killer", + [0x1C8] = "Demon Killer", + [0x1C9] = "Dragon Killer", + [0x1CA] = "Double Attack", + [0x1CB] = "Double Attack II", + [0x1CC] = "Double Attack Rate +15%", + [0x1CD] = "Double Attack Rate +30%", + [0x1CE] = "Triple Attack", + [0x1CF] = "Triple Attack II", + [0x1D0] = "Triple Attack Rate +15%", + [0x1D1] = "Triple Attack Rate +30%", + [0x1D2] = "Counter", + [0x1D3] = "Counter II", + [0x1D4] = "Counter Rate +15%", + [0x1D5] = "Counter Rate +30%", + [0x1D6] = "Subtle Blow", + [0x1D7] = "Subtle Blow II", + [0x1D8] = "Subtle Blow Rate +15%", + [0x1D9] = "Subtle Blow Rate +30%", + [0x1DA] = "Savagery", + [0x1DB] = "Aggressive Aim", + [0x1DC] = "Martial Arts", + [0x1DD] = "Kick Attacks", + [0x1DE] = "Invigorate", + [0x1DF] = "Penance", + [0x1E0] = "Clear Mind", + [0x1E1] = "Divine Veil", + [0x1E2] = "Assassin", + [0x1E3] = "Aura Steal", + [0x1E4] = "Ambush", + [0x1E5] = "Shield Mastery", + [0x1E6] = "Iron Will", + [0x1E7] = "Guardian", + [0x1E8] = "Muted Soul", + [0x1E9] = "Desperate Blows", + [0x1EA] = "Carrot Broth", + [0x1EB] = "Herbal Broth", + [0x1EC] = "Fish Broth", + [0x1ED] = "Alchemist's Water", + [0x1EE] = "Meat Broth", + [0x1EF] = "Bug Broth", + [0x1F0] = "Carrion Broth", + [0x1F1] = "Seedbed Soil", + [0x1F2] = "Tree Sap", + [0x1F3] = "Beast Affinity", + [0x1F4] = "Beast Healer", + [0x1F5] = "Alertness", + [0x1F6] = "Recycle", + [0x1F7] = "Rapid Shot", + [0x1F8] = "Snapshot", + [0x1F9] = "Zanshin", + [0x1FA] = "Overwhelm", + [0x1FB] = "Ikishoten", + [0x1FC] = "Stealth", + [0x1FD] = "Dual Wield", + [0x1FE] = "Ninja Tool Expertise", + [0x1FF] = "Ninja Tool Supply", } - - - - - -- TOOLS FOR HANDLING EXTDATA tools = {} From 57c8694c888480b127e00b25a0bd8b5a4ef9150e Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Mon, 21 Jun 2021 12:54:46 +0100 Subject: [PATCH 0667/1002] Update --- addons/macrochanger/macrochanger.lua | 244 +++++++++++++-------------- 1 file changed, 122 insertions(+), 122 deletions(-) diff --git a/addons/macrochanger/macrochanger.lua b/addons/macrochanger/macrochanger.lua index 51954d8b5f..1d9aac7bc4 100644 --- a/addons/macrochanger/macrochanger.lua +++ b/addons/macrochanger/macrochanger.lua @@ -26,143 +26,143 @@ _addon.name = 'MacroChanger' _addon.author = 'Banggugyangu' -_addon.version = '1.0.0.2' +_addon.version = '1.0.0.1' _addon.commands = {'mc','macrochanger'} require('strings') +require('logger') windower.register_event('load', function() - globaldisable = 0 - macros = { - WAR = {Book = '', Page = ''}, - MNK = {Book = '', Page = ''}, - WHM = {Book = '', Page = ''}, - BLM = {Book = '', Page = ''}, - RDM = {Book = '', Page = ''}, - THF = {Book = '', Page = ''}, - PLD = {Book = '', Page = ''}, - DRK = {Book = '', Page = ''}, - BST = {Book = '', Page = ''}, - BRD = {Book = '', Page = ''}, - RNG = {Book = '', Page = ''}, - SAM = {Book = '', Page = ''}, - NIN = {Book = '', Page = ''}, - DRG = {Book = '', Page = ''}, - SMN = {Book = '', Page = ''}, - BLU = {Book = '', Page = ''}, - COR = {Book = '', Page = ''}, - PUP = {Book = '', Page = ''}, - DNC = {Book = '', Page = ''}, - SCH = {Book = '', Page = ''}, - GEO = {Book = '', Page = ''}, - RUN = {Book = '', Page = ''}, - } - options_load() + globaldisable = 0 + macros = { + WAR = {Book = '', Page = ''}, + MNK = {Book = '', Page = ''}, + WHM = {Book = '', Page = ''}, + BLM = {Book = '', Page = ''}, + RDM = {Book = '', Page = ''}, + THF = {Book = '', Page = ''}, + PLD = {Book = '', Page = ''}, + DRK = {Book = '', Page = ''}, + BST = {Book = '', Page = ''}, + BRD = {Book = '', Page = ''}, + RNG = {Book = '', Page = ''}, + SAM = {Book = '', Page = ''}, + NIN = {Book = '', Page = ''}, + DRG = {Book = '', Page = ''}, + SMN = {Book = '', Page = ''}, + BLU = {Book = '', Page = ''}, + COR = {Book = '', Page = ''}, + PUP = {Book = '', Page = ''}, + DNC = {Book = '', Page = ''}, + SCH = {Book = '', Page = ''}, + GEO = {Book = '', Page = ''}, + RUN = {Book = '', Page = ''}, + } + options_load() end) function options_load() - local f = io.open(windower.addon_path..'data/settings.txt', "r") - if f == nil then - local g = io.open(windower.addon_path..'data/settings.txt', "w") - g:write('Release Date: 9:00 PM, 4-01-13\46\n') - g:write('Author Comment: This document is whitespace sensitive, which means that you need the same number of spaces between things as exist in this initial settings file\46\n') - g:write('Author Comment: It looks at the first two words separated by spaces and then takes anything as the value in question if the first two words are relevant\46\n') - g:write('Author Comment: If you ever mess it up so that it does not work, you can just delete it and MacroChanger will regenerate it upon reload\46\n') - g:write('Author Comment: For the output customization lines, simply place the book and page number that you would like to change to upon a job change.\46\n') - g:write('Author Comment: If 2 jobs share a book, you can place the same book number for each job, then put their individual pages.\46\n') - g:write('Author Comment: Example: BLM and SCH both use Macro Book 2: BLM uses page 3. SCH uses page 1.\46\n') - g:write('Author Comment: Put BLM Book: 2, BLM Page: 3, SCH Book: 2, SCH Page: 1.\46\n') - g:write('Author Comment: If you wish to disable auto-macro Changing for a specific job, type "disabled" instead of a book number. (e.g. BLM Book: disabled)\n') - g:write('Author Comment: The design of the settings file is credited to Byrthnoth as well as the creation of the settings file.\n\n\n') - g:write('File Settings: Fill in below\n') - g:write('Disable All: 0\n') - g:write('WAR Book: 1\nWAR Page: 1\nMNK Book: 2\nMNK Page: 1\nWHM Book: 3\nWHM Page: 1\nBLM Book: 4\nBLM Page: 1\nRDM Book: 5\nRDM Page: 1\nTHF Book: 6\nTHF Page: 1\n') - g:write('PLD Book: 7\nPLD Page: 1\nDRK Book: 8\nDRK Page: 1\nBST Book: 9\nBST Page: 1\nBRD Book: 10\nBRD Page: 1\nRNG Book: 11\nRNG Page: 1\nSAM Book: 12\nSAM Page: 1\n') - g:write('NIN Book: 13\nNIN Page: 1\nDRG Book: 14\nDRG Page: 1\nSMN Book: 15\nSMN Page: 1\nBLU Book: 16\nBLU Page: 1\nCOR Book: 17\nCOR Page: 1\nPUP Book: 18\nPUP Page: 1\n') - g:write('DNC Book: 19\nDNC Page: 1\nSCH Book: 20\nSCH Page: 1\nGEO Book: 20\nGEO Page: 1\nRUN Book: 20\nRUN Page: 1\n') - g:close() - DisableAll = 0 - macros = { - WAR = {Book = '1', Page = '1'}, - MNK = {Book = '2', Page = '1'}, - WHM = {Book = '3', Page = '1'}, - BLM = {Book = '4', Page = '1'}, - RDM = {Book = '5', Page = '1'}, - THF = {Book = '6', Page = '1'}, - PLD = {Book = '7', Page = '1'}, - DRK = {Book = '8', Page = '1'}, - BST = {Book = '9', Page = '1'}, - BRD = {Book = '10', Page = '1'}, - RNG = {Book = '11', Page = '1'}, - SAM = {Book = '12', Page = '1'}, - NIN = {Book = '13', Page = '1'}, - DRG = {Book = '14', Page = '1'}, - SMN = {Book = '15', Page = '1'}, - BLU = {Book = '16', Page = '1'}, - COR = {Book = '17', Page = '1'}, - PUP = {Book = '18', Page = '1'}, - DNC = {Book = '19', Page = '1'}, - SCH = {Book = '20', Page = '1'}, - GEO = {Book = '20', Page = '1'}, - RUN = {Book = '20', Page = '1'}, - } - print('Default settings file created') - windower.add_to_chat(12,'MacroChanger created a settings file and loaded!') - else - f:close() - for curline in io.lines(windower.addon_path..'data/settings.txt') do - local splat = curline:gsub(':',''):split(' ') - local cmd = '' - if splat[1] and macros[splat[1]:upper()] and splat[2] ~=nil and (splat[2]:lower() == 'book' or splat[2]:lower() == 'page') and splat[3] then - macros[splat[1]:upper()][splat[2]:ucfirst()] = splat[3] -- Instead of a number, this can also be 'disabled' - elseif splat[1] and splat[2] and (splat[1]..' '..splat[2]) == 'disable all' and tonumber(splat[3]) then - globaldisable = tonumber(splat[3]) - end - end - windower.add_to_chat(12,'MacroChanger read from a settings file and loaded!') - end + local f = io.open(windower.addon_path..'data/settings.txt', "r") + if f == nil then + local g = io.open(windower.addon_path..'data/settings.txt', "w") + g:write('Release Date: 9:00 PM, 4-01-13\46\n') + g:write('Author Comment: This document is whitespace sensitive, which means that you need the same number of spaces between things as exist in this initial settings file\46\n') + g:write('Author Comment: It looks at the first two words separated by spaces and then takes anything as the value in question if the first two words are relevant\46\n') + g:write('Author Comment: If you ever mess it up so that it does not work, you can just delete it and MacroChanger will regenerate it upon reload\46\n') + g:write('Author Comment: For the output customization lines, simply place the book and page number that you would like to change to upon a job change.\46\n') + g:write('Author Comment: If 2 jobs share a book, you can place the same book number for each job, then put their individual pages.\46\n') + g:write('Author Comment: Example: BLM and SCH both use Macro Book 2: BLM uses page 3. SCH uses page 1.\46\n') + g:write('Author Comment: Put BLM Book: 2, BLM Page: 3, SCH Book: 2, SCH Page: 1.\46\n') + g:write('Author Comment: If you wish to disable auto-macro Changing for a specific job, type "disabled" instead of a book number. (e.g. BLM Book: disabled)\n') + g:write('Author Comment: The design of the settings file is credited to Byrthnoth as well as the creation of the settings file.\n\n\n') + g:write('File Settings: Fill in below\n') + g:write('Disable All: 0\n') + g:write('WAR Book: 1\nWAR Page: 1\nMNK Book: 2\nMNK Page: 1\nWHM Book: 3\nWHM Page: 1\nBLM Book: 4\nBLM Page: 1\nRDM Book: 5\nRDM Page: 1\nTHF Book: 6\nTHF Page: 1\n') + g:write('PLD Book: 7\nPLD Page: 1\nDRK Book: 8\nDRK Page: 1\nBST Book: 9\nBST Page: 1\nBRD Book: 10\nBRD Page: 1\nRNG Book: 11\nRNG Page: 1\nSAM Book: 12\nSAM Page: 1\n') + g:write('NIN Book: 13\nNIN Page: 1\nDRG Book: 14\nDRG Page: 1\nSMN Book: 15\nSMN Page: 1\nBLU Book: 16\nBLU Page: 1\nCOR Book: 17\nCOR Page: 1\nPUP Book: 18\nPUP Page: 1\n') + g:write('DNC Book: 19\nDNC Page: 1\nSCH Book: 20\nSCH Page: 1\nGEO Book: 20\nGEO Page: 1\nRUN Book: 20\nRUN Page: 1\n') + g:close() + DisableAll = 0 + macros = { + WAR = {Book = '1', Page = '1'}, + MNK = {Book = '2', Page = '1'}, + WHM = {Book = '3', Page = '1'}, + BLM = {Book = '4', Page = '1'}, + RDM = {Book = '5', Page = '1'}, + THF = {Book = '6', Page = '1'}, + PLD = {Book = '7', Page = '1'}, + DRK = {Book = '8', Page = '1'}, + BST = {Book = '9', Page = '1'}, + BRD = {Book = '10', Page = '1'}, + RNG = {Book = '11', Page = '1'}, + SAM = {Book = '12', Page = '1'}, + NIN = {Book = '13', Page = '1'}, + DRG = {Book = '14', Page = '1'}, + SMN = {Book = '15', Page = '1'}, + BLU = {Book = '16', Page = '1'}, + COR = {Book = '17', Page = '1'}, + PUP = {Book = '18', Page = '1'}, + DNC = {Book = '19', Page = '1'}, + SCH = {Book = '20', Page = '1'}, + GEO = {Book = '20', Page = '1'}, + RUN = {Book = '20', Page = '1'}, + } + print('Default settings file created') + notice('MacroChanger created a settings file and loaded!') + else + f:close() + for curline in io.lines(windower.addon_path..'data/settings.txt') do + local splat = curline:gsub(':',''):split(' ') + local cmd = '' + if splat[1] and macros[splat[1]:upper()] and splat[2] ~=nil and (splat[2]:lower() == 'book' or splat[2]:lower() == 'page') and splat[3] then + macros[splat[1]:upper()][splat[2]:ucfirst()] = splat[3] -- Instead of a number, this can also be 'disabled' + elseif splat[1] and splat[2] and (splat[1]..' '..splat[2]) == 'disable all' and tonumber(splat[3]) then + globaldisable = tonumber(splat[3]) + end + end + notice('MacroChanger read from a settings file and loaded!') + end end windower.register_event('job change',function () -- Could use the job ID passed into this function, but the addon would have to include the resources library - local job = windower.ffxi.get_player().main_job - local book = '' - local page = '' - if globaldisable == 0 then + local job = windower.ffxi.get_player().main_job + local book = '' + local page = '' + if globaldisable == 0 then if job and macros[job] then - book = macros[job].Book - page = macros[job].Page - end - - if ((book == 'disabled') or (page == 'disabled')) then - windower.add_to_chat(17, ' Auto Macro Switching Disabled for ' .. job ..'.') - else - windower.add_to_chat(17, ' Changing macros to Book: ' .. book .. ' and Page: ' .. page .. '. Job Changed to ' .. job) - windower.send_command('wait 1;input /macro book '..book..';wait 1.2;input /macro set '..page..';') - end - elseif globaldisable == 1 then - - windower.add_to_chat(17, ' Auto Macro Switching Disabled for All Jobs.') - - end + book = macros[job].Book + page = macros[job].Page + end + if ((book == 'disabled') or (page == 'disabled')) then + notice('Auto Macro Switching Disabled for ' .. job ..'.') + else + log('Job changed to ' .. job .. ' - switched to Book: ' .. book .. ' and Page: ' .. page) + windower.chat.input('/macro book ' .. book) + coroutine.sleep(1.2) + windower.chat.input('/macro set ' .. page) + end + elseif globaldisable == 1 then + notice('Auto Macro Switching Disabled for All Jobs.') + end end) windower.register_event('addon command', function(...) local args = {...} - local mjob = windower.ffxi.get_player().main_job - if args[1] == 'disableall' then - if args[2] == 'on' then - globaldisable = 1 - windower.add_to_chat(17, 'All automated macro switching disabled.') - elseif args[2] == 'off' then - globaldisable = 0 - windower.add_to_chat(17, 'Automated macro switching enabled.') - end - elseif args[1]:lower() == 'help' then - windower.add_to_chat(17, 'MacroChanger Commands:') - windower.add_to_chat(17, 'disableall [on|off]') - windower.add_to_chat(17, ' on - Disables all automated macro switching') - windower.add_to_chat(17, ' off - Enables all automated macro switching not disabled individually') - windower.add_to_chat(17, ' Resets to what is stored in settings upon unloading of addon. To Permanently change, please change the option in the settings file.') - end + local mjob = windower.ffxi.get_player().main_job + if args[1] == 'disableall' then + if args[2] == 'on' then + globaldisable = 1 + notice('All automated macro switching disabled.') + elseif args[2] == 'off' then + globaldisable = 0 + notice('Automated macro switching enabled.') + end + elseif args[1]:lower() == 'help' then + log('MacroChanger Commands:') + log('disableall [on|off]') + log(' on - Disables all automated macro switching') + log(' off - Enables all automated macro switching not disabled individually') + log('Resets to what is stored in settings upon unloading of addon. To Permanently change, please change the option in the settings file.') + end end) From 7fcd3b8e792b11676ebaf4a9adf39154f5e04a1c Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Mon, 21 Jun 2021 12:56:41 +0100 Subject: [PATCH 0668/1002] Same fix, in mote libraries --- addons/GearSwap/libs/Mote-Utility.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/GearSwap/libs/Mote-Utility.lua b/addons/GearSwap/libs/Mote-Utility.lua index 12834d3e6a..ad7a0ffebe 100644 --- a/addons/GearSwap/libs/Mote-Utility.lua +++ b/addons/GearSwap/libs/Mote-Utility.lua @@ -527,7 +527,7 @@ function set_macro_page(set,book) add_to_chat(123,'Error setting macro page: Macro book ('..tostring(book)..') must be between 1 and 20.') return end - send_command('@input /macro book '..tostring(book)..';wait .1;input /macro set '..tostring(set)) + send_command('@input /macro book '..tostring(book)..';wait 1.1;input /macro set '..tostring(set)) else send_command('@input /macro set '..tostring(set)) end From 78dfccaa6f2451b2e90b993e281ddf70b168674e Mon Sep 17 00:00:00 2001 From: Chiaia Date: Mon, 12 Jul 2021 11:54:44 -0400 Subject: [PATCH 0669/1002] July 11th, 2021 Update --- addons/boxdestroyer/messages.lua | 42 ++++++++++++++++---------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/addons/boxdestroyer/messages.lua b/addons/boxdestroyer/messages.lua index dd8de669c0..87be19465a 100644 --- a/addons/boxdestroyer/messages.lua +++ b/addons/boxdestroyer/messages.lua @@ -12,36 +12,36 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination [110] = 7611, [111] = 8588, [112] = 8190, - [113] = 7929, - [114] = 7786, + [113] = 7932, + [114] = 7789, [115] = 7885, [116] = 7581, [117] = 7588, [118] = 8130, [119] = 8367, [120] = 7527, - [121] = 8104, - [122] = 7435, - [123] = 7887, - [124] = 7838, - [125] = 7648, + [121] = 8107, + [122] = 7438, + [123] = 7890, + [124] = 7841, + [125] = 7651, [126] = 8074, [127] = 7355, - [128] = 7507, - [130] = 7571, - [153] = 11397, + [128] = 7510, + [130] = 7574, + [153] = 11400, [158] = 7386, - [159] = 8446, - [160] = 7410, + [159] = 8449, + [160] = 7413, [166] = 10582, [167] = 10596, [169] = 7543, [172] = 7416, - [173] = 10518, - [174] = 11396, - [176] = 7605, - [177] = 11220, - [178] = 11400, + [173] = 10521, + [174] = 11399, + [176] = 7608, + [177] = 11223, + [178] = 11403, [190] = 8257, [191] = 8377, [192] = 7413, @@ -53,9 +53,9 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination [198] = 8275, [200] = 7531, [204] = 7519, - [205] = 11483, - [208] = 8285, - [212] = 10639, - [213] = 10449, + [205] = 11486, + [208] = 8288, + [212] = 10642, + [213] = 10452, } offsets = {greater_less=1, failure=2, success=4, second_even_odd=5, first_even_odd=6, range=7, less=8, greater=9, equal=10, second_multiple=11, first_multiple=12, tool_failure=13} From 492797bf2a568d6c9d5ecdb91ddc74c8907ff23f Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Mon, 12 Jul 2021 21:36:37 +0200 Subject: [PATCH 0670/1002] Update thtracker.lua Update th tracker to use packets instead of text --- addons/thtracker/thtracker.lua | 73 +++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 27 deletions(-) diff --git a/addons/thtracker/thtracker.lua b/addons/thtracker/thtracker.lua index e3be843640..063a770aa5 100644 --- a/addons/thtracker/thtracker.lua +++ b/addons/thtracker/thtracker.lua @@ -27,11 +27,12 @@ _addon.name = 'THTracker' _addon.author = 'Krizz' -_addon.version = 1.1 +_addon.version = 1.2 _addon.commands = {'thtracker', 'th'} config = require ('config') texts = require ('texts') +packets = require('packets') require('logger') defaults = {} @@ -51,7 +52,9 @@ defaults.bg.blue = 30 settings = config.load(defaults) -th = texts.new('No current mob', settings) +th = texts.new('${th_string}', settings) + +local th_table = {} windower.register_event('addon command', function(command, ...) command = command and command:lower() @@ -74,33 +77,49 @@ windower.register_event('addon command', function(command, ...) end end) -windower.register_event('incoming text', function(original, new, color) - original = original:strip_format() - local name, count = original:match('Additional effect: Treasure Hunter effectiveness against[%s%a%a%a]- (.*) increases to (%d+).') - - if name and count then - name = name.gsub(name, "the ", "") - mob = name - th:text(' '..name..'\n TH: '..count); - th:show() +windower.register_event('incoming chunk', function(id, data) + if id == 0x028 then + local packet = packets.parse('incoming', data) + if packet.Category == 1 and packet['Target 1 Action 1 Has Added Effect'] and packet['Target 1 Action 1 Added Effect Message'] == 603 then + th_table[packet['Target 1 ID']] = 'TH: '..packet['Target 1 Action 1 Added Effect Param'] + update_text() + elseif packet.Category == 3 and packet['Target 1 Action 1 Message'] == 608 then + th_table[packet['Target 1 ID']] = 'TH: '..packet['Target 1 Action 1 Param'] + update_text() + end + elseif id == 0x038 then + local packet = packets.parse('incoming', data) + if th_table[packet['Mob']] and packet['Type'] == 'kesu' then + th_table[packet['Mob']] = nil + update_text() + end + elseif id == 0x00E then + local packet = packets.parse('incoming', data) + if th_table[packet['NPC']] and packet['Status'] == 0 and packet['HP %'] == 100 then + th_table[packet['NPC']] = nil + update_text() + end end +end) - local deadmob = original:match('%w+ defeats[%s%a%a%a]- (.*).') - - if deadmob then - deadmob = deadmob.gsub(deadmob, "the ", "") - end - - if deadmob == mob then - - th:text('No current mob') - th:hide() - mob = nil - end +windower.register_event('zone change', function() + th_table = {} + update_text() +end) +windower.register_event('target change', function() + update_text() end) -windower.register_event('zone change', function() - th:text('No current mob') - th:hide() -end) \ No newline at end of file +function update_text() + local current_string + local target = windower.ffxi.get_mob_by_target('st') or windower.ffxi.get_mob_by_target('t') + if target and th_table[target.id] then + current_string = target.name..'\n '..th_table[target.id] + th:show() + else + current_string = '' + th:hide() + end + th.th_string = current_string +end From 789f37b826add86a650d2e55633d9ea5fa3a27c6 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Mon, 12 Jul 2021 22:15:36 +0200 Subject: [PATCH 0671/1002] Battlemod update Several updates and fixes. --- addons/battlemod/battlemod.lua | 22 +++++++++++-- addons/battlemod/parse_action_packet.lua | 39 +++++++++++------------ addons/battlemod/statics.lua | 40 +++++++++++++++++++++++- 3 files changed, 77 insertions(+), 24 deletions(-) diff --git a/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index 904570df19..5ae3426899 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -12,7 +12,7 @@ require 'generic_helpers' require 'parse_action_packet' require 'statics' -_addon.version = '3.30' +_addon.version = '3.31' _addon.name = 'BattleMod' _addon.author = 'Byrth, maintainer: SnickySnacks' _addon.commands = {'bm','battlemod'} @@ -76,6 +76,18 @@ windower.register_event('addon command', function(command, ...) 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 = '' @@ -112,6 +124,10 @@ windower.register_event('addon command', function(command, ...) 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') @@ -127,7 +143,7 @@ windower.register_event('incoming text',function (original, modified, color, col a,z = string.find(original,'Equipment changed') if a and not block_equip then - windower.send_command('@wait 1;lua i battlemod flip_block_equip') + flip_block_equip:schedule(1) block_equip = true elseif a and block_equip then modified = true @@ -138,7 +154,7 @@ windower.register_event('incoming text',function (original, modified, color, col 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 - windower.send_command('@wait 1;lua i battlemod flip_block_cannot') + flip_block_cannot:schedule(1) block_cannot = true elseif (a or b or c) and block_cannot then modified = true diff --git a/addons/battlemod/parse_action_packet.lua b/addons/battlemod/parse_action_packet.lua index 89c21c22f3..05cfd36011 100644 --- a/addons/battlemod/parse_action_packet.lua +++ b/addons/battlemod/parse_action_packet.lua @@ -54,7 +54,7 @@ function parse_action_packet(act) 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,2,4}:contains(m.effect) and S{0,2,4}:contains(r.effect)) then -- combine kicks and crits + 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 @@ -303,23 +303,11 @@ function parse_action_packet(act) 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 S{1,3,4,6,11,13,14,15}:contains(act.category) and (bit.band(m.unknown,1)==1 and 'Cover! ' or '') - ..(bit.band(m.unknown,4)==4 and 'Magic Burst! ' or '') --Used on Swipe/Lunge MB - ..(bit.band(m.unknown,8)==8 and 'Immunobreak! ' or '') --Unused? Displayed directly on message - ..(bit.band(m.unknown,16)==16 and 'Critical Hit! ' or '') --Unused? Crits have their own message - ..(reaction_lookup == 4 and 'Blocked! ' or '') - ..(reaction_lookup == 2 and 'Guarded! ' or '') - ..(reaction_lookup == 3 and S{3,4,6,11,13,14,15}:contains(act.category) and 'Parried! ' or '') or '' --Unused? They are send the same as missed - local prefix2 = has_line_break and S{1,3,4,6,11,13,14,15}:contains(act.category) and (bit.band(m.unknown,1)==1 and 'Cover! ' or '') - ..(bit.band(m.unknown,2)==2 and 'Resist! ' or '') - ..(bit.band(m.unknown,4)==4 and 'Magic Burst! ' or '') --Used on Swipe/Lunge MB - ..(bit.band(m.unknown,8)==8 and 'Immunobreak! ' or '') --Unused? Displayed directly on message - ..(bit.band(m.unknown,16)==16 and 'Critical Hit! ' or '') --Unused? Crits have their own message - ..(reaction_lookup == 4 and 'Blocked! ' or '') - ..(reaction_lookup == 2 and 'Guarded! ' or '') - ..(reaction_lookup == 3 and S{3,4,6,11,13,14,15}:contains(act.category) and 'Parried! ' or '') or '' --Unused? They are send the same as missed + 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)) @@ -327,13 +315,13 @@ function parse_action_packet(act) :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 or 'ERROR 116') + :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) + :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 @@ -654,7 +642,7 @@ function player_info(id) if not filt then if player_table.is_npc then - if player_table.index>1791 then + if player_table.index>1791 or player_table.charmed then typ = 'other_pets' filt = 'other_pets' owner = 'other' @@ -712,7 +700,7 @@ function player_info(id) end end if not typ then typ = 'debug' end - return {name=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} + 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) @@ -908,6 +896,17 @@ function color_filt(col,is_me) 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 = {} diff --git a/addons/battlemod/statics.lua b/addons/battlemod/statics.lua index 17021d9b0d..f701720688 100644 --- a/addons/battlemod/statics.lua +++ b/addons/battlemod/statics.lua @@ -99,6 +99,40 @@ replacements_map = { } } +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 @@ -170,7 +204,7 @@ default_settings_table = {line_aoe = 'AOE ${numb} '..string.char(129,168). 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,} + 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 @@ -596,6 +630,10 @@ default_settings = [[ true false true + true + true + false + false AOE ${numb} ]]..string.char(129,168)..[[ ${target} ${actor} ${abil} ]]..string.char(129,168)..[[ ${target} (${status}) [${actor}] ${numb} ${abil} ]]..string.char(129,168)..[[ ${target} From 316715882941960af021511ddfb34fe463068f46 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Tue, 13 Jul 2021 13:17:14 +0200 Subject: [PATCH 0672/1002] Update statics.lua Changed to single quotes --- addons/battlemod/statics.lua | 62 ++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/addons/battlemod/statics.lua b/addons/battlemod/statics.lua index f701720688..8abe43eb63 100644 --- a/addons/battlemod/statics.lua +++ b/addons/battlemod/statics.lua @@ -100,37 +100,37 @@ replacements_map = { } 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 + [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{ From a03b322358366bccafc8e7be124cb2e2ec2c8474 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Tue, 13 Jul 2021 14:19:07 +0200 Subject: [PATCH 0673/1002] Update slips.lua Adding Leafkin Bed --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 12cb8bfd6d..de0e188931 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757, 25909}, -- 192 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066}, -- 137 SE Skipped an index hence the 0 as one of the items + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748}, -- 138 SE Skipped an index hence the 0 as one of the items [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770}, --174 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, --115 From 85ff50e74d5b2e6afa88e51846ecddf66ff72fe9 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Thu, 15 Jul 2021 17:34:45 -0600 Subject: [PATCH 0674/1002] Linkshell name and color fixes --- addons/libs/extdata.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/libs/extdata.lua b/addons/libs/extdata.lua index aeae471c95..0537a4375e 100644 --- a/addons/libs/extdata.lua +++ b/addons/libs/extdata.lua @@ -1823,15 +1823,15 @@ function decode.Linkshell(str) end local name_map = {[0]="'",[1]="a",[2]='b',[3]='c',[4]='d',[5]='e',[6]='f',[7]='g',[8]='h',[9]='i',[10]='j', [11]='k',[12]='l',[13]='m',[14]='n',[15]='o',[16]='p',[17]='q',[18]='r',[19]='s',[20]='t',[21]='u',[22]='v',[23]='w', - [24]='x',[25]='yx',[26]='z',[27]='A',[28]='B',[29]='C',[30]='D',[31]='E',[32]='F',[33]='G',[34]='H',[35]='I',[36]='J', + [24]='x',[25]='y',[26]='z',[27]='A',[28]='B',[29]='C',[30]='D',[31]='E',[32]='F',[33]='G',[34]='H',[35]='I',[36]='J', [37]='K',[38]='L',[39]='M',[40]='N',[41]='O',[42]='P',[43]='Q',[44]='R',[45]='S',[46]='T',[47]='U',[48]='V',[49]='W', [50]='X',[51]='Y',[52]='Z' } local rettab = {type = 'Linkshell', linkshell_id = str:unpack('I'), - r = 17*str:byte(7)%16, + r = 17*(str:byte(7)%16), g = 17*math.floor(str:byte(7)/16), - b = 17*str:byte(8)%16, + b = 17*(str:byte(8)%16), status_id = str:byte(9), status = status_map[str:byte(9)]} From 2e6f9b649ef253e5158f7a3a99278c9e05b530cb Mon Sep 17 00:00:00 2001 From: Ian Anderson Date: Fri, 16 Jul 2021 20:59:54 -0700 Subject: [PATCH 0675/1002] Update roe.lua See discord message --- addons/roe/roe.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/addons/roe/roe.lua b/addons/roe/roe.lua index 6202066ad8..4de822afe5 100644 --- a/addons/roe/roe.lua +++ b/addons/roe/roe.lua @@ -206,8 +206,12 @@ local function blacklist(add_remove,id) settings.blacklist:add(id) notice('roe quest %d added to the blacklist':format(id)) elseif add_remove == 'remove' then - settings.blacklist:remove(id) - notice('roe quest %d removed from the blacklist':format(id)) + if not id >= 4008 and not id <= 4021 then + return + else + settings.blacklist:remove(id) + notice('roe quest %d removed from the blacklist':format(id)) + end else error('`blacklist` specify \'add\' or \'remove\'') end From 8c7d7b400b4896d8c86ec1cd2126cd80dc0cf85e Mon Sep 17 00:00:00 2001 From: Ian Anderson Date: Fri, 16 Jul 2021 21:07:38 -0700 Subject: [PATCH 0676/1002] Update roe.lua --- addons/roe/roe.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/roe/roe.lua b/addons/roe/roe.lua index 4de822afe5..5d27429125 100644 --- a/addons/roe/roe.lua +++ b/addons/roe/roe.lua @@ -206,7 +206,7 @@ local function blacklist(add_remove,id) settings.blacklist:add(id) notice('roe quest %d added to the blacklist':format(id)) elseif add_remove == 'remove' then - if not id >= 4008 and not id <= 4021 then + if id >= 4008 and id <= 4021 then return else settings.blacklist:remove(id) From d2832254e4ff1433f7aab1821b673a1f78f4a6f5 Mon Sep 17 00:00:00 2001 From: Ian Anderson Date: Sat, 17 Jul 2021 05:01:27 -0700 Subject: [PATCH 0677/1002] Update roe.lua --- addons/roe/roe.lua | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/addons/roe/roe.lua b/addons/roe/roe.lua index 5d27429125..236073c36a 100644 --- a/addons/roe/roe.lua +++ b/addons/roe/roe.lua @@ -27,7 +27,7 @@ _addon = {} _addon.name = 'ROE' -_addon.version = '1.0' +_addon.version = '1.1' _addon.author = "Cair" _addon.commands = {'roe'} @@ -206,12 +206,12 @@ local function blacklist(add_remove,id) settings.blacklist:add(id) notice('roe quest %d added to the blacklist':format(id)) elseif add_remove == 'remove' then - if id >= 4008 and id <= 4021 then - return - else - settings.blacklist:remove(id) - notice('roe quest %d removed from the blacklist':format(id)) - end + if id >= 4008 and id <= 4021 then + return + else + settings.blacklist:remove(id) + notice('roe quest %d removed from the blacklist':format(id)) + end else error('`blacklist` specify \'add\' or \'remove\'') end From 8c7b1aab352dffecb09118617ba05956a6f3ec2d Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sat, 17 Jul 2021 17:00:55 +0100 Subject: [PATCH 0678/1002] Added Nomad Moogle check. Check for Nomad/Pilgrim Moogles at the start of the command. Added appropriate debug notices. --- addons/organizer/organizer.lua | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/addons/organizer/organizer.lua b/addons/organizer/organizer.lua index 9abb43f043..a3c3107c89 100644 --- a/addons/organizer/organizer.lua +++ b/addons/organizer/organizer.lua @@ -35,6 +35,7 @@ require 'lists' require 'functions' config = require 'config' slips = require 'slips' +packets = require 'packets' _addon.name = 'Organizer' _addon.author = 'Byrth, maintainer: Rooks' @@ -243,6 +244,11 @@ windower.register_event('addon command',function(...) return end + local moogle = nomad_moogle() + if moogle then + org_debug("command","Using '" .. mog .. "' for Mog House interaction") + end + local bag = 'all' if inp[1] and (_static.bag_ids[inp[1]:lower()] or inp[1]:lower() == 'all') then bag = table.remove(inp,1):lower() @@ -299,6 +305,11 @@ windower.register_event('addon command',function(...) windower.send_command('input /heal') end + if moogle then + clear_moogle() + org_debug("command","Clearing '" .. moogle .. "' status") + end + org_debug("command", "Organizer complete") end) From 20a05162f456545476e8450d956d6588e0801546 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sat, 17 Jul 2021 17:02:32 +0100 Subject: [PATCH 0679/1002] Added poke to Nomad Moogles Initiate menu interaction with Moogles before using Mog House bags. --- addons/organizer/items.lua | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/addons/organizer/items.lua b/addons/organizer/items.lua index 3a1afea58d..ceaeb87d01 100644 --- a/addons/organizer/items.lua +++ b/addons/organizer/items.lua @@ -29,14 +29,30 @@ local items = {} local bags = {} local item_tab = {} -local nomad_moogle -local clear_moogles do local names = {'Nomad Moogle', 'Pilgrim Moogle'} local moogles = {} + local poked = false + local block_menu = false clear_moogles = function() moogles = {} + poked = false + end + + local poke_moogle = function(npc) + print('poking', npc.name) + local p = packets.new('outgoing', 0x1a, { + ["Target"] = npc.id, + ["Target Index"] = npc.index, + }) + poked = true + block_menu = true + packets.inject(p) + repeat + coroutine.sleep(0.4) + print('waitan') + until not block_menu end nomad_moogle = function() @@ -45,6 +61,7 @@ do local npcs = windower.ffxi.get_mob_list(name) for index in pairs(npcs) do table.insert(moogles,index) + print(name,index) end end end @@ -53,11 +70,22 @@ do for _, moo_index in ipairs(moogles) do local moo = windower.ffxi.get_mob_by_index(moo_index) if moo and (moo.x - player.x)^2 + (moo.y - player.y)^2 < 36 then - return true + if not poked then + poke_moogle(moo) + end + return moo.name end end return false end + + windower.register_event('incoming chunk',function(id,data,modified,injected,blocked) + if id == 0x02E and block_menu then + print('moogle poked, menu blocked') + block_menu = false + return true + end + end) end windower.register_event('zone change',function() From e05ab958aa176f864753c33122a59c3d8e69780e Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sat, 17 Jul 2021 17:05:26 +0100 Subject: [PATCH 0680/1002] Removing leftover debug lines --- addons/organizer/items.lua | 4 ---- 1 file changed, 4 deletions(-) diff --git a/addons/organizer/items.lua b/addons/organizer/items.lua index ceaeb87d01..91b5d7950f 100644 --- a/addons/organizer/items.lua +++ b/addons/organizer/items.lua @@ -41,7 +41,6 @@ do end local poke_moogle = function(npc) - print('poking', npc.name) local p = packets.new('outgoing', 0x1a, { ["Target"] = npc.id, ["Target Index"] = npc.index, @@ -51,7 +50,6 @@ do packets.inject(p) repeat coroutine.sleep(0.4) - print('waitan') until not block_menu end @@ -61,7 +59,6 @@ do local npcs = windower.ffxi.get_mob_list(name) for index in pairs(npcs) do table.insert(moogles,index) - print(name,index) end end end @@ -81,7 +78,6 @@ do windower.register_event('incoming chunk',function(id,data,modified,injected,blocked) if id == 0x02E and block_menu then - print('moogle poked, menu blocked') block_menu = false return true end From 92abc7df459752a323dca6ee16884a3443db29d9 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sat, 17 Jul 2021 17:05:57 +0100 Subject: [PATCH 0681/1002] Typo fix --- addons/organizer/organizer.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/organizer/organizer.lua b/addons/organizer/organizer.lua index a3c3107c89..26f1917b1a 100644 --- a/addons/organizer/organizer.lua +++ b/addons/organizer/organizer.lua @@ -246,7 +246,7 @@ windower.register_event('addon command',function(...) local moogle = nomad_moogle() if moogle then - org_debug("command","Using '" .. mog .. "' for Mog House interaction") + org_debug("command","Using '" .. moogle .. "' for Mog House interaction") end local bag = 'all' From 5e21c855baa4b7ccef492e0f197d18dc8b08d251 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 18 Jul 2021 00:06:10 +0100 Subject: [PATCH 0682/1002] Commas --- addons/organizer/items.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/organizer/items.lua b/addons/organizer/items.lua index 91b5d7950f..126cde3f4e 100644 --- a/addons/organizer/items.lua +++ b/addons/organizer/items.lua @@ -76,7 +76,7 @@ do return false end - windower.register_event('incoming chunk',function(id,data,modified,injected,blocked) + windower.register_event('incoming chunk',function(id) if id == 0x02E and block_menu then block_menu = false return true From 253042c648f4d0b223a401e065579ce3674d26f2 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 18 Jul 2021 00:07:37 +0100 Subject: [PATCH 0683/1002] Parentheses and spaces --- addons/organizer/organizer.lua | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/addons/organizer/organizer.lua b/addons/organizer/organizer.lua index 26f1917b1a..56e67826fe 100644 --- a/addons/organizer/organizer.lua +++ b/addons/organizer/organizer.lua @@ -24,18 +24,18 @@ --(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS --SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -res = require 'resources' -files = require 'files' -require 'pack' -Items = require 'items' -extdata = require 'extdata' -logger = require 'logger' -require 'tables' -require 'lists' -require 'functions' -config = require 'config' -slips = require 'slips' -packets = require 'packets' +res = require('resources') +files = require('files') +require('pack') +Items = require('items') +extdata = require('extdata') +logger = require('logger') +require('tables') +require('lists') +require('functions') +config = require('config') +slips = require('slips') +packets = require('packets') _addon.name = 'Organizer' _addon.author = 'Byrth, maintainer: Rooks' @@ -246,7 +246,7 @@ windower.register_event('addon command',function(...) local moogle = nomad_moogle() if moogle then - org_debug("command","Using '" .. moogle .. "' for Mog House interaction") + org_debug("command", "Using '" .. moogle .. "' for Mog House interaction") end local bag = 'all' @@ -307,7 +307,7 @@ windower.register_event('addon command',function(...) if moogle then clear_moogle() - org_debug("command","Clearing '" .. moogle .. "' status") + org_debug("command", "Clearing '" .. moogle .. "' status") end org_debug("command", "Organizer complete") From 383f893e40de36f924123f6058d09e269b12f3dc Mon Sep 17 00:00:00 2001 From: Ian Anderson Date: Sat, 17 Jul 2021 22:07:02 -0700 Subject: [PATCH 0684/1002] Update roe.lua --- addons/roe/roe.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/roe/roe.lua b/addons/roe/roe.lua index 236073c36a..dfa7570c16 100644 --- a/addons/roe/roe.lua +++ b/addons/roe/roe.lua @@ -70,8 +70,9 @@ local function accept_roe(id) id = tonumber(id) if not id or _roe.complete[id] or _roe.active[id] then return end + if id and id >= 4008 and id <= 4021 then return end - local p = packets.new('outgoing', 0x10c, {['RoE Quest'] = id }) + local p = packets.new('outgoing', 0x10c, {['RoE Quest'] = id }) packets.inject(p) end From 06a5c6725cf55b2af606d0ab5cef0c2ca73fbebd Mon Sep 17 00:00:00 2001 From: Ian Anderson Date: Sat, 17 Jul 2021 22:09:05 -0700 Subject: [PATCH 0685/1002] Update roe.lua --- addons/roe/roe.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/roe/roe.lua b/addons/roe/roe.lua index dfa7570c16..49dd52d33e 100644 --- a/addons/roe/roe.lua +++ b/addons/roe/roe.lua @@ -72,7 +72,7 @@ local function accept_roe(id) if not id or _roe.complete[id] or _roe.active[id] then return end if id and id >= 4008 and id <= 4021 then return end - local p = packets.new('outgoing', 0x10c, {['RoE Quest'] = id }) + local p = packets.new('outgoing', 0x10c, {['RoE Quest'] = id }) packets.inject(p) end From dac29e9e09c04faebd52d6e25d2395ff100e3d6b Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Wed, 21 Jul 2021 20:13:33 +0100 Subject: [PATCH 0686/1002] Typo fix --- addons/organizer/organizer.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/organizer/organizer.lua b/addons/organizer/organizer.lua index 56e67826fe..7d772add38 100644 --- a/addons/organizer/organizer.lua +++ b/addons/organizer/organizer.lua @@ -306,7 +306,7 @@ windower.register_event('addon command',function(...) end if moogle then - clear_moogle() + clear_moogles() org_debug("command", "Clearing '" .. moogle .. "' status") end From 14a0ccf61b4bd9b91cd21c28cd0fee44924a41ce Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Thu, 22 Jul 2021 22:30:00 +0100 Subject: [PATCH 0687/1002] Version Bump --- addons/organizer/organizer.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/organizer/organizer.lua b/addons/organizer/organizer.lua index 7d772add38..8e526d9d8c 100644 --- a/addons/organizer/organizer.lua +++ b/addons/organizer/organizer.lua @@ -39,7 +39,7 @@ packets = require('packets') _addon.name = 'Organizer' _addon.author = 'Byrth, maintainer: Rooks' -_addon.version = 0.20210610 +_addon.version = 0.20210721 _addon.commands = {'organizer','org'} _static = { From 9e9377461b97d2e96de0c20075d04595b7cdd826 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Thu, 22 Jul 2021 22:32:53 +0100 Subject: [PATCH 0688/1002] Removed Pilgrim moogle Added a comment instructing users not to add Pilgrim Moogles manually, as it won't work. --- addons/organizer/items.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/organizer/items.lua b/addons/organizer/items.lua index 126cde3f4e..20d9160ae2 100644 --- a/addons/organizer/items.lua +++ b/addons/organizer/items.lua @@ -30,7 +30,7 @@ local bags = {} local item_tab = {} do - local names = {'Nomad Moogle', 'Pilgrim Moogle'} + local names = {'Nomad Moogle'} -- don't add Pilgrim Moogle to this list, organizer currently does not work in Odyssey. local moogles = {} local poked = false local block_menu = false From 98b83295fd5789735fedc6d6a1432cdd033bc1fe Mon Sep 17 00:00:00 2001 From: Chiaia Date: Thu, 22 Jul 2021 22:28:45 -0400 Subject: [PATCH 0689/1002] Very Small Update to the Max --- addons/scoreboard/scoreboard.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/scoreboard/scoreboard.lua b/addons/scoreboard/scoreboard.lua index 4a73530d36..0d5b280f5c 100644 --- a/addons/scoreboard/scoreboard.lua +++ b/addons/scoreboard/scoreboard.lua @@ -2,7 +2,7 @@ _addon.name = 'Scoreboard' _addon.author = 'Suji' -_addon.version = '1.12' +_addon.version = '1.13' _addon.commands = {'sb', 'scoreboard'} require('tables') @@ -69,6 +69,7 @@ end -- Handle addon args windower.register_event('addon command', function() + -- Hi Max, the way I see it, is you should have taken Rub's suggestion. local chatmodes = S{'s', 'l', 'l2', 'p', 't', 'say', 'linkshell', 'linkshell2', 'party', 'tell'} return function(command, ...) From 91b906bf1a70d8b2e0de913cb132a20f2cce4c18 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Mon, 26 Jul 2021 04:27:33 -0400 Subject: [PATCH 0690/1002] Added echo output as requested by a user. --- addons/scoreboard/scoreboard.lua | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/addons/scoreboard/scoreboard.lua b/addons/scoreboard/scoreboard.lua index 0d5b280f5c..893cefb641 100644 --- a/addons/scoreboard/scoreboard.lua +++ b/addons/scoreboard/scoreboard.lua @@ -2,7 +2,7 @@ _addon.name = 'Scoreboard' _addon.author = 'Suji' -_addon.version = '1.13' +_addon.version = '1.14' _addon.commands = {'sb', 'scoreboard'} require('tables') @@ -69,8 +69,7 @@ end -- Handle addon args windower.register_event('addon command', function() - -- Hi Max, the way I see it, is you should have taken Rub's suggestion. - local chatmodes = S{'s', 'l', 'l2', 'p', 't', 'say', 'linkshell', 'linkshell2', 'party', 'tell'} + local chatmodes = S{'s', 'l', 'l2', 'p', 't', 'say', 'linkshell', 'linkshell2', 'party', 'tell', 'echo'} return function(command, ...) if command == 'e' then From ac7d9cc8517115a23bed2b8cea2fbc455d40ff20 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Tue, 27 Jul 2021 09:47:26 +0200 Subject: [PATCH 0691/1002] Treasury: Added check for item validity --- addons/Treasury/Treasury.lua | 37 +++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/addons/Treasury/Treasury.lua b/addons/Treasury/Treasury.lua index 9f4b9f311d..dda4966de3 100644 --- a/addons/Treasury/Treasury.lua +++ b/addons/Treasury/Treasury.lua @@ -44,14 +44,21 @@ local flatten = function(s) end, S{}) end -local extract_ids = function(names) - return flatten(names:map(table.get+{all_ids} .. string.lower)) +local extract_ids = function(settings_table, key) + local valid = settings_table[key]:filter(function(name) + local found = all_ids[name:lower()] ~= nil + if not found then + print('Treasury: Item "%s" not found in %s list.':format(name, key)) + end + return found + end) + return flatten(valid:map(table.get+{all_ids} .. string.lower)) end config.register(settings, function(settings_table) - code.pass = extract_ids(settings_table.Pass) - code.lot = extract_ids(settings_table.Lot) - code.drop = extract_ids(settings_table.Drop) + code.pass = extract_ids(settings_table, 'Pass') + code.lot = extract_ids(settings_table, 'Lot') + code.drop = extract_ids(settings_table, 'Drop') end) lotpassdrop_commands = T{ @@ -143,13 +150,13 @@ end function find_id(name) if name == 'pool' then return pool_ids() - + elseif name == 'seals' then return S{1126, 1127, 2955, 2956, 2957} - + elseif name == 'currency' then return S{1449, 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457} - + elseif name == 'geodes' then return S{3297, 3298, 3299, 3300, 3301, 3302, 3303, 3304} @@ -161,16 +168,16 @@ function find_id(name) elseif name == 'detritus' then return S{9875, 9876} - + elseif name == 'heroism' then return S{9877, 9878} - + elseif name == 'moldy' then return S{9773, 9830, 9831, 9832, 9833, 9834, 9835, 9836, 9837, 9838, 9839, 9840, 9841, 9843, 9868, 9869, 9870, 9871, 9872, 9873, 9874} - + elseif name == 'dynad' then return S{9538, 9539, 9540, 9541, 9542, 9543, 9844, 9845} - + elseif name == 'papers' then return S{9544, 9545, 9546, 9547, 9548, 9549, 9550, 9551, 9552, 9553, 9554, 9555, 9556, 9557, 9558, 9559, 9560, 9561, 9562, 9563, 9564, 9565, 9566, 9567, 9568, 9569, 9570, 9571, 9572, 9573, 9574, 9575, 9576, 9577, 9578, 9579, 9580, 9581, 9582, 9583, 9584, 9585, 9586, 9587, 9588, 9589, 9590, 9591, 9592, 9593, 9594, 9595, 9596, 9597, 9598, 9599, 9600, 9601, 9602, 9603, 9604, 9605, 9606, 9607, 9608, 9609, 9610, 9611, 9612, 9613, 9614, 9615, 9616, 9617, 9618, 9619, 9620, 9621, 9622, 9623, 9624, 9625, 9626, 9627, 9628, 9629, 9630, 9631, 9632, 9633, 9634, 9635, 9636, 9637, 9638, 9639, 9640, 9641, 9642, 9643, 9644, 9645, 9646, 9647, 9648, 9649, 9650, 9651, 9652, 9653, 9654, 9655, 9656, 9657, 9658, 9659, 9660, 9661, 9662, 9663, 9664, 9665, 9666, 9667, 9668, 9669, 9670, 9671, 9672, 9673, 9674, 9675, 9676, 9677, 9678, 9679, 9680, 9681, 9682, 9683, 9684, 9685, 9686, 9687, 9688, 9689, 9690, 9691, 9692, 9693, 9694, 9695, 9696, 9697, 9698, 9699, 9700, 9701, 9702, 9703, 9704, 9705, 9706, 9707, 9708, 9709, 9710, 9711, 9712, 9713, 9714, 9715, 9716, 9717, 9718, 9719, 9720, 9721, 9722, 9723, 9724, 9725, 9726, 9727, 9728, 9729, 9730, 9731, 9732, 9733, 9734, 9735, 9736, 9737, 9738, 9739, 9740, 9741, 9742, 9743, 9744, 9745, 9746, 9747, 9748, 9749, 9750, 9751, 9752, 9753, 9754, 9755, 9756, 9757, 9758, 9759, 9760, 9761, 9762, 9763} @@ -280,12 +287,12 @@ windower.register_event('addon command', function(command1, command2, ...) end elseif command1 == 'passall' then - for slot_index, item_table in pairs(windower.ffxi.get_items().treasure) do + for slot_index, item_table in pairs(windower.ffxi.get_items().treasure) do windower.ffxi.pass_item(slot_index) end - + elseif command1 == 'lotall' then - for slot_index, item_table in pairs(windower.ffxi.get_items().treasure) do + for slot_index, item_table in pairs(windower.ffxi.get_items().treasure) do windower.ffxi.lot_item(slot_index) end From 47df5c2f15362e8c9666f6bdcfd31a70967d95bc Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Sat, 31 Jul 2021 21:02:36 +0200 Subject: [PATCH 0692/1002] Update fields.lua Update for incoming packet 0x075 --- addons/libs/packets/fields.lua | 38 ++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index dc6f21f22f..b542124e03 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -3160,14 +3160,48 @@ fields.incoming[0x070] = L{ } -- Unity Start --- Only observed being used for Unity fights. -fields.incoming[0x075] = L{ +-- Only observed being used for Unity fights. Also observed on DynaD and Odyssey for mask//weapon/neck/izzat progression bars. +func.incoming[0x075] = {} +fields.incoming[0x075] = function() + local fields = func.incoming[0x075] + + return function(data, type) + return fields.base + (fields[type or data:byte(0x025)] or fields.default) + end +end() + +enums[0x075] = { + [0] = 'No Timer', + [1] = 'Timer', + [2] = 'Bars', + [3] = 'Timer and Bars', +} + +types.bars = L{ + {ctype='unsigned char', label='Bar Progress'}, -- 28 0xFF if inactive + {ctype='data[3]', label='_unknown4'}, -- 29 Observed 0x000000 if active, 0xFFFFF7 if inactive + {ctype='char[16]', label='Bar String'}, -- 2C Bar 1 for mask/izzat | Bar 2 Main slot | Bar 3 Sub slot | Bar 4 Ranged slot | Bar 5 Neck slot +} + +func.incoming[0x075].base = L{ {ctype='unsigned int', label='Fight Designation'}, -- 04 Anything other than 0 makes a timer. 0 deletes the timer. {ctype='unsigned int', label='Timestamp Offset', fn=time}, -- 08 Number of seconds since 15:00:00 GMT 31/12/2002 (0x3C307D70) {ctype='unsigned int', label='Fight Duration', fn=time}, -- 0C {ctype='data[12]', label='_unknown1'}, -- 10 This packet clearly needs position information, but it's unclear how these bytes carry it {ctype='unsigned int', label='Battlefield Radius'}, -- 1C Yalms*1000, so a 50 yalm battlefield would have 50,000 for this field {ctype='unsigned int', label='Render Radius'}, -- 20 Yalms*1000, so a fence that renders when you're 25 yalms away would have 25,000 for this field + {ctype='unsigned char', label='Type', fn=e+{0x075}}, -- 24 most likely a bitflag where first bit activates the timer and bit 2 activates the bars +} + +func.incoming[0x075].default = L{ + {ctype='data[135]', label='_junk1'}, -- 28 Seems to be junk +} + +func.incoming[0x075][0x03] = L{ + {ctype='unsigned char', label='_unknown2'}, -- 25 + {ctype='unsigned short', label='_unknown3'}, -- 26 Value changes constatly + {ref=types.bars, count=5}, -- 28 + {ctype='data[32]', label='_unknown5'}, -- 8C } -- Party status icon update From b902a2422fe370d80b83b4175ce9a07e21c852a9 Mon Sep 17 00:00:00 2001 From: Ian Anderson Date: Wed, 4 Aug 2021 06:39:38 -0700 Subject: [PATCH 0693/1002] Update craft.lua --- addons/craft/craft.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/craft/craft.lua b/addons/craft/craft.lua index ba7693f89a..9751dd7587 100644 --- a/addons/craft/craft.lua +++ b/addons/craft/craft.lua @@ -1,5 +1,5 @@ --[[ -Craft v1.1.0 +Craft v1.1.3 Copyright © 2017 Mojo All rights reserved. @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'craft' _addon.author = 'Mojo, Recipes provided by BG-Wiki.com' -_addon.version = '1.1.2' +_addon.version = '1.1.3' _addon.commands = {'craft'} require('chat') From 9f957d7370d6f280aeb382446ff41e8351b32b2e Mon Sep 17 00:00:00 2001 From: Ian Anderson Date: Wed, 4 Aug 2021 06:40:38 -0700 Subject: [PATCH 0694/1002] Update README.md --- addons/craft/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/craft/README.md b/addons/craft/README.md index ed054005cb..64f29a739b 100644 --- a/addons/craft/README.md +++ b/addons/craft/README.md @@ -1,5 +1,5 @@ **Author:** Snaps
    -**Version:** 1.0
    +**Version:** 1.1.3
    **Date:** June 13th, 2017
    # craft # From 2254d61cbd4bd5536aa319ba388e167c0845d775 Mon Sep 17 00:00:00 2001 From: ts Date: Sun, 15 Aug 2021 19:15:21 -0400 Subject: [PATCH 0695/1002] (not tested!) pointwatch - automatically update message IDs I never logged in to test if this would load, but I did test it locally to see if the functions could pull the correct IDs from DAT files sent by a friend. (c) dos2unix, struct to lpack, read *a to read 2 --- addons/pointwatch/libs/dialog.lua | 130 ++++++++++++++++++++++++++++++ addons/pointwatch/message_ids.lua | 77 +++++++++++++++++- 2 files changed, 206 insertions(+), 1 deletion(-) create mode 100644 addons/pointwatch/libs/dialog.lua diff --git a/addons/pointwatch/libs/dialog.lua b/addons/pointwatch/libs/dialog.lua new file mode 100644 index 0000000000..860deacc67 --- /dev/null +++ b/addons/pointwatch/libs/dialog.lua @@ -0,0 +1,130 @@ +--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 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 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. + +local xor = require('bit').bxor +require('pack') +local unpack = require('string').unpack +local pack = require('string').pack +local find = require('string').find + +local dialog = {} + +local function decode(int) + return xor(int, 0x80808080) +end +local encode = decode + +local floor = require('math').floor +local function binary_search(pos, dat, n) + local l, r, m = 1, n + while l < r do + m = floor((l+r)/2) + if decode(unpack(' 0 then + local f = io.open(ftable, 'rb') + local offset = 2*dat_id + f:seek('set', offset) + local dat = f:read(2) + f:close() + + local packed_16bit = byte(dat, 2) * 256 + byte(dat, 1) + local dir = floor(packed_16bit / 128) + local file = packed_16bit - dir * 128 + + path = rom .. tostring(dir) .. '/' .. tostring(file) .. '.DAT' + end + f:close() + n = n + 1 + local d = tostring(n) + rom = dat_path .. 'ROM' .. d .. '/' + vtable = rom .. 'VTABLE' .. d .. '.DAT' + ftable = rom .. 'FTABLE' .. d .. '.DAT' + until path or not windower.dir_exists(rom) + if not path then print('Could not convert dat ID', dat_id) return end + + -- convert dialog entry to dialog ID + local dialog = require('libs/dialog') + local search_phrase = string.char( + 158,133,214,233,243,233,244,225,238,244,160,204,233,231,232, + 244,160,201,238,244,229,238,243,233,244,249,158,129,135,208, + 229,225,242,236,229,243,227,229,238,244,186,160,138,128,160, + 175,160,197,226,239,238,186,160,138,129,135,199,239,236,228, + 229,238,186,160,138,130,160,175,160,211,233,236,246,229,242, + 249,186,160,138,131,255,177,128,135 + ) + local f = io.open(path, 'rb') + local dat = f:read('*a') + f:close() + local id = dialog.get_entry_id(dat, search_phrase) + if not id then return end -- ruh roh + + messages['z'..tostring(zone_id)].offset = id + t[zone_id] = nil + end +end + +update_offset(windower.ffxi.get_info().zone) +windower.register_event('zone change', update_offset) + return messages + From d7eb00582bf160d6b71a82f91652af830267f31d Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Mon, 16 Aug 2021 16:25:17 -0600 Subject: [PATCH 0696/1002] fix flatten fix flatten and extend function calls for non-meta tables --- addons/libs/tables.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/libs/tables.lua b/addons/libs/tables.lua index 7dcbb4697f..24417a2524 100644 --- a/addons/libs/tables.lua +++ b/addons/libs/tables.lua @@ -146,10 +146,10 @@ end -- Appends an array table to the end of another array table. function table.extend(t, t_extend) if type(t_extend) ~= 'table' then - return t:append(t_extend) + return table.append(t, t_extend) end for _, val in ipairs(t_extend) do - t:append(val) + table.append(t, val) end return t @@ -268,7 +268,7 @@ function table.flatten(t, recursive) local res = {} local key = 1 local flat = {} - for key, val in ipairs(t) do + for _, val in ipairs(t) do if type(val) == 'table' then if recursive then flat = table.flatten(val, recursive) From 2c3865d9243d9e20f501bfe16ba2e4444cac4c25 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Fri, 27 Aug 2021 12:25:15 -0600 Subject: [PATCH 0697/1002] Update to properly handle more valid commands Now will properly swap for valid commands such as `/ma "Garuda"` and `/ma "Elemental Siphon"` Also will now properly handle (ignore) more valid forms of waits such as `` and `` and waits that are not preceded by a space `/ma garuda ` --- addons/GearSwap/triggers.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/GearSwap/triggers.lua b/addons/GearSwap/triggers.lua index 5a1ca8d8fd..1dad0feb25 100644 --- a/addons/GearSwap/triggers.lua +++ b/addons/GearSwap/triggers.lua @@ -44,8 +44,8 @@ windower.register_event('outgoing text',function(original,modified,blocked,ffxi, windower.debug('outgoing text') if gearswap_disabled then return modified end - local splitline = windower.from_shift_jis(windower.convert_auto_trans(modified)):gsub(' ',''):gsub('"(.-)"',function(str) - return str:gsub(' ',string.char(7)) + local splitline = windower.from_shift_jis(windower.convert_auto_trans(modified)):gsub('',''):gsub('"(.-)"',function(str) + return ' '..str:gsub(' ',string.char(7))..' ' end):split(' '):filter(-'') if splitline.n == 0 then return end From d02d19f680dc4cd1419f5a8efdd6bad929312ff7 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Sun, 5 Sep 2021 20:50:21 -0400 Subject: [PATCH 0698/1002] Inventory Full Cannot Bid --- addons/libs/packets/fields.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index dc6f21f22f..51129e8dcf 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2492,6 +2492,7 @@ enums['buy stat'] = { [0x01] = 'Success', [0x02] = 'Placing', [0xC5] = 'Failed', + [0xE5] = 'Cannot Bid' } -- 0x0A, 0x0B and 0x0D could probably be combined, the fields seem the same. From 7b15fe8782fabc680af85088a43af7c6231f210e Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Tue, 7 Sep 2021 03:32:43 +0200 Subject: [PATCH 0699/1002] Adding Levin to Slips lib Adding Levin to Slips lib --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index de0e188931..a2b93ea397 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -35,7 +35,7 @@ slips.items = { [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748}, -- 138 SE Skipped an index hence the 0 as one of the items - [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770}, --174 + [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067}, --175 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, --115 [slips.storages[26]] = L{23063, 23130, 23197, 23264, 23331, 23064, 23131, 23198, 23265, 23332, 23065, 23132, 23199, 23266, 23333, 23066, 23133, 23200, 23267, 23334, 23067, 23134, 23201, 23268, 23335, 23068, 23135, 23202, 23269, 23336, 23069, 23136, 23203, 23270, 23337, 23070, 23137, 23204, 23271, 23338, 23071, 23138, 23205, 23272, 23339, 23072, 23139, 23206, 23273, 23340, 23073, 23140, 23207, 23274, 23341, 23074, 23141, 23208, 23275, 23342, 23075, 23142, 23209, 23276, 23343, 23076, 23143, 23210, 23277, 23344, 23077, 23144, 23211, 23278, 23345, 23078, 23145, 23212, 23279, 23346, 23079, 23146, 23213, 23280, 23347, 23080, 23147, 23214, 23281, 23348, 23081, 23148, 23215, 23282, 23349, 23082, 23149, 23216, 23283, 23350, 23083, 23150, 23217, 23284, 23351, 23084, 23151, 23218, 23285, 23352}, --110 From ec8f53abd71e6dfbd9edd191310de94f278c978e Mon Sep 17 00:00:00 2001 From: ts Date: Mon, 13 Sep 2021 17:14:06 -0400 Subject: [PATCH 0700/1002] duplicate entries There are duplicates in the tables. That's a pain. --- addons/pointwatch/libs/dialog.lua | 133 ++++++++++++++++++++---------- addons/pointwatch/message_ids.lua | 12 ++- 2 files changed, 99 insertions(+), 46 deletions(-) diff --git a/addons/pointwatch/libs/dialog.lua b/addons/pointwatch/libs/dialog.lua index 860deacc67..fcc9983df0 100644 --- a/addons/pointwatch/libs/dialog.lua +++ b/addons/pointwatch/libs/dialog.lua @@ -24,11 +24,24 @@ --(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS --SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-- This library was written to help find the ID of a known +-- action message corresponding to an entry in the dialog tables. +-- While the IDs can be collected in-game, they occasionally +-- change and would otherwise need to be manually updated. +-- It can also be used to find and decode an entry given the ID. + +-- Common parameters: +-- dat: The entire content of the zone dialog DAT file +-- i.e. local dat = io.open('path/to/dialog/DAT', 'rb'):read('*a') +-- entry: The string you are looking for. If you do not know the +-- entire string, use dev_find_substring. + local xor = require('bit').bxor require('pack') -local unpack = require('string').unpack -local pack = require('string').pack -local find = require('string').find +local string = require('string') +local unpack = string.unpack +local pack = string.pack +local find = string.find local dialog = {} @@ -49,33 +62,59 @@ local function binary_search(pos, dat, n) r = m end end - return l-2 - -- -1 since we want the index to the left of where "pos" would be placed - -- another -1 to convert to 0-indexing + return l-2 -- we want the index to the left of where "pos" would be placed +end + +local function plain_text_gmatch(text, substring, n) + n = n or 1 + return function() + local pos = find(text, substring, n, true) + if pos then n = pos + 1 end + return pos + end end function dialog.dev_get_offset(dat, id) -- sanity check function - return decode(unpack(' last_offset then + break + elseif offset == last_offset then + next_pos = #dat+1 + else + next_pos = decode(unpack(' 0 then local f = io.open(ftable, 'rb') local offset = 2*dat_id - f:seek('set', offset) + f:seek('set', offset) local dat = f:read(2) f:close() @@ -249,10 +249,14 @@ local function update_offset(zone_id) local f = io.open(path, 'rb') local dat = f:read('*a') f:close() - local id = dialog.get_entry_id(dat, search_phrase) - if not id then return end -- ruh roh + local res = dialog.get_ids_matching_entry(dat, search_phrase) + if res.n ~= 1 then + print('In pointwatch/message_ids.lua: matched multiple entries') + print('Could not update message ID.') + return + end - messages['z'..tostring(zone_id)].offset = id + messages['z'..tostring(zone_id)].offset = res[1] t[zone_id] = nil end end From c038655cf2c7cc1d27572c4867948c4215309ca6 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Wed, 15 Sep 2021 21:01:44 +0200 Subject: [PATCH 0701/1002] Update slips.lua Update Slips libs for September FFXI update --- addons/libs/slips.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index a2b93ea397..829c5acf0b 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -15,7 +15,7 @@ slips.storages = L{29312, 29313, 29314, 29315, 29316, 29317, 29318, 2931 slips.items = { [slips.storages[1]] = L{16084, 14546, 14961, 15625, 15711, 16085, 14547, 14962, 15626, 15712, 16086, 14548, 14963, 15627, 15713, 16087, 14549, 14964, 15628, 15714, 16088, 14550, 14965, 15629, 15715, 16089, 14551, 14966, 15630, 15716, 16090, 14552, 14967, 15631, 15717, 16091, 14553, 14968, 15632, 15718, 16092, 14554, 14969, 15633, 15719, 16093, 14555, 14970, 15634, 15720, 16094, 14556, 14971, 15635, 15721, 16095, 14557, 14972, 15636, 15722, 16096, 14558, 14973, 15637, 15723, 16097, 14559, 14974, 15638, 15724, 16098, 14560, 14975, 15639, 15725, 16099, 14561, 14976, 15640, 15726, 16100, 14562, 14977, 15641, 15727, 16101, 14563, 14978, 15642, 15728, 16102, 14564, 14979, 15643, 15729, 16103, 14565, 14980, 15644, 15730, 16106, 14568, 14983, 15647, 15733, 16107, 14569, 14984, 15648, 15734, 16108, 14570, 14985, 15649, 15735, 16602, 17741, 18425, 18491, 18588, 18717, 18718, 18850, 18943, 16069, 14530, 14940, 15609, 15695, 16062, 14525, 14933, 15604, 15688, 16064, 14527, 14935, 15606, 15690, 18685, 18065, 17851, 18686, 18025, 18435, 18113, 17951, 17715, 18485, 18408, 18365, 18583, 18417, 18388, 16267, 16268, 16269, 16228, 16229, 15911, 15799, 15800, 15990, 17745, 18121, 16117, 14577, 17857}, -- 168 [slips.storages[2]] = L{12421, 12549, 12677, 12805, 12933, 13911, 14370, 14061, 14283, 14163, 12429, 12557, 12685, 12813, 12941, 13924, 14371, 14816, 14296, 14175, 13934, 14387, 14821, 14303, 14184, 13935, 14388, 14822, 14304, 14185, 13876, 13787, 14006, 14247, 14123, 13877, 13788, 14007, 14248, 14124, 13908, 14367, 14058, 14280, 14160, 13909, 14368, 14059, 14281, 14161, 16113, 14573, 14995, 15655, 15740, 16115, 14575, 14997, 15657, 15742, 16114, 14574, 14996, 15656, 15741, 16116, 14576, 14998, 15658, 15743, 12818, 18198, 12946, 18043, 12690, 17659, 12296, 12434, 15471, 15472, 15473, 15508, 15509, 15510, 15511, 15512, 15513, 15514, 17710, 17595, 18397, 18360, 18222, 17948, 18100, 15475, 15476, 15477, 15488, 15961, 14815, 14812, 14813, 15244, 15240, 14488, 14905, 15576, 15661, 15241, 14489, 14906, 15577, 15662, 13927, 14378, 14076, 14308, 14180, 13928, 14379, 14077, 14309, 14181, 10438, 10276, 10320, 10326, 10367, 10439, 10277, 10321, 10327, 10368, 10440, 10278, 10322, 10328, 10369, 10441, 10279, 10323, 10329, 10370, 25734, 25735, 25736, 25737, 25738, 25739, 25740, 25741, 25742, 25743, 25744}, -- 155 - [slips.storages[3]] = L{16155, 11282, 15021, 16341, 11376, 16156, 11283, 15022, 16342, 11377, 16157, 11284, 15023, 16343, 11378, 16148, 14590, 15011, 16317, 15757, 16143, 14591, 15012, 16318, 15758, 16146, 14588, 15009, 16315, 15755, 16147, 14589, 15010, 16316, 15756, 15966, 15967, 19041, 17684, 17685, 11636, 15844, 15934, 16258, 18735, 18734, 16291, 16292, 19042, 15935, 16293, 16294, 15936, 18618, 11588, 11545, 16158, 16159, 16160, 16149, 14583, 15007, 16314, 15751, 16141, 14581, 15005, 16312, 15749, 16142, 14582, 15006, 16313, 15750, 10876, 10450, 10500, 11969, 10600, 10877, 10451, 10501, 11970, 10601, 10878, 10452, 10502, 11971, 10602, 19132, 18551, 11798, 11362, 11363, 11625, 15959, 16259, 22299, 26414, 21623, 26219, 21886, 23792, 23793, 23794, 23795, 23796}, -- 107 + [slips.storages[3]] = L{16155, 11282, 15021, 16341, 11376, 16156, 11283, 15022, 16342, 11377, 16157, 11284, 15023, 16343, 11378, 16148, 14590, 15011, 16317, 15757, 16143, 14591, 15012, 16318, 15758, 16146, 14588, 15009, 16315, 15755, 16147, 14589, 15010, 16316, 15756, 15966, 15967, 19041, 17684, 17685, 11636, 15844, 15934, 16258, 18735, 18734, 16291, 16292, 19042, 15935, 16293, 16294, 15936, 18618, 11588, 11545, 16158, 16159, 16160, 16149, 14583, 15007, 16314, 15751, 16141, 14581, 15005, 16312, 15749, 16142, 14582, 15006, 16313, 15750, 10876, 10450, 10500, 11969, 10600, 10877, 10451, 10501, 11970, 10601, 10878, 10452, 10502, 11971, 10602, 19132, 18551, 11798, 11362, 11363, 11625, 15959, 16259, 22299, 26414, 21623, 26219, 21886, 23792, 23793, 23794, 23795, 23796, 22032, 22043}, -- 109 [slips.storages[4]] = L{12511, 12638, 13961, 14214, 14089, 12512, 12639, 13962, 14215, 14090, 13855, 12640, 13963, 14216, 14091, 13856, 12641, 13964, 14217, 14092, 12513, 12642, 13965, 14218, 14093, 12514, 12643, 13966, 14219, 14094, 12515, 12644, 13967, 14220, 14095, 12516, 12645, 13968, 14221, 14096, 12517, 12646, 13969, 14222, 14097, 13857, 12647, 13970, 14223, 14098, 12518, 12648, 13971, 14099, 14224, 13868, 13781, 13972, 14225, 14100, 13869, 13782, 13973, 14226, 14101, 12519, 12649, 13974, 14227, 14102, 12520, 12650, 13975, 14228, 14103, 15265, 14521, 14928, 15600, 15684, 15266, 14522, 14929, 15601, 15685, 15267, 14523, 14930, 15602, 15686, 16138, 14578, 15002, 15659, 15746, 16139, 14579, 15003, 15660, 15747, 16140, 14580, 15004, 16311, 15748, 16678, 17478, 17422, 17423, 16829, 16764, 17643, 16798, 16680, 16766, 17188, 17812, 17771, 17772, 16887, 17532, 17717, 18702, 17858, 19203, 21461, 21124, 20776, 27786, 27926, 28066, 28206, 28346, 27787, 27927, 28067, 28207, 28347}, -- 138 [slips.storages[5]] = L{15225, 14473, 14890, 15561, 15352, 15226, 14474, 14891, 15562, 15353, 15227, 14475, 14892, 15563, 15354, 15228, 14476, 14893, 15564, 15355, 15229, 14477, 14894, 15565, 15356, 15230, 14478, 14895, 15566, 15357, 15231, 14479, 14896, 15567, 15358, 15232, 14480, 14897, 15568, 15359, 15233, 14481, 14898, 15569, 15360, 15234, 14482, 14899, 15570, 15361, 15235, 14483, 14900, 15362, 15571, 15236, 14484, 14901, 15572, 15363, 15237, 14485, 14902, 15573, 15364, 15238, 14486, 14903, 15574, 15365, 15239, 14487, 14904, 15575, 15366, 11464, 11291, 15024, 16345, 11381, 11467, 11294, 15027, 16348, 11384, 11470, 11297, 15030, 16351, 11387, 11475, 11302, 15035, 16357, 11393, 11476, 11303, 15036, 16358, 11394, 11477, 11304, 15037, 16359, 11395}, -- 105 [slips.storages[6]] = L{15072, 15087, 15102, 15117, 15132, 15871, 15073, 15088, 15103, 15118, 15133, 15478, 15074, 15089, 15104, 15119, 15134, 15872, 15075, 15090, 15105, 15120, 15135, 15874, 15076, 15091, 15106, 15121, 15136, 15873, 15077, 15092, 15107, 15122, 15137, 15480, 15078, 15093, 15108, 15123, 15138, 15481, 15079, 15094, 15109, 15124, 15139, 15479, 15080, 15095, 15110, 15125, 15140, 15875, 15081, 15096, 15111, 15126, 15141, 15482, 15082, 15097, 15112, 15127, 15142, 15876, 15083, 15098, 15113, 15128, 15143, 15879, 15084, 15099, 15114, 15129, 15144, 15877, 15085, 15100, 15115, 15130, 15145, 15878, 15086, 15101, 15116, 15131, 15146, 15484, 11465, 11292, 15025, 16346, 11382, 16244, 11468, 11295, 15028, 16349, 11385, 15920, 11471, 11298, 15031, 16352, 11388, 16245, 11478, 11305, 15038, 16360, 11396, 16248, 11480, 11307, 15040, 16362, 11398, 15925}, -- 120 @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757, 25909}, -- 192 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748}, -- 138 SE Skipped an index hence the 0 as one of the items + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801}, -- 141 SE Skipped an index hence the 0 as one of the items [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067}, --175 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, --115 From 3f65070307a1fbdc2c6b9727f36fed14bfff0ac2 Mon Sep 17 00:00:00 2001 From: funkworkz Date: Wed, 15 Sep 2021 20:49:16 -0500 Subject: [PATCH 0702/1002] Update setbgm.lua Two new songs added in the September 2021 update. Names are not known yet. --- addons/setbgm/setbgm.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/setbgm/setbgm.lua b/addons/setbgm/setbgm.lua index 0edd4548b9..000c7be8f6 100644 --- a/addons/setbgm/setbgm.lua +++ b/addons/setbgm/setbgm.lua @@ -50,7 +50,7 @@ music_types = { } songs = { - [25]='Voracious Resurgence Unknown 1', [26]='Voracious Resurgence Unknown 2', [27]='Voracious Resurgence Unknown 3', [28]='Voracious Resurgence Unknown 4', [29]="Devils' Delight", [30]="Odyssey - Bumba", + [25]='Voracious Resurgence Unknown 1', [26]='Voracious Resurgence Unknown 2', [27]='Voracious Resurgence Unknown 3', [28]='Voracious Resurgence Unknown 4', [29]="Devils' Delight", [30]="Odyssey - Bumba", [31]='Voracious Resurgence Unknown 5', [32]='Voracious Resurgence Unknown 6', [40]='Cloister of Time and Souls', [41]='Royal Wanderlust', [42]='Snowdrift Waltz', [43]='Troubled Shadows', [44]='Where Lords Rule Not', [45]='Summers Lost', [46]='Goddess Divine', [47]='Echoes of Creation', [48]='Main Theme', [49]='Luck of the Mog', [50]='Feast of the Ladies', [51]='Abyssea - Scarlet Skies, Shadowed Plains', [52]='Melodies Errant', [53]='Shinryu', [54]='Everlasting Bonds', [55]='Provenance Watcher', [56]='Where it All Begins', [57]='Steel Sings, Blades Dance', [58]='A New Direction', [59]='The Pioneers', [60]='Into Lands Primeval - Ulbuka', [61]="Water's Umbral Knell", [62]='Keepers of the Wild', [63]='The Sacred City of Adoulin', [64]='Breaking Ground', [65]='Hades', [66]='Arciela', [67]='Mog Resort', [68]='Worlds Away', [69]="Distant Worlds (Nanaa Mihgo's version)", From 209a7396e9ab32991be10d450014b9b5d18c859f Mon Sep 17 00:00:00 2001 From: Byrth Date: Wed, 15 Sep 2021 22:06:38 -0400 Subject: [PATCH 0703/1002] Fix gearswap (requires monster_skills.lua) --- addons/GearSwap/flow.lua | 6 +++++- addons/GearSwap/gearswap.lua | 2 +- addons/GearSwap/helper_functions.lua | 2 +- addons/GearSwap/statics.lua | 2 +- addons/GearSwap/triggers.lua | 12 ++++++------ 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/addons/GearSwap/flow.lua b/addons/GearSwap/flow.lua index 1c136861e4..ef5a1eecd1 100644 --- a/addons/GearSwap/flow.lua +++ b/addons/GearSwap/flow.lua @@ -144,7 +144,7 @@ function equip_sets(swap_type,ts,...) end if player.race ~= 'Precomposed NPC' then - -- Short circuits the routine and gets out before equip processing + -- Short circuits the routine and gets out before equip processing -- if there's no swapping to be done because the user is a monster. for v,i in pairs(default_slot_map) do @@ -203,6 +203,10 @@ function equip_sets(swap_type,ts,...) end end end + else + if swap_type == 'midcast' and command_registry[ts] and command_registry[ts].proposed_packet and not _settings.demo_mode then + windower.packets.inject_outgoing(command_registry[ts].proposed_packet:byte(1),command_registry[ts].proposed_packet) + end end windower.debug(tostring(swap_type)..' exit') diff --git a/addons/GearSwap/gearswap.lua b/addons/GearSwap/gearswap.lua index 6e2ee0063d..88e574d66f 100644 --- a/addons/GearSwap/gearswap.lua +++ b/addons/GearSwap/gearswap.lua @@ -113,7 +113,7 @@ require 'actions' packets = require 'packets' -- Resources Checks -if res.items and res.bags and res.slots and res.statuses and res.jobs and res.elements and res.skills and res.buffs and res.spells and res.job_abilities and res.weapon_skills and res.monster_abilities and res.action_messages and res.skills and res.monstrosity and res.weather and res.moon_phases and res.races then +if res.items and res.bags and res.slots and res.statuses and res.jobs and res.elements and res.skills and res.buffs and res.spells and res.job_abilities and res.weapon_skills and res.monster_skills and res.action_messages and res.skills and res.monstrosity and res.weather and res.moon_phases and res.races then else error('Missing resources!') end diff --git a/addons/GearSwap/helper_functions.lua b/addons/GearSwap/helper_functions.lua index 2fc8a11d0a..0034d6031a 100644 --- a/addons/GearSwap/helper_functions.lua +++ b/addons/GearSwap/helper_functions.lua @@ -682,7 +682,7 @@ function filter_pretarget(action) not res.monstrosity[windower.ffxi.get_mjob_data().species] or not res.monstrosity[windower.ffxi.get_mjob_data().species].tp_moves[action.id] or not (res.monstrosity[windower.ffxi.get_mjob_data().species].tp_moves[action.id] <= player.main_job_level)) then -- Monstrosity filtering - msg.debugging("Unable to execute command. You do not have access to that monsterskill ("..(res.monster_abilities[action.id][language] or action.id)..")") + msg.debugging("Unable to execute command. You do not have access to that monsterskill ("..(res.monster_skills[action.id][language] or action.id)..")") return false end diff --git a/addons/GearSwap/statics.lua b/addons/GearSwap/statics.lua index b32e6c982c..2e9e46da42 100644 --- a/addons/GearSwap/statics.lua +++ b/addons/GearSwap/statics.lua @@ -92,7 +92,7 @@ for i,v in pairs(res.weapon_skills) do make_entry(v,i) end -for i,v in pairs(res.monster_abilities) do +for i,v in pairs(res.monster_skills) do v.type = 'MonsterSkill' make_entry(v,i) end diff --git a/addons/GearSwap/triggers.lua b/addons/GearSwap/triggers.lua index 5a1ca8d8fd..8df14f1a0c 100644 --- a/addons/GearSwap/triggers.lua +++ b/addons/GearSwap/triggers.lua @@ -81,15 +81,15 @@ windower.register_event('outgoing text',function(original,modified,blocked,ffxi, elseif temp_mob_arr then refresh_globals() - local r_line, find_monster_ability + local r_line, find_monster_skill - function find_monster_ability(abil) + function find_monster_skill(abil) local line = false if player.species and player.species.tp_moves then -- Iterates over currently available monster TP moves instead of using validabils for i,v in pairs(player.species.tp_moves) do - if res.monster_abilities[i][language]:lower() == abil then - line = copy_entry(res.monster_abilities[i]) + if res.monster_skills[i][language]:lower() == abil then + line = copy_entry(res.monster_skills[i]) break end end @@ -100,8 +100,8 @@ windower.register_event('outgoing text',function(original,modified,blocked,ffxi, if unified_prefix == '/ma' then r_line = copy_entry(res.spells[validabils[language][unified_prefix][abil]]) storedcommand = command..' "'..windower.to_shift_jis(r_line[language])..'" ' - elseif unified_prefix == '/ms' and find_monster_ability(abil) then - r_line = find_monster_ability(abil) + elseif unified_prefix == '/ms' and find_monster_skill(abil) then + r_line = find_monster_skill(abil) storedcommand = command..' "'..windower.to_shift_jis(r_line[language])..'" ' elseif unified_prefix == '/ws' then r_line = copy_entry(res.weapon_skills[validabils[language][unified_prefix][abil]]) From 60e6d5aa9a201f3d7d031f7cefc4600e194787dd Mon Sep 17 00:00:00 2001 From: Byrth Date: Wed, 15 Sep 2021 22:06:48 -0400 Subject: [PATCH 0704/1002] fix shortcuts (requires monster_skills.lua) --- addons/shortcuts/helper_functions.lua | 2 +- addons/shortcuts/shortcuts.lua | 4 ++-- addons/shortcuts/statics.lua | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/addons/shortcuts/helper_functions.lua b/addons/shortcuts/helper_functions.lua index 081409ed03..092f4cfe69 100644 --- a/addons/shortcuts/helper_functions.lua +++ b/addons/shortcuts/helper_functions.lua @@ -182,7 +182,7 @@ function check_usability(player,resource,id) return true elseif L(windower.ffxi.get_abilities()[resource] or {}):contains(id) then return true - elseif resource == 'monster_abilities' and player.main_job_id == 23 and (res.monstrosity[windower.ffxi.get_mjob_data().species].tp_moves[id] or 0) <= player.main_job_level then + elseif resource == 'monster_skills' and player.main_job_id == 23 and (res.monstrosity[windower.ffxi.get_mjob_data().species].tp_moves[id] or 0) <= player.main_job_level then return true elseif resource == 'mounts' and math.floor((windower.packets.last_incoming(0x0AE):byte(math.floor(id/8)+5)%2^(id%8+1))/2^(id%8)) == 1 then return true diff --git a/addons/shortcuts/shortcuts.lua b/addons/shortcuts/shortcuts.lua index cfd8cb7548..0d83c66833 100644 --- a/addons/shortcuts/shortcuts.lua +++ b/addons/shortcuts/shortcuts.lua @@ -367,9 +367,9 @@ function interp_text(splitline,offset,modified) 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_abilities and 'monster_abilities') or (options.mounts and 'mounts')][options[command_list[splitline[1]]] or options.spells or options.job_abilities or options.weapon_skills or options.monster_abilities or options.mounts] + 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_abilities and 'monster_abilities') or (nonoptions.mounts and 'mounts')][nonoptions[command_list[splitline[1]]] or nonoptions.spells or nonoptions.weapon_skills or nonoptions.job_abilities or nonoptions.monster_abilities or nonoptions.mounts] + 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) diff --git a/addons/shortcuts/statics.lua b/addons/shortcuts/statics.lua index f8c6b1791c..4fd1219ee9 100644 --- a/addons/shortcuts/statics.lua +++ b/addons/shortcuts/statics.lua @@ -36,7 +36,7 @@ validabils = {} -- List of valid prefixes to be interpreted with the resources. The values currently have no use. command_list = {['ja']='job_abilities',['jobability']='job_abilities',['so']='spells',['song']='spells',['ma']='spells',['magic']='spells',['nin']='spells',['ninjutsu']='spells', - ['ra']='Ranged Attack',['range']='Ranged Attack',['throw']='Ranged Attack',['shoot']='Ranged Attack',['monsterskill']='monster_abilities',['ms']='monster_abilities', + ['ra']='Ranged Attack',['range']='Ranged Attack',['throw']='Ranged Attack',['shoot']='Ranged Attack',['monsterskill']='monster_skills',['ms']='monster_skills', ['ws']='weapon_skills',['weaponskill']='weapon_skills',['item']='Ability',['pet']='job_abilities',['mo']='mounts',['mount']='mounts'} in_game_res_commands = {['ja']='/ja',['jobability']='/ja',['pet']='/ja', @@ -208,5 +208,5 @@ end validabils_it('spells') validabils_it('job_abilities') validabils_it('weapon_skills') -validabils_it('monster_abilities') +validabils_it('monster_skills') validabils_it('mounts') \ No newline at end of file From 82e6653d2a302bbf5492ee553570b0c89bda8ca4 Mon Sep 17 00:00:00 2001 From: Byrth Date: Wed, 15 Sep 2021 22:07:44 -0400 Subject: [PATCH 0705/1002] version bumps --- addons/GearSwap/gearswap.lua | 2 +- addons/shortcuts/shortcuts.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/GearSwap/gearswap.lua b/addons/GearSwap/gearswap.lua index 88e574d66f..516840635e 100644 --- a/addons/GearSwap/gearswap.lua +++ b/addons/GearSwap/gearswap.lua @@ -25,7 +25,7 @@ --SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'GearSwap' -_addon.version = '0.936' +_addon.version = '0.937' _addon.author = 'Byrth' _addon.commands = {'gs','gearswap'} diff --git a/addons/shortcuts/shortcuts.lua b/addons/shortcuts/shortcuts.lua index 0d83c66833..a2f5da526e 100644 --- a/addons/shortcuts/shortcuts.lua +++ b/addons/shortcuts/shortcuts.lua @@ -24,7 +24,7 @@ --(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.902' +_addon.version = '2.903' _addon.name = 'Shortcuts' _addon.author = 'Byrth' _addon.commands = {'shortcuts'} From 02f95fa465669a9a5b79529c05dc9654772cab24 Mon Sep 17 00:00:00 2001 From: ts Date: Mon, 27 Sep 2021 17:47:35 -0400 Subject: [PATCH 0706/1002] A few functions for decoding dialog entries Locals, spacing dev table, format arg, no more length the rest of the owl --- addons/libs/dialog.lua | 227 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 addons/libs/dialog.lua diff --git a/addons/libs/dialog.lua b/addons/libs/dialog.lua new file mode 100644 index 0000000000..5598175597 --- /dev/null +++ b/addons/libs/dialog.lua @@ -0,0 +1,227 @@ +-- This library was written to help find the ID of a known +-- action message corresponding to an entry in the dialog tables. +-- While the IDs can be collected in-game, they occasionally +-- change and would otherwise need to be manually updated. +-- It can also be used to find and decode an entry given the ID. + +-- Common parameters: +-- +-- dat: Either the entire content of the zone dialog DAT file or +-- a file descriptor. +-- i.e. either local dat = io.open('path/to/dialog/DAT', 'rb') +-- or dat = dat:read('*a') +-- The functions are expected to be faster when passed a string, +-- but will use less memory when receiving a file descriptor. +-- +-- entry: The string you are looking for. Whether or not the string +-- is expected to be encoded should be indicated in the parameter's +-- name. If you do not know the entire string, use dev.find_substring +-- and serialize the result. + +local xor = require('bit').bxor +local floor = require('math').floor +local string = require('string') +local find = string.find +local sub = string.sub +local gsub = string.gsub +local format = string.format +local char = string.char +local byte = string.byte +require('pack') +local unpack = string.unpack +local pack = string.pack + +local function decode(int) + return xor(int, 0x80808080) +end +local encode = decode + +local function binary_search(pos, dat, n) + local l, r, m = 1, n + while l < r do + m = floor((l + r) / 2) + if decode(unpack(' last_offset then + break + elseif offset == last_offset then + next_pos = #dat + 1 + else + next_pos = decode(unpack(' Date: Fri, 1 Oct 2021 19:38:43 -0400 Subject: [PATCH 0707/1002] Update messages and Add Low/Mid D Tower to be extracted --- addons/boxdestroyer/make_messages/settings.py | 4 ++-- addons/boxdestroyer/messages.lua | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/addons/boxdestroyer/make_messages/settings.py b/addons/boxdestroyer/make_messages/settings.py index c2cf18c221..ccc6b1bb74 100644 --- a/addons/boxdestroyer/make_messages/settings.py +++ b/addons/boxdestroyer/make_messages/settings.py @@ -100,7 +100,7 @@ #151: 6571, # castle oztroja 153: 6573, # the boyahda tree #154: 6574, # dragon's aery - #157: 6577, # middle delkfutt's tower + 157: 6577, # middle delkfutt's tower 158: 6578, # upper delkfutt's tower 159: 6579, # temple of uggalepih 160: 6580, # den of rancor @@ -113,7 +113,7 @@ 176: 6596, # sea serpent grotto 177: 6597, # ve'lugannon palace 178: 6598, # the shrine of ru'avitau - #184: 6604, # lower delkfutt's tower + 184: 6604, # lower delkfutt's tower #186: 6606, # dynamis - bastok #187: 6607, # dynamis - windurst 190: 6610, # king ranpere's tomb diff --git a/addons/boxdestroyer/messages.lua b/addons/boxdestroyer/messages.lua index 87be19465a..6624a9520c 100644 --- a/addons/boxdestroyer/messages.lua +++ b/addons/boxdestroyer/messages.lua @@ -30,6 +30,7 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination [128] = 7510, [130] = 7574, [153] = 11400, + [157] = 7380, [158] = 7386, [159] = 8449, [160] = 7413, @@ -42,6 +43,7 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination [176] = 7608, [177] = 11223, [178] = 11403, + [184] = 8633, [190] = 8257, [191] = 8377, [192] = 7413, From 84cc1a7fd8ae531e0773934b7e7aa2e19af895d5 Mon Sep 17 00:00:00 2001 From: Byrth Date: Mon, 11 Oct 2021 06:39:41 -0400 Subject: [PATCH 0708/1002] change based on CHA CHA CHA's info --- addons/libs/packets/fields.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 51129e8dcf..1268329067 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -646,7 +646,7 @@ types.lockstyleset = L{ } -- lockstyleset -fields.outgoing[0x53] = L{ +fields.outgoing[0x053] = L{ -- First 4 bytes are a header for the set {ctype='unsigned char', label='Count'}, -- 04 {ctype='unsigned char', label='Type'}, -- 05 0 = "Stop locking style", 1 = "Continue locking style", 3 = "Lock style in this way". Might be flags? @@ -1542,7 +1542,7 @@ fields.incoming[0x01C] = L{ {ctype='unsigned char', label='Wardrobe 2 Size'}, -- 0E {ctype='unsigned char', label='Wardrobe 3 Size'}, -- 0F {ctype='unsigned char', label='Wardrobe 4 Size'}, -- 10 - {ctype='data[3]', label='_padding1', const=''}, -- 11 + {ctype='data[19]', label='_padding1', const=''}, -- 11 {ctype='unsigned short', label='_dupeInventory Size'}, -- 14 These "dupe" sizes are set to 0 if the inventory disabled. {ctype='unsigned short', label='_dupeSafe Size'}, -- 16 {ctype='unsigned short', label='_dupeStorage Size'}, -- 18 The accumulated storage from all items (uncapped) -1 @@ -1556,7 +1556,7 @@ fields.incoming[0x01C] = L{ {ctype='unsigned short', label='_dupeWardrobe 2 Size'}, -- 28 {ctype='unsigned short', label='_dupeWardrobe 3 Size'}, -- 2A This is not set to 0 despite being disabled for whatever reason {ctype='unsigned short', label='_dupeWardrobe 4 Size'}, -- 2C This is not set to 0 despite being disabled for whatever reason - {ctype='data[6]', label='_padding2', const=''}, -- 2E + {ctype='data[22]', label='_padding2', const=''}, -- 2E } -- Finish Inventory From 566a726d50fcee693644dfe7e7ff29164a9280d7 Mon Sep 17 00:00:00 2001 From: Byrth Date: Mon, 11 Oct 2021 07:06:37 -0400 Subject: [PATCH 0709/1002] fixed comment numbering for 0x01C --- addons/libs/packets/fields.lua | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 1268329067..9073dc4b9b 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1543,20 +1543,20 @@ fields.incoming[0x01C] = L{ {ctype='unsigned char', label='Wardrobe 3 Size'}, -- 0F {ctype='unsigned char', label='Wardrobe 4 Size'}, -- 10 {ctype='data[19]', label='_padding1', const=''}, -- 11 - {ctype='unsigned short', label='_dupeInventory Size'}, -- 14 These "dupe" sizes are set to 0 if the inventory disabled. - {ctype='unsigned short', label='_dupeSafe Size'}, -- 16 - {ctype='unsigned short', label='_dupeStorage Size'}, -- 18 The accumulated storage from all items (uncapped) -1 - {ctype='unsigned short', label='_dupeTemporary Size'}, -- 1A - {ctype='unsigned short', label='_dupeLocker Size'}, -- 1C + {ctype='unsigned short', label='_dupeInventory Size'}, -- 24 These "dupe" sizes are set to 0 if the inventory disabled. + {ctype='unsigned short', label='_dupeSafe Size'}, -- 26 + {ctype='unsigned short', label='_dupeStorage Size'}, -- 28 The accumulated storage from all items (uncapped) -1 + {ctype='unsigned short', label='_dupeTemporary Size'}, -- 2A + {ctype='unsigned short', label='_dupeLocker Size'}, -- 2C {ctype='unsigned short', label='_dupeSatchel Size'}, -- 2E - {ctype='unsigned short', label='_dupeSack Size'}, -- 20 - {ctype='unsigned short', label='_dupeCase Size'}, -- 22 - {ctype='unsigned short', label='_dupeWardrobe Size'}, -- 24 - {ctype='unsigned short', label='_dupeSafe 2 Size'}, -- 26 - {ctype='unsigned short', label='_dupeWardrobe 2 Size'}, -- 28 - {ctype='unsigned short', label='_dupeWardrobe 3 Size'}, -- 2A This is not set to 0 despite being disabled for whatever reason - {ctype='unsigned short', label='_dupeWardrobe 4 Size'}, -- 2C This is not set to 0 despite being disabled for whatever reason - {ctype='data[22]', label='_padding2', const=''}, -- 2E + {ctype='unsigned short', label='_dupeSack Size'}, -- 30 + {ctype='unsigned short', label='_dupeCase Size'}, -- 32 + {ctype='unsigned short', label='_dupeWardrobe Size'}, -- 34 + {ctype='unsigned short', label='_dupeSafe 2 Size'}, -- 36 + {ctype='unsigned short', label='_dupeWardrobe 2 Size'}, -- 38 + {ctype='unsigned short', label='_dupeWardrobe 3 Size'}, -- 3A This is not set to 0 despite being disabled for whatever reason + {ctype='unsigned short', label='_dupeWardrobe 4 Size'}, -- 3C This is not set to 0 despite being disabled for whatever reason + {ctype='data[22]', label='_padding2', const=''}, -- 3E } -- Finish Inventory From 394ebfb762e969baadc324c54413d6234d1e7482 Mon Sep 17 00:00:00 2001 From: zetaepyon Date: Tue, 2 Nov 2021 15:43:46 -0500 Subject: [PATCH 0710/1002] Update README.md --- addons/plugin_manager/README.md | 35 ++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/addons/plugin_manager/README.md b/addons/plugin_manager/README.md index 0aae29e543..dc4cbd0c6b 100644 --- a/addons/plugin_manager/README.md +++ b/addons/plugin_manager/README.md @@ -1,26 +1,29 @@ -Author: Byrth +**Author:** Byrth -Version: 1.0 +**Version:** 1.0 -Date: 15/11/13 +**Date:** 15/11/13 -Plugin Manager +# Plugin Manager -Abbreviation: None +**Abbreviation:** None -Commands: None +**Commands:** None -Purpose: To allow player-customizable plugin management. +**Purpose:** To allow player-customizable plugin management. -Installation Instructions (from the Windower 4 Launcher): +## Installation -* 1 Start your copy of Windower 4 and select the "Addons" menu up top in the Launcher. -* 2 Click the icon next to "plugin_manager" -* 3 Log in to the game! -* 4 Alter the settings as you wish. (An example file has been included) -* 5 "//lua r plugin_manager" will reload and give you the new settings. +1. Start your copy of Windower 4 and select the "Addons" menu up top in the Launcher. +1. Click the icon next to "plugin_manager" +1. Log in to the game! +1. Alter the settings as you wish. (An example file has been included) +1. `//lua r plugin_manager` will reload and give you the new settings. -Settings Files: -The settings file for pluginmanager is one xml file with a format similar to the settings files for plugins. XML files can be opened with Notepad, edited, and closed 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" +> **Note:** Plugin Manager will *not* automatically disable or unload any plugins or addons that you have enabled in the Windower launcher. Anything enabled in the launcher will be loaded for all characters, regardless of how you have configured your Plugin Manager settings. +> If you want Plugin Manager to handle a plugin or addon, be sure to disable it in the launcher. -* data/settings.xml - contains plugins and addons specific to each character. is loaded if there is not a set of plugins/addons inside tags that are a case-sensitive match to the player's name. \ No newline at end of file +## Settings Files +The settings file for Plugin Manager are found in a single XML file with a format similar to the settings files for plugins. + +* `data/settings.xml` - contains plugins and addons specific to each character. is loaded if there is not a set of plugins/addons inside tags that are a case-sensitive match to the player's name. From b09d2e31e05023d0aff6c5fa08477769e1c772f9 Mon Sep 17 00:00:00 2001 From: Dean James Date: Sat, 6 Nov 2021 23:26:53 +0000 Subject: [PATCH 0711/1002] Update Mount Roulette to 3.1.0. Add blacklist function. --- addons/MountRoulette/MountRoulette.lua | 95 ++++++++++++++++++++++++-- addons/MountRoulette/README.md | 22 +++++- 2 files changed, 111 insertions(+), 6 deletions(-) diff --git a/addons/MountRoulette/MountRoulette.lua b/addons/MountRoulette/MountRoulette.lua index 0b272b70e3..3dfab1232e 100644 --- a/addons/MountRoulette/MountRoulette.lua +++ b/addons/MountRoulette/MountRoulette.lua @@ -26,14 +26,18 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ]] -_addon.name = 'Mount Roulette' -_addon.author = 'Dean James (Xurion of Bismarck)' -_addon.version = '3.0.1' +_addon.name = 'Mount Roulette' +_addon.author = 'Dean James (Xurion of Bismarck)' +_addon.version = '3.1.0' _addon.commands = {'mountroulette', 'mr'} require('lists') require('sets') resources = require('resources') +config = require('config') +settings = config.load({ + blacklist = '' +}) math.randomseed(os.time()) @@ -43,6 +47,13 @@ for _, mount in pairs(resources.mounts) do possible_mounts:append(mount.name:lower()) end +blacklist = {} +if string.len(settings.blacklist) > 0 then + for mount in settings.blacklist:gmatch("([^,]+)") do + table.insert(blacklist, mount) + end +end + function update_allowed_mounts() local allowed_mounts_set = S{} local kis = windower.ffxi.get_key_items() @@ -55,7 +66,10 @@ function update_allowed_mounts() end) local mount = possible_mounts[mount_index] - allowed_mounts_set:add(mount) + -- Add this to allowed mounts if it is not already there and it is not blacklisted + if not allowed_mounts:contains(mount) and not S(blacklist):contains(mount) then + allowed_mounts_set:add(mount) + end end end @@ -70,7 +84,9 @@ windower.register_event('incoming chunk', function(id) end end) -windower.register_event('addon command', function() +commands = {} + +commands.mount = function() local player = windower.ffxi.get_player() -- If the player is mounted, dismount now @@ -86,4 +102,73 @@ windower.register_event('addon command', function() -- Generate random number and use it to choose a mount local mount_index = math.ceil(math.random() * #allowed_mounts) windower.send_command('input /mount "' .. allowed_mounts[mount_index] .. '"') +end + +commands.blacklist = function(args) + local operation = args:remove(1) + + if not operation then + windower.add_to_chat(8, 'Blacklisted mounts:') + for k, v in ipairs(blacklist) do + windower.add_to_chat(8, ' ' .. v) + end + return + end + + local mount = args:concat(' '):lower() + + if not operation or not mount then + commands.help() + return + end + + if not possible_mounts:contains(mount) then + windower.add_to_chat(8, 'Unknown mount ' .. mount) + return + end + + if operation == 'add' and not S(blacklist):contains(mount) then + for k, v in ipairs(T(allowed_mounts)) do + if v == mount then + allowed_mounts:remove(k) + end + end + table.insert(blacklist, mount) + windower.add_to_chat(8, 'The ' .. mount .. ' mount is now blacklisted') + save_settings() + elseif operation == 'remove' then + for k, v in ipairs(blacklist) do + if v == mount then + table.remove(blacklist, k) + end + end + allowed_mounts:append(mount) + windower.add_to_chat(8, 'The ' .. mount .. ' mount is no longer blacklisted') + save_settings() + end +end + +commands.help = function() + windower.add_to_chat(8, '---Mount Roulette---') + windower.add_to_chat(8, 'Available commands:') + windower.add_to_chat(8, '//mr mount (or just //mr) - Selects a mount at random, or dismounts if mounted') + windower.add_to_chat(8, '//mr blacklist - show blacklisted mounts') + windower.add_to_chat(8, '//mr blacklist add - blacklist a mount so it is never randomly selected') + windower.add_to_chat(8, '//mr blacklist remove - remove a mount from the blacklist') + windower.add_to_chat(8, '//mr help - displays this help') +end + +windower.register_event('addon command', function(command, ...) + command = command and command:lower() or 'mount' + + if commands[command] then + commands[command](L{...}) + else + commands.help() + end end) + +function save_settings() + settings.blacklist = table.concat(blacklist, ",") + settings:save() +end diff --git a/addons/MountRoulette/README.md b/addons/MountRoulette/README.md index 5072d4ae26..c0f8620138 100644 --- a/addons/MountRoulette/README.md +++ b/addons/MountRoulette/README.md @@ -8,10 +8,30 @@ Get the addon from the addon section of the Windower launcher. ### Summon a mount -`//mr` +`//mr` (or `//mr mount`) This will also dismount you if you're currently mounted. +### Add a mount to the blacklist + +`//mr blacklist add ` + +Prevents the given mount from being summoned by Mount Roulette. + +### Remove a mount from the blacklist + +`//mr blacklist remove ` + +Allows the given mount to be summoned by Mount Roulette. + +### List blacklisted mounts + +`//mr blacklist` + +### Show help and commands + +`//mr help` + ## Mount music In an earlier version, this addon disabled mount music. This is now removed in favour of the MountMuzzle addon. From f77419554c62bbd32a8c001935722d6684b38951 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Wed, 10 Nov 2021 09:35:25 -0700 Subject: [PATCH 0712/1002] Master Levels Update 1 --- addons/libs/packets/fields.lua | 41 +++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 9073dc4b9b..bcbdbf0ffa 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -176,7 +176,7 @@ local function slot(val) end local function statuses(val) - return res.statuses[val].name + return res.statuses[val] and res.statuses[val].name or 'Unknown' end local function srank(val) @@ -2989,8 +2989,14 @@ fields.incoming[0x061] = L{ {ctype='bit[5]', label='Unity Rank'}, -- 58 Danger, 00ing caused my client to crash {ctype='bit[16]', label='Unity Points'}, -- 59 {ctype='bit[6]', label='_unknown6'}, -- 5A No obvious function - {ctype='unsigned int', label='_junk1'}, -- 5B - {ctype='unsigned int', label='_junk2'}, -- 5F + {ctype='unsigned int', label='_junk1'}, -- 5C + {ctype='unsigned int', label='_junk2'}, -- 60 + {ctype='unsigned char', label='_unknown6'}, -- 64 + {ctype='unsigned char', label='Master Level'}, -- 65 + {ctype='bit[1]', label='Master Breaker'}, -- 66 + {ctype='bit[15]', label='_junk3'}, -- 66 + {ctype='unsigned int', label='Current Exemplar Points'}, -- 68 + {ctype='unsigned int', label='Required Exemplar Points'}, -- 6C } types.combat_skill = L{ @@ -3365,17 +3371,20 @@ func.incoming[0x0C9][0x01] = L{ {ctype='data[3]', label='_junk1'}, -- 0B {ctype='unsigned char', label='Icon Set Subtype'}, -- 0E 0 = Unopened Linkshell?, 1 = Linkshell, 2 = Pearlsack, 3 = Linkpearl, 4 = Ripped Pearlsack (I think), 5 = Broken Linkpearl? {ctype='unsigned char', label='Icon Set ID'}, -- 0F This identifies the icon set, always 2 for linkshells. - {ctype='bit[4]', label='Linkshell Red'}, -- 10 0xGR, 0x-B - {ctype='bit[4]', label='Linkshell Green'}, -- 10 - {ctype='bit[4]', label='Linkshell Blue'}, -- 11 - {ctype='bit[4]', label='_junk1'}, -- 11 - {ctype='unsigned char', label='Main Job', fn=job}, -- 12 - {ctype='unsigned char', label='Sub Job', fn=job}, -- 13 - {ctype='data[15]', label='Linkshell', enc=ls_enc}, -- 14 6-bit packed - {ctype='unsigned char', label='_padding1'}, -- 23 + {ctype='data[16]', label='Linkshell', enc=ls_enc}, -- 10 6-bit packed + {ctype='bit[4]', label='_junk1'}, -- 20 + {ctype='bit[4]', label='Linkshell Red'}, -- 20 0xGR, 0x-B + {ctype='bit[4]', label='Linkshell Green'}, -- 21 + {ctype='bit[4]', label='Linkshell Blue'}, -- 21 + {ctype='unsigned char', label='_unknown1'}, -- 22 + {ctype='unsigned char', label='Sub Job', fn=job}, -- 23 {ctype='unsigned char', label='Main Job Level'}, -- 24 {ctype='unsigned char', label='Sub Job Level'}, -- 25 - {ctype='data[42]', label='_unknown5'}, -- 26 At least the first two bytes and the last twelve bytes are junk, possibly more + {ctype='unsigned char', label='Main Job', fn=job}, -- 26 + {ctype='unsigned char', label='Master Level'}, -- 27 + {ctype='bit[1]', label='Master Breaker'}, -- 28 + {ctype='bit[7]', label='_junk2'}, -- 28 + {ctype='data[43]', label='_unknown5'}, -- 29 At least the first two bytes and the last twelve bytes are junk, possibly more } -- Bazaar Message @@ -3457,7 +3466,10 @@ fields.incoming[0x0DD] = L{ {ctype='unsigned char', label='Main job level'}, -- 23 {ctype='unsigned char', label='Sub job', fn=job}, -- 24 {ctype='unsigned char', label='Sub job level'}, -- 25 - {ctype='char*', label='Name'}, -- 26 + {ctype='unsigned char', label='Master Level'}, -- 26 + {ctype='bit[1]', label='Master Breaker'}, -- 27 + {ctype='bit[7]', label='_junk2'}, -- 27 + {ctype='char*', label='Name'}, -- 28 } -- Unnamed 0xDE packet @@ -3486,6 +3498,9 @@ fields.incoming[0x0DF] = L{ {ctype='unsigned char', label='Main job level'}, -- 21 {ctype='unsigned char', label='Sub job', fn=job}, -- 22 {ctype='unsigned char', label='Sub job level'}, -- 23 + {ctype='unsigned char', label='Master Level'}, -- 24 + {ctype='bit[1]', label='Master Breaker'}, -- 25 + {ctype='bit[7]', label='_junk2'}, -- 25 } -- Unknown packet 0x0E0: I still can't make heads or tails of the content. The packet is always 8 bytes long. From 0023a173ac0e9ff150894bcd032a4c523d325fed Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Wed, 10 Nov 2021 19:24:16 +0100 Subject: [PATCH 0713/1002] [thtracker] variable fix variable fix --- addons/thtracker/thtracker.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/thtracker/thtracker.lua b/addons/thtracker/thtracker.lua index 063a770aa5..2f05e046c2 100644 --- a/addons/thtracker/thtracker.lua +++ b/addons/thtracker/thtracker.lua @@ -58,7 +58,7 @@ local th_table = {} windower.register_event('addon command', function(command, ...) command = command and command:lower() - local args = {...} + local params = {...} if command == 'pos' then local posx, posy = tonumber(params[2]), tonumber(params[3]) From 411d14f9200741fc16d26cad3a6777c1222f4347 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Wed, 10 Nov 2021 19:27:05 +0100 Subject: [PATCH 0714/1002] Slips lib Update Adding Chemistry Set and Goujian to Slips library --- addons/libs/slips.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 829c5acf0b..3fd7063b10 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,8 +34,8 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757, 25909}, -- 192 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801}, -- 141 SE Skipped an index hence the 0 as one of the items - [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067}, --175 + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749}, -- 142 SE Skipped an index hence the 0 as one of the items + [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067, 21680}, --176 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, --115 [slips.storages[26]] = L{23063, 23130, 23197, 23264, 23331, 23064, 23131, 23198, 23265, 23332, 23065, 23132, 23199, 23266, 23333, 23066, 23133, 23200, 23267, 23334, 23067, 23134, 23201, 23268, 23335, 23068, 23135, 23202, 23269, 23336, 23069, 23136, 23203, 23270, 23337, 23070, 23137, 23204, 23271, 23338, 23071, 23138, 23205, 23272, 23339, 23072, 23139, 23206, 23273, 23340, 23073, 23140, 23207, 23274, 23341, 23074, 23141, 23208, 23275, 23342, 23075, 23142, 23209, 23276, 23343, 23076, 23143, 23210, 23277, 23344, 23077, 23144, 23211, 23278, 23345, 23078, 23145, 23212, 23279, 23346, 23079, 23146, 23213, 23280, 23347, 23080, 23147, 23214, 23281, 23348, 23081, 23148, 23215, 23282, 23349, 23082, 23149, 23216, 23283, 23350, 23083, 23150, 23217, 23284, 23351, 23084, 23151, 23218, 23285, 23352}, --110 From 6e2dbc3a8889c6fd56106bd1673c4b4d0b8511c2 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Wed, 10 Nov 2021 15:38:35 -0500 Subject: [PATCH 0715/1002] Fix dupe label --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index bcbdbf0ffa..5133d02555 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2991,7 +2991,7 @@ fields.incoming[0x061] = L{ {ctype='bit[6]', label='_unknown6'}, -- 5A No obvious function {ctype='unsigned int', label='_junk1'}, -- 5C {ctype='unsigned int', label='_junk2'}, -- 60 - {ctype='unsigned char', label='_unknown6'}, -- 64 + {ctype='unsigned char', label='_unknown7'}, -- 64 {ctype='unsigned char', label='Master Level'}, -- 65 {ctype='bit[1]', label='Master Breaker'}, -- 66 {ctype='bit[15]', label='_junk3'}, -- 66 From 5ade870f842c7be518f6d9112b2592c25072ee2c Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Thu, 11 Nov 2021 07:51:27 -0700 Subject: [PATCH 0716/1002] Update Master Level 2 Changed to use boolbits and added Master Levels menu display data --- addons/libs/packets/fields.lua | 47 +++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 5133d02555..36b4f66767 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1519,6 +1519,45 @@ fields.incoming[0x01B] = L{ {ctype='unsigned char', label='Mentor Icon', fn=e+{'mentor icon'}},-- 65 {ctype='unsigned char', label='Mastery Rank'}, -- 66 {ctype='unsigned char', label='_unknown8'}, -- 67 + {ctype='bit[1]', label='_junk1'}, -- 68 + {ctype='boolbit', label='Warrior Master'}, -- 68 Indicates if the job is mastered, but only after receiving "Master Breaker" KI. Used to populate "Master Levels" Menu + {ctype='boolbit', label='Monk Master'}, -- 68 + {ctype='boolbit', label='White Mage Master'}, -- 68 + {ctype='boolbit', label='Black Mage Master'}, -- 68 + {ctype='boolbit', label='Red Mage Master'}, -- 68 + {ctype='boolbit', label='Thief Master'}, -- 68 + {ctype='boolbit', label='Paladin Master'}, -- 68 + {ctype='boolbit', label='Dark Knight Master'}, -- 69 + {ctype='boolbit', label='Beastmaster Master'}, -- 69 + {ctype='boolbit', label='Bard Master'}, -- 69 + {ctype='boolbit', label='Ranger Master'}, -- 69 + {ctype='boolbit', label='Samurai Master'}, -- 69 + {ctype='boolbit', label='Ninja Master'}, -- 69 + {ctype='boolbit', label='Dragoon Master'}, -- 69 + {ctype='boolbit', label='Summoner Master'}, -- 69 + {ctype='boolbit', label='Blue Mage Master'}, -- 6A + {ctype='boolbit', label='Corsair Master'}, -- 6A + {ctype='boolbit', label='Puppetmaster Master'}, -- 6A + {ctype='boolbit', label='Dancer Master'}, -- 6A + {ctype='boolbit', label='Scholar Master'}, -- 6A + {ctype='boolbit', label='Geomancer Master'}, -- 6A + {ctype='boolbit', label='Rune Fencer Master'}, -- 6A + {ctype='bit[1]', label='_junk2'}, -- 6A + {ctype='unsigned short', label='_junk3'}, -- 6B + {ctype='unsigned char', label='Warrior Master Level'}, -- 6D + {ctype='unsigned char', label='Monk Master Level'}, -- 6E + {ctype='unsigned char', label='White Mage Master Level'}, -- 6F + {ctype='unsigned char', label='Black Mage Master Level'}, -- 70 + {ctype='unsigned char', label='Red Mage Master Level'}, -- 71 + {ctype='unsigned char', label='Thief Master Level'}, -- 72 + {ctype='unsigned char', label='Paladin Master Level'}, -- 73 + {ctype='unsigned char', label='Dark Knight Master Level'}, -- 74 + {ctype='unsigned char', label='Beastmaster Master Level'}, -- 75 + {ctype='unsigned char', label='Bard Master Level'}, -- 76 + {ctype='unsigned char', label='Dancer Master Level'}, -- 77 + {ctype='unsigned char', label='Scholar Master Level'}, -- 78 + {ctype='unsigned char', label='Geomancer Master Level'}, -- 79 + {ctype='unsigned char', label='Rune Fencer Master Level'}, -- 7A } -- Inventory Count @@ -2993,7 +3032,7 @@ fields.incoming[0x061] = L{ {ctype='unsigned int', label='_junk2'}, -- 60 {ctype='unsigned char', label='_unknown7'}, -- 64 {ctype='unsigned char', label='Master Level'}, -- 65 - {ctype='bit[1]', label='Master Breaker'}, -- 66 + {ctype='boolbit', label='Master Breaker'}, -- 66 {ctype='bit[15]', label='_junk3'}, -- 66 {ctype='unsigned int', label='Current Exemplar Points'}, -- 68 {ctype='unsigned int', label='Required Exemplar Points'}, -- 6C @@ -3382,7 +3421,7 @@ func.incoming[0x0C9][0x01] = L{ {ctype='unsigned char', label='Sub Job Level'}, -- 25 {ctype='unsigned char', label='Main Job', fn=job}, -- 26 {ctype='unsigned char', label='Master Level'}, -- 27 - {ctype='bit[1]', label='Master Breaker'}, -- 28 + {ctype='boolbit', label='Master Breaker'}, -- 28 {ctype='bit[7]', label='_junk2'}, -- 28 {ctype='data[43]', label='_unknown5'}, -- 29 At least the first two bytes and the last twelve bytes are junk, possibly more } @@ -3467,7 +3506,7 @@ fields.incoming[0x0DD] = L{ {ctype='unsigned char', label='Sub job', fn=job}, -- 24 {ctype='unsigned char', label='Sub job level'}, -- 25 {ctype='unsigned char', label='Master Level'}, -- 26 - {ctype='bit[1]', label='Master Breaker'}, -- 27 + {ctype='boolbit', label='Master Breaker'}, -- 27 {ctype='bit[7]', label='_junk2'}, -- 27 {ctype='char*', label='Name'}, -- 28 } @@ -3499,7 +3538,7 @@ fields.incoming[0x0DF] = L{ {ctype='unsigned char', label='Sub job', fn=job}, -- 22 {ctype='unsigned char', label='Sub job level'}, -- 23 {ctype='unsigned char', label='Master Level'}, -- 24 - {ctype='bit[1]', label='Master Breaker'}, -- 25 + {ctype='boolbit', label='Master Breaker'}, -- 25 {ctype='bit[7]', label='_junk2'}, -- 25 } From 22b865b5a08d919688a2a2182745056377596166 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Thu, 11 Nov 2021 08:44:12 -0700 Subject: [PATCH 0717/1002] Master Levels Update 2 Change to use Refs --- addons/libs/packets/fields.lua | 45 +++++++--------------------------- 1 file changed, 9 insertions(+), 36 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 36b4f66767..e4baefcdc4 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1490,6 +1490,13 @@ fields.incoming[0x017] = function() end end() +types.job_master= L{ + {ctype='boolbit', label='Master'} +} +types.job_master_level= L{ + {ctype='unsigned char', label='Master Level'} +} + -- Job Info fields.incoming[0x01B] = L{ {ctype='unsigned int', label='_unknown1'}, -- 04 Observed value of 05 @@ -1520,44 +1527,10 @@ fields.incoming[0x01B] = L{ {ctype='unsigned char', label='Mastery Rank'}, -- 66 {ctype='unsigned char', label='_unknown8'}, -- 67 {ctype='bit[1]', label='_junk1'}, -- 68 - {ctype='boolbit', label='Warrior Master'}, -- 68 Indicates if the job is mastered, but only after receiving "Master Breaker" KI. Used to populate "Master Levels" Menu - {ctype='boolbit', label='Monk Master'}, -- 68 - {ctype='boolbit', label='White Mage Master'}, -- 68 - {ctype='boolbit', label='Black Mage Master'}, -- 68 - {ctype='boolbit', label='Red Mage Master'}, -- 68 - {ctype='boolbit', label='Thief Master'}, -- 68 - {ctype='boolbit', label='Paladin Master'}, -- 68 - {ctype='boolbit', label='Dark Knight Master'}, -- 69 - {ctype='boolbit', label='Beastmaster Master'}, -- 69 - {ctype='boolbit', label='Bard Master'}, -- 69 - {ctype='boolbit', label='Ranger Master'}, -- 69 - {ctype='boolbit', label='Samurai Master'}, -- 69 - {ctype='boolbit', label='Ninja Master'}, -- 69 - {ctype='boolbit', label='Dragoon Master'}, -- 69 - {ctype='boolbit', label='Summoner Master'}, -- 69 - {ctype='boolbit', label='Blue Mage Master'}, -- 6A - {ctype='boolbit', label='Corsair Master'}, -- 6A - {ctype='boolbit', label='Puppetmaster Master'}, -- 6A - {ctype='boolbit', label='Dancer Master'}, -- 6A - {ctype='boolbit', label='Scholar Master'}, -- 6A - {ctype='boolbit', label='Geomancer Master'}, -- 6A - {ctype='boolbit', label='Rune Fencer Master'}, -- 6A + {ref=types.job_master, lookup={res.jobs, 0x01}, count=0x16}, -- 68 {ctype='bit[1]', label='_junk2'}, -- 6A {ctype='unsigned short', label='_junk3'}, -- 6B - {ctype='unsigned char', label='Warrior Master Level'}, -- 6D - {ctype='unsigned char', label='Monk Master Level'}, -- 6E - {ctype='unsigned char', label='White Mage Master Level'}, -- 6F - {ctype='unsigned char', label='Black Mage Master Level'}, -- 70 - {ctype='unsigned char', label='Red Mage Master Level'}, -- 71 - {ctype='unsigned char', label='Thief Master Level'}, -- 72 - {ctype='unsigned char', label='Paladin Master Level'}, -- 73 - {ctype='unsigned char', label='Dark Knight Master Level'}, -- 74 - {ctype='unsigned char', label='Beastmaster Master Level'}, -- 75 - {ctype='unsigned char', label='Bard Master Level'}, -- 76 - {ctype='unsigned char', label='Dancer Master Level'}, -- 77 - {ctype='unsigned char', label='Scholar Master Level'}, -- 78 - {ctype='unsigned char', label='Geomancer Master Level'}, -- 79 - {ctype='unsigned char', label='Rune Fencer Master Level'}, -- 7A + {ref=types.job_master_level,lookup={res.jobs, 0x01}, count=0x16}, -- 6D } -- Inventory Count From ffa2cce145973ae61bbb5f3ba88804108ce70e5a Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Thu, 11 Nov 2021 08:47:11 -0700 Subject: [PATCH 0718/1002] Master Level Update 2 Re-add Master flags comment --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index e4baefcdc4..77f3f44065 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1527,7 +1527,7 @@ fields.incoming[0x01B] = L{ {ctype='unsigned char', label='Mastery Rank'}, -- 66 {ctype='unsigned char', label='_unknown8'}, -- 67 {ctype='bit[1]', label='_junk1'}, -- 68 - {ref=types.job_master, lookup={res.jobs, 0x01}, count=0x16}, -- 68 + {ref=types.job_master, lookup={res.jobs, 0x01}, count=0x16}, -- 68 Indicates if the job is mastered, but only after receiving "Master Breaker" KI. Used to populate "Master Levels" Menu {ctype='bit[1]', label='_junk2'}, -- 6A {ctype='unsigned short', label='_junk3'}, -- 6B {ref=types.job_master_level,lookup={res.jobs, 0x01}, count=0x16}, -- 6D From cf18fa94f889d2c5174d1d4bbc1d436d5fb53393 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Thu, 11 Nov 2021 08:48:25 -0700 Subject: [PATCH 0719/1002] Master Level Update 2 spacing fix --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 77f3f44065..769a43ed61 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -3394,7 +3394,7 @@ func.incoming[0x0C9][0x01] = L{ {ctype='unsigned char', label='Sub Job Level'}, -- 25 {ctype='unsigned char', label='Main Job', fn=job}, -- 26 {ctype='unsigned char', label='Master Level'}, -- 27 - {ctype='boolbit', label='Master Breaker'}, -- 28 + {ctype='boolbit', label='Master Breaker'}, -- 28 {ctype='bit[7]', label='_junk2'}, -- 28 {ctype='data[43]', label='_unknown5'}, -- 29 At least the first two bytes and the last twelve bytes are junk, possibly more } From bf4ee315782e3a6090992e2f3f81cd250c751c7d Mon Sep 17 00:00:00 2001 From: Dean James Date: Sun, 14 Nov 2021 01:33:52 +0000 Subject: [PATCH 0720/1002] Use set directly in settings table. Use convenient iterator methods. PR feedback. --- addons/MountRoulette/MountRoulette.lua | 42 +++++++++----------------- 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/addons/MountRoulette/MountRoulette.lua b/addons/MountRoulette/MountRoulette.lua index 3dfab1232e..220cae44ec 100644 --- a/addons/MountRoulette/MountRoulette.lua +++ b/addons/MountRoulette/MountRoulette.lua @@ -36,7 +36,7 @@ require('sets') resources = require('resources') config = require('config') settings = config.load({ - blacklist = '' + blacklist = S{} }) math.randomseed(os.time()) @@ -47,13 +47,6 @@ for _, mount in pairs(resources.mounts) do possible_mounts:append(mount.name:lower()) end -blacklist = {} -if string.len(settings.blacklist) > 0 then - for mount in settings.blacklist:gmatch("([^,]+)") do - table.insert(blacklist, mount) - end -end - function update_allowed_mounts() local allowed_mounts_set = S{} local kis = windower.ffxi.get_key_items() @@ -66,8 +59,8 @@ function update_allowed_mounts() end) local mount = possible_mounts[mount_index] - -- Add this to allowed mounts if it is not already there and it is not blacklisted - if not allowed_mounts:contains(mount) and not S(blacklist):contains(mount) then + -- Add this to allowed mounts if it is not blacklisted + if not settings.blacklist:contains(mount) then allowed_mounts_set:add(mount) end end @@ -109,8 +102,8 @@ commands.blacklist = function(args) if not operation then windower.add_to_chat(8, 'Blacklisted mounts:') - for k, v in ipairs(blacklist) do - windower.add_to_chat(8, ' ' .. v) + for mount in settings.blacklist:it() do + windower.add_to_chat(8, ' ' .. mount) end return end @@ -127,24 +120,24 @@ commands.blacklist = function(args) return end - if operation == 'add' and not S(blacklist):contains(mount) then - for k, v in ipairs(T(allowed_mounts)) do - if v == mount then - allowed_mounts:remove(k) + if operation == 'add' and not settings.blacklist:contains(mount) then + for allowed_mount, index in allowed_mounts:it() do + if allowed_mount == mount then + allowed_mounts:remove(index) end end - table.insert(blacklist, mount) + settings.blacklist:add(mount) windower.add_to_chat(8, 'The ' .. mount .. ' mount is now blacklisted') - save_settings() + settings:save() elseif operation == 'remove' then - for k, v in ipairs(blacklist) do - if v == mount then - table.remove(blacklist, k) + for blacklisted_mount in settings.blacklist:it() do + if blacklisted_mount == mount then + settings.blacklist:remove(mount) end end allowed_mounts:append(mount) windower.add_to_chat(8, 'The ' .. mount .. ' mount is no longer blacklisted') - save_settings() + settings:save() end end @@ -167,8 +160,3 @@ windower.register_event('addon command', function(command, ...) commands.help() end end) - -function save_settings() - settings.blacklist = table.concat(blacklist, ",") - settings:save() -end From 7620dd219cd618239889fa535ef30b703a275908 Mon Sep 17 00:00:00 2001 From: Byrth Date: Sun, 14 Nov 2021 09:54:54 -0500 Subject: [PATCH 0721/1002] the table's hex keys are interpreted as unsigned --- addons/libs/packets/fields.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 769a43ed61..bdc9b782f7 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2719,9 +2719,9 @@ enums.quest_mission_log = { [0x00E8] = 'Completed Abyssea Quests', [0x00F0] = 'Current Adoulin Quests', [0x00F8] = 'Completed Adoulin Quests', - [0x0100] = 'Current Coalition Quests', - [0x0108] = 'Completed Coalition Quests', - [0xFFFF] = 'Current Missions', + [0x0100] = 'Current Coalition Quests', + [0x0108] = 'Completed Coalition Quests', + [0xFFFF] = 'Current Missions', } -- There are 27 variations of this packet to populate different quest information. @@ -2737,7 +2737,7 @@ fields.incoming[0x056] = function (data, type) end func.incoming[0x056].type = L{ - {ctype='short', label='Type', fn=e+{'quest_mission_log'}} -- 24 + {ctype='unsigned short',label='Type', fn=e+{'quest_mission_log'}} -- 24 } func.incoming[0x056][0x0080] = L{ From 295e1fb7d950e77835a3945d7312c89d64ce1749 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Tue, 23 Nov 2021 18:32:25 -0700 Subject: [PATCH 0722/1002] Update Pointwatch.lua 1) Add support for Exemplar Points 2) Partial rework of packets to both utilize the packets library, and to take advantage of last_incoming when it is first loaded 3) Partial rework of Key Item detection for Dynamis --- addons/pointwatch/pointwatch.lua | 163 +++++++++++++++++++------------ 1 file changed, 102 insertions(+), 61 deletions(-) diff --git a/addons/pointwatch/pointwatch.lua b/addons/pointwatch/pointwatch.lua index 8eac64d95c..a2bd623426 100644 --- a/addons/pointwatch/pointwatch.lua +++ b/addons/pointwatch/pointwatch.lua @@ -24,17 +24,19 @@ --(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS --SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -texts = require 'texts' -config = require 'config' -require 'sets' -res = require 'resources' -require 'statics' -messages = require 'message_ids' -require 'pack' +texts = require('texts') +config = require('config') +require('sets') +res = require('resources') +require('statics') +messages = require('message_ids') +packets = require('packets') +require('pack') +require('chat') _addon.name = 'PointWatch' _addon.author = 'Byrth' -_addon.version = 0.150811 +_addon.version = 0.211112 _addon.command = 'pw' settings = config.load('data\\settings.xml',default_settings) @@ -44,31 +46,35 @@ box = texts.new('${current_string}',settings.text_box_settings,settings) box.current_string = '' box:show() -initialize() +granule_KIs = res.key_items:en(function(x) return x:endswith('granules of time') end):map(function(ki) + return { + id=ki.id, + type=math.floor(ki.id/0x200), + offset=ki.id%0x200, + name=ki.en:match('%w+'):ucfirst(), + } +end) -windower.register_event('incoming chunk',function(id,org,modi,is_injected,is_blocked) - if is_injected then return end - if id == 0x29 then -- Action Message, used in Abyssea for xp - local val = org:unpack('I',0xD) - local msg = org:unpack('H',0x19)%1024 - exp_msg(val,msg) - elseif id == 0x2A then -- Resting message +packet_initiators = L{0x02A,0x055,0x061,0x063,0x110} +packet_handlers = { + [0x029] = function(org) -- Action Message, used in Abyssea for xp + local p = packets.parse('incoming',org) + exp_msg(p['Param 1'],p['Message']) + end, + [0x02A] = function(org) -- Resting message + local p = packets.parse('incoming',org) local zone = 'z'..windower.ffxi.get_info().zone if settings.options.message_printing then - print('Message ID: '..(org:unpack('H',0x1B)%2^14)) + print('Message ID: '..p['Message ID']) end if messages[zone] then - local msg = org:unpack('H',0x1B)%2^14 + local msg = p['Message ID'] for i,v in pairs(messages[zone]) do - if tonumber(v) and v + messages[zone].offset == msg then - local param_1 = org:unpack('I',0x9) - local param_2 = org:unpack('I',0xD) - local param_3 = org:unpack('I',0x11) - local param_4 = org:unpack('I',0x15) - -- print(param_1,param_2,param_3,param_4) -- DEBUGGING STATEMENT ------------------------- + if tonumber(v) and v + messages[zone].offset == msg then + -- print(p['Param 1'],p['Param 2'],p['Param 3'],p['Param 4']) -- DEBUGGING STATEMENT ------------------------- if zone_message_functions[i] then - zone_message_functions[i](param_1,param_2,param_3,param_4) + zone_message_functions[i](p['Param 1'],p['Param 2'],p['Param 3'],p['Param 4']) end if i:contains("visitant_status_") then abyssea.update_time = os.clock() @@ -76,50 +82,75 @@ windower.register_event('incoming chunk',function(id,org,modi,is_injected,is_blo end end end - elseif id == 0x2D then - local val = org:unpack('I',0x11) - local msg = org:unpack('H',0x19)%1024 - exp_msg(val,msg) - elseif id == 0x55 then - if org:byte(0x85) == 3 then - local dyna_KIs = math.floor((org:byte(6)%64)/2) -- 5 bits (32, 16, 8, 4, and 2 originally -> shifted to 16, 8, 4, 2, and 1) - dynamis._KIs = { - ['Crimson'] = dyna_KIs%2 == 1, - ['Azure'] = math.floor(dyna_KIs/2)%2 == 1, - ['Amber'] = math.floor(dyna_KIs/4)%2 == 1, - ['Alabaster'] = math.floor(dyna_KIs/8)%2 == 1, - ['Obsidian'] = math.floor(dyna_KIs/16) == 1, - } - if dynamis_map[dynamis.zone] then - dynamis.time_limit = 3600 - for KI,TE in pairs(dynamis_map[dynamis.zone]) do - if dynamis._KIs[KI] then - dynamis.time_limit = dynamis.time_limit + TE*60 + end, + [0x02D] = function(org) + local p = packets.parse('incoming',org) + exp_msg(p['Param 1'],p['Message']) + end, + [0x055] = function(org) + local p = packets.parse('incoming',org) + --print(p['Type'],p['Key item available'], p['Key item available']:byte(1),p['Key item available']:byte(2)) + for _,ki in pairs(granule_KIs) do + if p['Type'] == ki.type then + local byte = p['Key item available']:byte(math.floor(ki.offset/8)+1) + local flag = bit.band(bit.rshift(byte, ki.offset % 8), 1) + --print('byte', byte, 'offset', ki.offset % 8, 'flag', flag) + if flag == 1 then + dynamis._KIs[ki.name] = true + if dynamis_map[dynamis.zone] then + dynamis.time_limit = 3600 + for KI,TE in pairs(dynamis_map[dynamis.zone]) do + if dynamis._KIs[KI] then + dynamis.time_limit = dynamis.time_limit + TE*60 + end + end + update_box() end end - update_box() end end - elseif id == 0x61 then - xp.current = org:unpack('H',0x11) - xp.tnl = org:unpack('H',0x13) - accolades.current = math.floor(org:byte(0x5A)/4) + org:byte(0x5B)*2^6 + org:byte(0x5C)*2^14 - elseif id == 0x63 and org:byte(5) == 2 then - lp.current = org:unpack('H',9) - lp.number_of_merits = org:byte(11)%128 - lp.maximum_merits = org:byte(0x0D)%128 - elseif id == 0x63 and org:byte(5) == 5 then - local offset = windower.ffxi.get_player().main_job_id*6+13 -- So WAR (ID==1) starts at byte 19 - cp.current = org:unpack('H',offset) - cp.number_of_job_points = org:unpack('H',offset+2) - elseif id == 0x110 then - sparks.current = org:unpack('I',5) - elseif id == 0xB and box:visible() then + end, + [0x061] = function(org) + local p = packets.parse('incoming',org) + xp.current = p['Current EXP'] + xp.tnl = p['Required EXP'] + accolades.current = p['Unity Points'] + ep.current = p['Current Exemplar Points'] + ep.tnml = p['Required Exemplar Points'] + end, + [0x063] = function(org) + local p = packets.parse('incoming',org) + if p['Order'] == 2 then + lp.current = p['Limit Points'] + lp.number_of_merits = p['Merit Points'] + lp.maximum_merits = p['Max Merit Points'] + elseif p['Order'] == 5 then + local job = windower.ffxi.get_player().main_job_full + cp.current = p[job..' Capacity Points'] + cp.number_of_job_points = p[job..' Job Points'] + end + end, + [0x110] = function(org) + local p = packets.parse('incoming',org) + sparks.current = p['Sparks Total'] + end, + [0xB] = function(org) zoning_bool = true box:hide() - elseif id == 0xA and zoning_bool then + end, + [0xA] = function(org) zoning_bool = nil box:show() + end, +} + +initialize() + +windower.register_event('incoming chunk',function(id,org,modi,is_injected,is_blocked) + if is_injected or is_blocked then return end + local handler = packet_handlers[id] + if handler then + handler(org,modi) end end) @@ -195,6 +226,7 @@ function update_box() end cp.rate = analyze_points_table(cp.registry) xp.rate = analyze_points_table(xp.registry) + ep.rate = analyze_points_table(ep.registry) if dynamis.entry_time ~= 0 and dynamis.entry_time+dynamis.time_limit-os.clock() > 0 then dynamis.time_remaining = os.date('!%H:%M:%S',dynamis.entry_time+dynamis.time_limit-os.clock()) dynamis.KIs = X_or_O(dynamis._KIs.Crimson)..X_or_O(dynamis._KIs.Azure)..X_or_O(dynamis._KIs.Amber)..X_or_O(dynamis._KIs.Alabaster)..X_or_O(dynamis._KIs.Obsidian) @@ -323,6 +355,15 @@ function exp_msg(val,msg) -- If a merit point was not gained, lp.current = math.min(lp.current,lp.tnm-1) end + elseif msg == 810 then + ep.registry[t] = (ep.registry[t] or 0) + val + if ep.tnl and ep.current >= ep.tnl then + ep.current = ep.current - ep.tnl + end end update_box() end + +function max_color(str,val,max,r,g,b) + return val >= max and tostring(str):text_color(r,g,b) or tostring(str) or "" +end From 3190cb63950572de57596c1914149cd44107a5de Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Tue, 23 Nov 2021 18:37:26 -0700 Subject: [PATCH 0723/1002] Update Pointwatch - Statics.lua - Exemplar Points --- addons/pointwatch/statics.lua | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/addons/pointwatch/statics.lua b/addons/pointwatch/statics.lua index 902cc46dcf..eee27f3f5a 100644 --- a/addons/pointwatch/statics.lua +++ b/addons/pointwatch/statics.lua @@ -28,9 +28,9 @@ --Default settings file: default_settings = { strings = { - default = "xp.current..'/'..xp.tnl..'XP '..lp.current..'/'..lp.tnm..'LP ['..lp.number_of_merits..'/'..lp.maximum_merits..'] XP/hr:'..string.format('%.1f',math.floor(xp.rate/100)/10)..'k '..cp.current..'/'..cp.tnjp..'CP ['..cp.number_of_job_points..'] CP/hr:'..string.format('%.1f',math.floor(cp.rate/100)/10)..'k'", - dynamis = "xp.current..'/'..xp.tnl..'XP '..lp.current..'/'..lp.tnm..'LP ['..lp.number_of_merits..'/'..lp.maximum_merits..'] XP/hr:'..string.format('%.1f',math.floor(xp.rate/100)/10)..'k '..cp.current..'/'..cp.tnjp..'CP ['..cp.number_of_job_points..'] '..dynamis.KIs..' '..dynamis.time_remaining", - abyssea = "xp.current..'/'..xp.tnl..'XP '..lp.current..'/'..lp.tnm..'LP ['..lp.number_of_merits..'/'..lp.maximum_merits..'] XP/hr:'..string.format('%.1f',math.floor(xp.rate/100)/10)..'k Amber:'..(abyssea.amber or 0)..'/Azure:'..(abyssea.azure or 0)..'/Ruby:'..(abyssea.ruby or 0)..'/Pearlescent:'..(abyssea.pearlescent or 0)..'/Ebon:'..(abyssea.ebon or 0)..'/Silvery:'..(abyssea.silvery or 0)..'/Golden:'..(abyssea.golden or 0)..'/Time Remaining:'..(abyssea.time_remaining or 0)" + default = "string.format('%d/%dXP %sMerits XP/hr:%.1fk %sJP CP/hr:%.1fk %d/%dEP EP/hr:%.1fk',xp.current,xp.tnl,max_color('%5.2f':format(math.floor(lp.current/lp.tnm*100)/100+lp.number_of_merits),lp.current/lp.tnm+lp.number_of_merits,lp.maximum_merits,58,147,191),math.floor(xp.rate/100)/10,max_color('%6.2f':format(math.floor(cp.current/cp.tnjp*100)/100+cp.number_of_job_points),cp.current/cp.tnjp+cp.number_of_job_points,500,58,147,191),math.floor(cp.rate/100)/10,ep.current,ep.tnml,math.floor(ep.rate/100)/10)", + dynamis = "string.format('%d/%dXP %sMerits XP/hr:%.1fk %sJP CP/hr:%.1fk %d/%dEP %s %s',xp.current,xp.tnl,max_color('%5.2f':format(math.floor(lp.current/lp.tnm*100)/100+lp.number_of_merits),lp.current/lp.tnm+lp.number_of_merits,lp.maximum_merits,58,147,191),math.floor(xp.rate/100)/10,max_color('%6.2f':format(math.floor(cp.current/cp.tnjp*100)/100+cp.number_of_job_points),cp.current/cp.tnjp+cp.number_of_job_points,500,58,147,191),math.floor(cp.rate/100)/10,ep.current,ep.tnml,dynamis.KIs,dynamis.time_remaining or 0)", + abyssea = "string.format('%d/%dXP %sMerits XP/hr:%.1fk %sJP CP/hr:%.1fk %d/%dEP Amber:%d Azure:%d Ruby:%d Pearl:%d Ebon:%d Silver: Gold:%d Time-Remaining:%d',xp.current,xp.tnl,max_color('%5.2f':format(math.floor(lp.current/lp.tnm*100)/100+lp.number_of_merits),lp.current/lp.tnm+lp.number_of_merits,lp.maximum_merits,58,147,191),math.floor(xp.rate/100)/10,max_color('%6.2f':format(math.floor(cp.current/cp.tnjp*100)/100+cp.number_of_job_points),cp.current/cp.tnjp+cp.number_of_job_points,500,58,147,191),math.floor(cp.rate/100)/10,ep.current,ep.tnml,abyssea.amber or 0,abyssea.azure or 0,abyssea.ruby or 0,abyssea.pearlescent or 0,abyssea.ebon or 0,abyssea.silvery or 0,abyssea.golden or 0,abyssea.time_remaining or 0)", }, text_box_settings = { pos = { @@ -110,6 +110,13 @@ function initialize() number_of_merits = 0, maximum_merits = 30, } + + ep = { + registry = {}, + current = 0, + rate = 0, + tnml = 0, + } sparks = { current = 0, @@ -155,5 +162,13 @@ function initialize() cur_func = loadstring("current_string = "..settings.strings.default) setfenv(cur_func,_G) end - + for _,id in ipairs(packet_initiators) do + local handler = packet_handlers[id] + if handler then + local last = windower.packets.last_incoming(id) + if last then + handler(last) + end + end + end end From 30338c630b0730dbccba96794b0bfc9fe3dba665 Mon Sep 17 00:00:00 2001 From: trevor Date: Tue, 23 Nov 2021 21:12:58 -0500 Subject: [PATCH 0724/1002] Use the other libs/dialog --- addons/pointwatch/libs/dialog.lua | 179 ------------------------------ addons/pointwatch/message_ids.lua | 4 +- 2 files changed, 2 insertions(+), 181 deletions(-) delete mode 100644 addons/pointwatch/libs/dialog.lua diff --git a/addons/pointwatch/libs/dialog.lua b/addons/pointwatch/libs/dialog.lua deleted file mode 100644 index fcc9983df0..0000000000 --- a/addons/pointwatch/libs/dialog.lua +++ /dev/null @@ -1,179 +0,0 @@ ---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 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 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. - --- This library was written to help find the ID of a known --- action message corresponding to an entry in the dialog tables. --- While the IDs can be collected in-game, they occasionally --- change and would otherwise need to be manually updated. --- It can also be used to find and decode an entry given the ID. - --- Common parameters: --- dat: The entire content of the zone dialog DAT file --- i.e. local dat = io.open('path/to/dialog/DAT', 'rb'):read('*a') --- entry: The string you are looking for. If you do not know the --- entire string, use dev_find_substring. - -local xor = require('bit').bxor -require('pack') -local string = require('string') -local unpack = string.unpack -local pack = string.pack -local find = string.find - -local dialog = {} - -local function decode(int) - return xor(int, 0x80808080) -end -local encode = decode - -local floor = require('math').floor -local function binary_search(pos, dat, n) - local l, r, m = 1, n - while l < r do - m = floor((l+r)/2) - if decode(unpack(' last_offset then - break - elseif offset == last_offset then - next_pos = #dat+1 - else - next_pos = decode(unpack(' Date: Tue, 23 Nov 2021 19:30:29 -0700 Subject: [PATCH 0725/1002] Update Pointwatch.lua -- minor bugfix typo --- addons/pointwatch/pointwatch.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/pointwatch/pointwatch.lua b/addons/pointwatch/pointwatch.lua index a2bd623426..91b3566095 100644 --- a/addons/pointwatch/pointwatch.lua +++ b/addons/pointwatch/pointwatch.lua @@ -357,8 +357,8 @@ function exp_msg(val,msg) end elseif msg == 810 then ep.registry[t] = (ep.registry[t] or 0) + val - if ep.tnl and ep.current >= ep.tnl then - ep.current = ep.current - ep.tnl + if ep.tnml and ep.current >= ep.tnml then + ep.current = ep.current - ep.tnml end end update_box() From f8015a0adb7e0bf777ebe8d5f27f3af257cb3842 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Tue, 23 Nov 2021 22:29:39 -0700 Subject: [PATCH 0726/1002] update for 0x063 order 2 --- addons/libs/packets/fields.lua | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index bdc9b782f7..b7aba18b93 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2719,9 +2719,9 @@ enums.quest_mission_log = { [0x00E8] = 'Completed Abyssea Quests', [0x00F0] = 'Current Adoulin Quests', [0x00F8] = 'Completed Adoulin Quests', - [0x0100] = 'Current Coalition Quests', - [0x0108] = 'Completed Coalition Quests', - [0xFFFF] = 'Current Missions', + [0x0100] = 'Current Coalition Quests', + [0x0108] = 'Completed Coalition Quests', + [0xFFFF] = 'Current Missions', } -- There are 27 variations of this packet to populate different quest information. @@ -2737,7 +2737,7 @@ fields.incoming[0x056] = function (data, type) end func.incoming[0x056].type = L{ - {ctype='unsigned short',label='Type', fn=e+{'quest_mission_log'}} -- 24 + {ctype='short', label='Type', fn=e+{'quest_mission_log'}} -- 24 } func.incoming[0x056][0x0080] = L{ @@ -3045,7 +3045,14 @@ func.incoming[0x063].base = L{ } func.incoming[0x063][0x02] = L{ - {ctype='data[7]', label='_flags1', fn=bin+{7}}, -- 06 The 3rd bit of the last byte is the flag that indicates whether or not you are xp capped (blue levels) + {ctype='unsigned short', label='_unknown1', const=0x000C}, -- 06 + {ctype='unsigned short', label='Limit Points'}, -- 08 + {ctype='bit[7]', label='Merit Points'}, -- 0A + {ctype='bit[6]', label='Assimilation'}, -- 0A Bonus Blue Magic Points + {ctype='boolbit', label='Limit Breaker'}, -- 0A Level >=75 and have KI + {ctype='boolbit', label='EXP Capped'}, -- 0A + {ctype='boolbit', label='Limit Point Mode'}, -- 0A + {ctype='unsigned char', label='Max Merit Points'}, -- 0C } func.incoming[0x063][0x03] = L{ From 2564bd1cf420feb0ed6b5a26de3f614415c1fef6 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Tue, 23 Nov 2021 23:00:57 -0700 Subject: [PATCH 0727/1002] fix extra spaces --- addons/libs/packets/fields.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index b7aba18b93..22cab0feea 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2719,9 +2719,9 @@ enums.quest_mission_log = { [0x00E8] = 'Completed Abyssea Quests', [0x00F0] = 'Current Adoulin Quests', [0x00F8] = 'Completed Adoulin Quests', - [0x0100] = 'Current Coalition Quests', - [0x0108] = 'Completed Coalition Quests', - [0xFFFF] = 'Current Missions', + [0x0100] = 'Current Coalition Quests', + [0x0108] = 'Completed Coalition Quests', + [0xFFFF] = 'Current Missions', } -- There are 27 variations of this packet to populate different quest information. From 410cd5e8ff975425437e67122e2b85c4699717a7 Mon Sep 17 00:00:00 2001 From: Imisnew Date: Thu, 2 Sep 2021 13:13:23 +0900 Subject: [PATCH 0728/1002] Add support for items in shortcuts addon. --- addons/shortcuts/helper_functions.lua | 22 ++++- addons/shortcuts/shortcuts.lua | 124 +++++++++++++++++++------- addons/shortcuts/statics.lua | 20 +++-- addons/shortcuts/targets.lua | 4 +- 4 files changed, 123 insertions(+), 47 deletions(-) diff --git a/addons/shortcuts/helper_functions.lua b/addons/shortcuts/helper_functions.lua index 092f4cfe69..8ce9ca5838 100644 --- a/addons/shortcuts/helper_functions.lua +++ b/addons/shortcuts/helper_functions.lua @@ -80,19 +80,33 @@ function bracket_closer(str,opener,closer) end ----------------------------------------------------------------------------------- ---Name: strip() +--Name: strip_non_alphanumeric_convert_digits_to_roman() --Args: ----- name (string): Name to be slugged +---- name (string): Name to be stripped ----------------------------------------------------------------------------------- --Returns: ---- string with a gsubbed version of name that removes non-alphanumeric characters, -------- forces the string to lower-case, and converts numbers to Roman numerals, -------- which are upper case. ----------------------------------------------------------------------------------- -function strip(name) +function strip_non_alphanumeric_convert_digits_to_roman(name) return name:gsub('[^%w]',''):lower():gsub('(%d+)',to_roman) end +----------------------------------------------------------------------------------- +--Name: strip_non_alphanumeric_keep_plus() +--Args: +---- name (string): Name to be stripped +----------------------------------------------------------------------------------- +--Returns: +---- string with a gsubbed version of name that removes non-alphanumeric characters, +-------- but allows the character '+', and forces the string to lower-case. Does not +-------- convert numbers to roman numerals. +----------------------------------------------------------------------------------- +function strip_non_alphanumeric_keep_plus(name) + return name:gsub('[^%w+]',''):lower() +end + ----------------------------------------------------------------------------------- --Name: to_roman() @@ -186,6 +200,8 @@ function check_usability(player,resource,id) return true elseif resource == 'mounts' and math.floor((windower.packets.last_incoming(0x0AE):byte(math.floor(id/8)+5)%2^(id%8+1))/2^(id%8)) == 1 then return true + elseif resource == 'items' then + return true end end diff --git a/addons/shortcuts/shortcuts.lua b/addons/shortcuts/shortcuts.lua index a2f5da526e..e850bc0436 100644 --- a/addons/shortcuts/shortcuts.lua +++ b/addons/shortcuts/shortcuts.lua @@ -117,10 +117,16 @@ default_aliases = { cw5="Curing Waltz V", hw="Healing Waltz" } +default_settings = { + include_items = false, +} -aliases = config.load('data\\aliases.xml',default_aliases) +aliases = config.load('data/aliases.xml', default_aliases) +settings = config.load('data/settings.xml', default_settings) config.save(aliases) +config.save(settings) setmetatable(aliases,nil) +setmetatable(settings,nil) require 'statics' @@ -166,12 +172,12 @@ windower.register_event('outgoing text',function(original,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(' ',''):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 = '' @@ -218,11 +224,11 @@ function command_logic(original,modified) 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 @@ -232,17 +238,17 @@ function command_logic(original,modified) 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 ~= '' then -- These commands, like emotes, check, etc., don't need to default to @@ -253,7 +259,7 @@ function command_logic(original,modified) debug_chat('258: input '..lastsent) if logging then - logfile:write('\n\n',tostring(os.clock()),'Original: ',original,'\n(162) ',lastsent) + logfile:write('\n\n',tostring(os.clock()),'Original: ',original,'\n(162) ',lastsent) logfile:flush() end windower.send_command('@input '..lastsent) @@ -339,24 +345,49 @@ end ---- 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 + -- Assume there was not a target suffix on the command. + local preliminary_action_name = table.concat(splitline,' ',1+offset,splitline.n) + local preliminary_action_name_normalized_as_item = strip_non_alphanumeric_keep_plus(preliminary_action_name) + local preliminary_action_name_normalized_as_nonitem = strip_non_alphanumeric_convert_digits_to_roman(preliminary_action_name) + + -- Note: The normalized 'item' name is almost strictly more specific than + -- the normalized 'nonitem' name, and thus the former must be searched + -- before the latter to avoid falsely matching the wrong entry. + local temporary_target_name, normalized_preliminary_action_name + if validabils[preliminary_action_name_normalized_as_item] then + normalized_preliminary_action_name = preliminary_action_name_normalized_as_item + elseif validabils[preliminary_action_name_normalized_as_nonitem] then + normalized_preliminary_action_name = preliminary_action_name_normalized_as_nonitem elseif splitline.n > 1 then - temptarg = valid_target(targ_reps[splitline[splitline.n]] or splitline[splitline.n]) + temporary_target_name = 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 + -- Compute a better name to look up based on the result of the above. + local finalized_action_name = normalized_preliminary_action_name + if temporary_target_name then + finalized_action_name = _raw.table.concat(splitline,' ',1+offset,splitline.n-1) + elseif not normalized_preliminary_action_name then + finalized_action_name = _raw.table.concat(splitline,' ',1+offset,splitline.n) + end + + -- Re-normalize the action name, but using the finalized name + local finalized_action_name_normalized_as_item = strip_non_alphanumeric_keep_plus(finalized_action_name) + local finalized_action_name_normalized_as_nonitem = strip_non_alphanumeric_convert_digits_to_roman(finalized_action_name) + + -- Note: The normalized 'item' name is almost strictly more specific than + -- the normalized 'nonitem' name, and thus the former must be searched + -- before the latter to avoid falsely matching the wrong entry. + local actions_by_normalized_name + if validabils[finalized_action_name_normalized_as_item] then + actions_by_normalized_name = validabils[finalized_action_name_normalized_as_item] + else + actions_by_normalized_name = validabils[finalized_action_name_normalized_as_nonitem] + end - if validabils[strippedabil] then - local options,nonoptions,num_opts, r_line = {},{},0 + if actions_by_normalized_name then + local options,nonoptions,num_opts = {},{},0 local player = windower.ffxi.get_player() - for v in validabils[strippedabil]:it() do + for v in actions_by_normalized_name:it() do if check_usability(player,v.res,v.id) then options[v.res] = v.id num_opts = num_opts + 1 @@ -364,29 +395,54 @@ function interp_text(splitline,offset,modified) 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] + + -- If there are usable options then prioritize: + -- Prefix, if given -> Spells -> Job Abilities -> Weapon Skills -> Monster Skills + local r_type,r_idx,r_line + local opts_to_use = num_opts > 0 and options or nonoptions + if offset == 1 and opts_to_use[command_list[splitline[1]]] then + r_type = command_list[splitline[1]] + else + r_type = (opts_to_use.spells and 'spells') + or (opts_to_use.job_abilities and 'job_abilities') + or (opts_to_use.weapon_skills and 'weapon_skills') + or (opts_to_use.monster_skills and 'monster_skills') + or (opts_to_use.mounts and 'mounts') + or (opts_to_use.items and 'items') + end + if opts_to_use[command_list[splitline[1]]] then + r_idx = opts_to_use[command_list[splitline[1]]] + else + r_idx = opts_to_use.spells + or opts_to_use.job_abilities + or opts_to_use.weapon_skills + or opts_to_use.monster_skills + or opts_to_use.mounts + or opts_to_use.items + end + r_line = res[r_type][r_idx] + + -- Modify r_line to contain 'prefix' for items. + if r_line and not r_line.prefix and r_type == 'items' then + r_line = r_line:copy() + r_line.prefix = '/item' 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 + 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)} + + local out_tab = {prefix = in_game_res_commands[r_line.prefix:gsub("/","")], name = abil_name, target = temporary_target_name 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 diff --git a/addons/shortcuts/statics.lua b/addons/shortcuts/statics.lua index 4fd1219ee9..da321ccc1a 100644 --- a/addons/shortcuts/statics.lua +++ b/addons/shortcuts/statics.lua @@ -37,11 +37,11 @@ validabils = {} -- List of valid prefixes to be interpreted with the resources. The values currently have no use. command_list = {['ja']='job_abilities',['jobability']='job_abilities',['so']='spells',['song']='spells',['ma']='spells',['magic']='spells',['nin']='spells',['ninjutsu']='spells', ['ra']='Ranged Attack',['range']='Ranged Attack',['throw']='Ranged Attack',['shoot']='Ranged Attack',['monsterskill']='monster_skills',['ms']='monster_skills', - ['ws']='weapon_skills',['weaponskill']='weapon_skills',['item']='Ability',['pet']='job_abilities',['mo']='mounts',['mount']='mounts'} - + ['ws']='weapon_skills',['weaponskill']='weapon_skills',['item']='items',['pet']='job_abilities',['mo']='mounts',['mount']='mounts'} + in_game_res_commands = {['ja']='/ja',['jobability']='/ja',['pet']='/ja', ['so']='/ma',['song']='/ma',['ma']='/ma',['magic']='/ma',['nin']='/ma',['ninjutsu']='/ma', - ['monsterskill']='/ms',['ms']='/ms',['ws']='/ws',['weaponskill']='/ws', + ['monsterskill']='/ms',['ms']='/ms',['ws']='/ws',['weaponskill']='/ws',['item']='/item', ['ra']='/ra',['range']='/ra',['throw']='/ra',['shoot']='/ra',['mount']='/mo',['mo']='/mo'} -- List of other commands that might use name completion. @@ -161,7 +161,7 @@ command2_list = { ['returnfaith']=new_cmd_entry(Party_targets,{all=No_targets}), ['bstpet']=new_cmd_entry(No_targets,{['1']=BST_targets,['2']=BST_targets,['3']=BST_targets,['4']=BST_targets,['5']=BST_targets,['6']=BST_targets,['7']=BST_targets}), } - + unhandled_list = {['p']=true,['s']=true,['sh']=true,['yell']=true,['echo']=true,['t']=true,['l']=true,['breaklinkshell']=true} -- List of commands to be ignored @@ -176,7 +176,7 @@ st_targs = T{'','','','',''} targ_reps = {t='',me='',ft='',scan='',bt='',lastst='',r='',pet='',p0='',p1='',p2='',p3='',p4='', p5='',a10='',a11='',a12='',a13='',a14='',a15='',a20='',a21='',a22='',a23='',a24='',a25='', st='',stpc='',stal='',stnpc='',stpt='',focust=''} - + language = 'english' -- windower.ffxi.get_info()['language']:lower() @@ -198,9 +198,10 @@ end -- Iterate through resources and make validabils. function validabils_it(resource) for id,v in pairs(res[resource]) do - if (not v.monster_level and v.prefix) or (v.monster_level and v.monster_level ~= -1 and v.ja:sub(1,1) ~= '#' ) then + if (not v.monster_level and v.prefix) or (v.monster_level and v.monster_level ~= -1 and v.ja:sub(1,1) ~= '#' ) or (v.category == 'Usable') then -- Monster Abilities contains a large number of player-usable moves (but not monstrosity-usable). This excludes them. - make_abil(strip(v.english),resource,id) + local name = resource ~= 'items' and strip_non_alphanumeric_convert_digits_to_roman(v.english) or strip_non_alphanumeric_keep_plus(v.english) + make_abil(name,resource,id) end end end @@ -209,4 +210,7 @@ validabils_it('spells') validabils_it('job_abilities') validabils_it('weapon_skills') validabils_it('monster_skills') -validabils_it('mounts') \ No newline at end of file +validabils_it('mounts') +if settings.include_items then + validabils_it('items') +end diff --git a/addons/shortcuts/targets.lua b/addons/shortcuts/targets.lua index 25ecabb010..8c9816ac3c 100644 --- a/addons/shortcuts/targets.lua +++ b/addons/shortcuts/targets.lua @@ -39,7 +39,7 @@ ----------------------------------------------------------------------------------- function valid_target(targ,flag) local spell_targ - local san_targ = find_san(strip(targ)) + local san_targ = find_san(strip_non_alphanumeric_convert_digits_to_roman(targ)) -- If the target is whitelisted, pass it through. if pass_through_targs:contains(targ:lower()) or st_targs:contains(targ:lower()) or (tonumber(targ:lower()) and windower.ffxi.get_mob_by_id(tonumber(targ:lower()))) then return targ:lower() @@ -48,7 +48,7 @@ function valid_target(targ,flag) local current_target = windower.ffxi.get_mob_by_target('t') local targar = {} for i,v in pairs(windower.ffxi.get_mob_array()) do - if string.find(strip(v.name),san_targ) and (v.valid_target or v.id == windower.ffxi.get_player().id) then -- Malformed pattern somehow + if string.find(strip_non_alphanumeric_convert_digits_to_roman(v.name),san_targ) and (v.valid_target or v.id == windower.ffxi.get_player().id) then -- Malformed pattern somehow -- Handling for whether it's a monster or not if v.is_npc and v.spawn_type ~= 14 and current_target then if v.id == current_target.id then From e7c348cedb3fba9ef0bfb624684113371032a3b8 Mon Sep 17 00:00:00 2001 From: trevor Date: Thu, 25 Nov 2021 21:33:54 -0500 Subject: [PATCH 0729/1002] Swap the order of unpack's arguments. --- addons/libs/dialog.lua | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/addons/libs/dialog.lua b/addons/libs/dialog.lua index 5598175597..9fd054d6e0 100644 --- a/addons/libs/dialog.lua +++ b/addons/libs/dialog.lua @@ -40,7 +40,7 @@ local function binary_search(pos, dat, n) local l, r, m = 1, n while l < r do m = floor((l + r) / 2) - if decode(unpack(' Date: Thu, 25 Nov 2021 21:43:04 -0500 Subject: [PATCH 0730/1002] Handle unsigned int --- addons/libs/dialog.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/addons/libs/dialog.lua b/addons/libs/dialog.lua index 9fd054d6e0..01473c0e3b 100644 --- a/addons/libs/dialog.lua +++ b/addons/libs/dialog.lua @@ -80,7 +80,11 @@ function dialog.get_ids_matching_entry(dat, encoded_entry) local last_offset = decode(unpack(dat, ' Date: Fri, 26 Nov 2021 22:05:08 -0700 Subject: [PATCH 0731/1002] Revert "update for 0x063 order 2" This reverts commit f8015a0adb7e0bf777ebe8d5f27f3af257cb3842. --- addons/libs/packets/fields.lua | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 22cab0feea..bdc9b782f7 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2737,7 +2737,7 @@ fields.incoming[0x056] = function (data, type) end func.incoming[0x056].type = L{ - {ctype='short', label='Type', fn=e+{'quest_mission_log'}} -- 24 + {ctype='unsigned short',label='Type', fn=e+{'quest_mission_log'}} -- 24 } func.incoming[0x056][0x0080] = L{ @@ -3045,14 +3045,7 @@ func.incoming[0x063].base = L{ } func.incoming[0x063][0x02] = L{ - {ctype='unsigned short', label='_unknown1', const=0x000C}, -- 06 - {ctype='unsigned short', label='Limit Points'}, -- 08 - {ctype='bit[7]', label='Merit Points'}, -- 0A - {ctype='bit[6]', label='Assimilation'}, -- 0A Bonus Blue Magic Points - {ctype='boolbit', label='Limit Breaker'}, -- 0A Level >=75 and have KI - {ctype='boolbit', label='EXP Capped'}, -- 0A - {ctype='boolbit', label='Limit Point Mode'}, -- 0A - {ctype='unsigned char', label='Max Merit Points'}, -- 0C + {ctype='data[7]', label='_flags1', fn=bin+{7}}, -- 06 The 3rd bit of the last byte is the flag that indicates whether or not you are xp capped (blue levels) } func.incoming[0x063][0x03] = L{ From 07a44c87b593e6938a1aa4330c3739a8f03c0f13 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Fri, 26 Nov 2021 22:16:03 -0700 Subject: [PATCH 0732/1002] Update 0x063-Order 2 --- addons/libs/packets/fields.lua | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index bdc9b782f7..b7aba18b93 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2719,9 +2719,9 @@ enums.quest_mission_log = { [0x00E8] = 'Completed Abyssea Quests', [0x00F0] = 'Current Adoulin Quests', [0x00F8] = 'Completed Adoulin Quests', - [0x0100] = 'Current Coalition Quests', - [0x0108] = 'Completed Coalition Quests', - [0xFFFF] = 'Current Missions', + [0x0100] = 'Current Coalition Quests', + [0x0108] = 'Completed Coalition Quests', + [0xFFFF] = 'Current Missions', } -- There are 27 variations of this packet to populate different quest information. @@ -2737,7 +2737,7 @@ fields.incoming[0x056] = function (data, type) end func.incoming[0x056].type = L{ - {ctype='unsigned short',label='Type', fn=e+{'quest_mission_log'}} -- 24 + {ctype='short', label='Type', fn=e+{'quest_mission_log'}} -- 24 } func.incoming[0x056][0x0080] = L{ @@ -3045,7 +3045,14 @@ func.incoming[0x063].base = L{ } func.incoming[0x063][0x02] = L{ - {ctype='data[7]', label='_flags1', fn=bin+{7}}, -- 06 The 3rd bit of the last byte is the flag that indicates whether or not you are xp capped (blue levels) + {ctype='unsigned short', label='_unknown1', const=0x000C}, -- 06 + {ctype='unsigned short', label='Limit Points'}, -- 08 + {ctype='bit[7]', label='Merit Points'}, -- 0A + {ctype='bit[6]', label='Assimilation'}, -- 0A Bonus Blue Magic Points + {ctype='boolbit', label='Limit Breaker'}, -- 0A Level >=75 and have KI + {ctype='boolbit', label='EXP Capped'}, -- 0A + {ctype='boolbit', label='Limit Point Mode'}, -- 0A + {ctype='unsigned char', label='Max Merit Points'}, -- 0C } func.incoming[0x063][0x03] = L{ From 10d34abd4a86fedd0f80327ece3dd0a667b62c82 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Fri, 26 Nov 2021 22:19:28 -0700 Subject: [PATCH 0733/1002] un-un-revert a change --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index b7aba18b93..7b9ad2da58 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -3041,7 +3041,7 @@ fields.incoming[0x063] = function(data, type) end func.incoming[0x063].base = L{ - {ctype='unsigned short', label='Order'}, -- 04 + {ctype='unsigned short',label='Type', fn=e+{'quest_mission_log'}} -- 24 } func.incoming[0x063][0x02] = L{ From 9fcf2aca49d12a89260166aed05df25ded95562f Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Fri, 26 Nov 2021 22:24:21 -0700 Subject: [PATCH 0734/1002] fix broken fix --- addons/libs/packets/fields.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 7b9ad2da58..59c4367073 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2737,7 +2737,7 @@ fields.incoming[0x056] = function (data, type) end func.incoming[0x056].type = L{ - {ctype='short', label='Type', fn=e+{'quest_mission_log'}} -- 24 + {ctype='unsigned short',label='Type', fn=e+{'quest_mission_log'}} -- 24 } func.incoming[0x056][0x0080] = L{ @@ -3041,7 +3041,7 @@ fields.incoming[0x063] = function(data, type) end func.incoming[0x063].base = L{ - {ctype='unsigned short',label='Type', fn=e+{'quest_mission_log'}} -- 24 + {ctype='unsigned short', label='Order'}, -- 04 } func.incoming[0x063][0x02] = L{ From e4493465e3fdd38e8113e80b3de7ae7751b04ea2 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Fri, 26 Nov 2021 22:27:06 -0700 Subject: [PATCH 0735/1002] copy paste hates me --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 59c4367073..d0ed63a8d7 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -3041,7 +3041,7 @@ fields.incoming[0x063] = function(data, type) end func.incoming[0x063].base = L{ - {ctype='unsigned short', label='Order'}, -- 04 + {ctype='unsigned short', label='Order'}, -- 04 } func.incoming[0x063][0x02] = L{ From b87b43b29200e04e815ce9f6ad7a16acc28da1e2 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Fri, 26 Nov 2021 22:28:24 -0700 Subject: [PATCH 0736/1002] remove extra spaces --- addons/libs/packets/fields.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index d0ed63a8d7..f22fee46ba 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2719,9 +2719,9 @@ enums.quest_mission_log = { [0x00E8] = 'Completed Abyssea Quests', [0x00F0] = 'Current Adoulin Quests', [0x00F8] = 'Completed Adoulin Quests', - [0x0100] = 'Current Coalition Quests', - [0x0108] = 'Completed Coalition Quests', - [0xFFFF] = 'Current Missions', + [0x0100] = 'Current Coalition Quests', + [0x0108] = 'Completed Coalition Quests', + [0xFFFF] = 'Current Missions', } -- There are 27 variations of this packet to populate different quest information. From 348834a00303b39c4a0470d7df90a95ff1000d3f Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Fri, 26 Nov 2021 22:29:19 -0700 Subject: [PATCH 0737/1002] delete additional spaces --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index f22fee46ba..5f30696fd4 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2721,7 +2721,7 @@ enums.quest_mission_log = { [0x00F8] = 'Completed Adoulin Quests', [0x0100] = 'Current Coalition Quests', [0x0108] = 'Completed Coalition Quests', - [0xFFFF] = 'Current Missions', + [0xFFFF] = 'Current Missions', } -- There are 27 variations of this packet to populate different quest information. From e2cce23eeb0445c3e3eba6d2a49951c90629f464 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Sat, 27 Nov 2021 17:26:54 +0100 Subject: [PATCH 0738/1002] Update fields.lua --- addons/libs/packets/fields.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index b542124e03..fcd2a867b8 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -3160,13 +3160,13 @@ fields.incoming[0x070] = L{ } -- Unity Start --- Only observed being used for Unity fights. Also observed on DynaD and Odyssey for mask//weapon/neck/izzat progression bars. +-- Only observed being used for Unity fights. Also observed on DynaD, Odyssey for mask//weapon/neck/izzat progression bars, Escutcheons progression and mandragora minigame. func.incoming[0x075] = {} fields.incoming[0x075] = function() local fields = func.incoming[0x075] return function(data, type) - return fields.base + (fields[type or data:byte(0x025)] or fields.default) + return fields.base + (fields[type] or (data:byte(0x025) > 1 and fields.bars) or fields.default) end end() @@ -3197,7 +3197,7 @@ func.incoming[0x075].default = L{ {ctype='data[135]', label='_junk1'}, -- 28 Seems to be junk } -func.incoming[0x075][0x03] = L{ +func.incoming[0x075].bars = L{ {ctype='unsigned char', label='_unknown2'}, -- 25 {ctype='unsigned short', label='_unknown3'}, -- 26 Value changes constatly {ref=types.bars, count=5}, -- 28 From f7f1158778a346ea1aebc71a5d587c29ab4c214e Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Wed, 1 Dec 2021 21:09:05 -0700 Subject: [PATCH 0739/1002] Add missing message ID --- addons/pointwatch/pointwatch.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/pointwatch/pointwatch.lua b/addons/pointwatch/pointwatch.lua index 91b3566095..b1f453e474 100644 --- a/addons/pointwatch/pointwatch.lua +++ b/addons/pointwatch/pointwatch.lua @@ -355,7 +355,7 @@ function exp_msg(val,msg) -- If a merit point was not gained, lp.current = math.min(lp.current,lp.tnm-1) end - elseif msg == 810 then + elseif msg == 809 or msg == 810 then ep.registry[t] = (ep.registry[t] or 0) + val if ep.tnml and ep.current >= ep.tnml then ep.current = ep.current - ep.tnml From b9f48a756ee8500688d3c5c05233442b72e2d69b Mon Sep 17 00:00:00 2001 From: Byrth Date: Sat, 4 Dec 2021 04:37:50 -0500 Subject: [PATCH 0740/1002] Add 0x0AD Incoming --- addons/libs/packets/data.lua | 1 + addons/libs/packets/fields.lua | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/addons/libs/packets/data.lua b/addons/libs/packets/data.lua index 31df30741e..ff1a674731 100644 --- a/addons/libs/packets/data.lua +++ b/addons/libs/packets/data.lua @@ -200,6 +200,7 @@ data.incoming[0x08D] = {name='Job Points', description='Contains all jo data.incoming[0x0A0] = {name='Party Map Marker', description='Marks where players are on your map.'} data.incoming[0x0AA] = {name='Spell List', description='Packet that shows the spells that you know.'} data.incoming[0x0AC] = {name='Ability List', description='Packet that shows your current abilities and traits.'} +data.incoming[0x0AD] = {name='MMM List', description='Packet that shows your current Moblin Maze Mongers Vouchers and Runes.'} data.incoming[0x0AE] = {name='Mount List', description='Packet that shows your current mounts.'} data.incoming[0x0B4] = {name='Seek AnonResp', description='Server response sent after you put up party or anon flag.'} data.incoming[0x0B5] = {name='Help Desk Open', description='Sent when you open the Help Desk submenu.'} diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 5f30696fd4..7f13dc333c 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -3338,6 +3338,16 @@ fields.incoming[0x0A0] = L{ --0x0AA, 0x0AC, and 0x0AE are all bitfields where the lsb indicates whether you have index 0 of the related resource. +-- Moblin Maze Mongers information +-- It appears that they anticipated a substantial expansion of the system, +-- but field sizes here are limited to the available items. +fields.incoming[0x0AD] = L{ + {ctype='bit[16]', label='Maze Vouchers'}, + {ctype='data[6]', label='_junk1'}, + {ctype='bit[128]', label='Maze Runes'}, + {ctype='data[0x68]', label="_junk2"}, +} + -- Help Desk submenu open fields.incoming[0x0B5] = L{ {ctype='data[0x14]', label='_unknown1'}, -- 04 From cc0fd2eec1e046f60f887d8ce8cffa685b12b851 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Wed, 8 Dec 2021 14:52:40 +0100 Subject: [PATCH 0741/1002] [fields.lua] Fix for Accolades Fix for Accolades (Unity points) --- addons/libs/packets/fields.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 7f13dc333c..be0a844d54 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2999,8 +2999,8 @@ fields.incoming[0x061] = L{ {ctype='unsigned char', label='_unknown5'}, -- 57 Always 00 for me {ctype='bit[5]', label='Unity ID'}, -- 58 0=None, 1=Pieuje, 2=Ayame, 3=Invincible Shield, 4=Apururu, 5=Maat, 6=Aldo, 7=Jakoh Wahcondalo, 8=Naja Salaheem, 9=Flavira {ctype='bit[5]', label='Unity Rank'}, -- 58 Danger, 00ing caused my client to crash - {ctype='bit[16]', label='Unity Points'}, -- 59 - {ctype='bit[6]', label='_unknown6'}, -- 5A No obvious function + {ctype='bit[17]', label='Unity Points'}, -- 59 + {ctype='bit[5]', label='_unknown6'}, -- 5A No obvious function {ctype='unsigned int', label='_junk1'}, -- 5C {ctype='unsigned int', label='_junk2'}, -- 60 {ctype='unsigned char', label='_unknown7'}, -- 64 From 206eb6efea401a10c8250375d18b6c3c1959d5d7 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Fri, 10 Dec 2021 05:33:11 -0500 Subject: [PATCH 0742/1002] Box Destroyer Dec Update / Dressup + 2 items --- addons/DressUp/body.lua | 2 ++ addons/DressUp/head.lua | 1 + addons/boxdestroyer/messages.lua | 48 ++++++++++++++++---------------- 3 files changed, 27 insertions(+), 24 deletions(-) diff --git a/addons/DressUp/body.lua b/addons/DressUp/body.lua index d91a3c7c02..d0c414c774 100644 --- a/addons/DressUp/body.lua +++ b/addons/DressUp/body.lua @@ -1013,6 +1013,8 @@ models.body[27924] = { name = "Thurandaut Tabard" , enl = "thurandaut tabard", m models.body[27925] = { name = "Karieyh Haubert" , enl = "karieyh haubert", model = 8534} models.body[27926] = { name = "Geomancy Tunic" , enl = "geomancy tunic", model = 8500} --8508 Taru M models.body[27927] = { name = "Runeist Coat" , enl = "runeist coat", model = 8530} +models.body[27854] = { name = "Mandra. Suit" , enl = "mandragora suit", model = 8568} + models.body[50000] = { name = "Volunteer Solider Body" , model = 8365 } models.body[50001] = { name = "Chasuble (Male Only)", model = 8369 } diff --git a/addons/DressUp/head.lua b/addons/DressUp/head.lua index 385e86f846..255bfa9edc 100644 --- a/addons/DressUp/head.lua +++ b/addons/DressUp/head.lua @@ -962,6 +962,7 @@ models.head[27784] = { name = "Thurandaut Chapeau" , enl = "thurandaut chapeau", models.head[27785] = { name = "Karieyh Morion" , enl = "karieyh morion", model = 4438} models.head[27786] = { name = "Geomancy Galero" , enl = "geomancy galero", model = 4404} models.head[27787] = { name = "Runeist Bandeau" , enl = "runeist bandeau", model = 4434} +models.head[26705] = { name = "Mandra. Masque" , enl = "mandra masque", model = 4472} models.head[40001] = { name = "??? Chapeau" , model = 4257 } models.head[40002] = { name = "Haudrale's Chapeau" , model = 4338 } diff --git a/addons/boxdestroyer/messages.lua b/addons/boxdestroyer/messages.lua index 6624a9520c..198d7c1fc6 100644 --- a/addons/boxdestroyer/messages.lua +++ b/addons/boxdestroyer/messages.lua @@ -1,31 +1,31 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination" for the associated zone IDs - [100] = 8078, + [100] = 8071, [101] = 7509, - [102] = 7929, - [103] = 8104, - [104] = 8669, - [105] = 7720, - [106] = 8094, - [107] = 7555, - [108] = 7624, - [109] = 8487, - [110] = 7611, - [111] = 8588, - [112] = 8190, + [102] = 7922, + [103] = 8097, + [104] = 8662, + [105] = 7713, + [106] = 8087, + [107] = 7548, + [108] = 7617, + [109] = 8480, + [110] = 7604, + [111] = 8581, + [112] = 8183, [113] = 7932, - [114] = 7789, - [115] = 7885, - [116] = 7581, - [117] = 7588, - [118] = 8130, - [119] = 8367, - [120] = 7527, - [121] = 8107, + [114] = 7782, + [115] = 7878, + [116] = 7574, + [117] = 7581, + [118] = 8123, + [119] = 8360, + [120] = 7520, + [121] = 8100, [122] = 7438, - [123] = 7890, - [124] = 7841, - [125] = 7651, - [126] = 8074, + [123] = 7883, + [124] = 7834, + [125] = 7644, + [126] = 8067, [127] = 7355, [128] = 7510, [130] = 7574, From 89208e31172bec7f55b900f7dfd579002172bfa2 Mon Sep 17 00:00:00 2001 From: Byrth Date: Fri, 10 Dec 2021 06:16:45 -0500 Subject: [PATCH 0743/1002] add three items to slip 3 and one to slip 22 --- addons/libs/slips.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 3fd7063b10..ebe9143e96 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -15,7 +15,7 @@ slips.storages = L{29312, 29313, 29314, 29315, 29316, 29317, 29318, 2931 slips.items = { [slips.storages[1]] = L{16084, 14546, 14961, 15625, 15711, 16085, 14547, 14962, 15626, 15712, 16086, 14548, 14963, 15627, 15713, 16087, 14549, 14964, 15628, 15714, 16088, 14550, 14965, 15629, 15715, 16089, 14551, 14966, 15630, 15716, 16090, 14552, 14967, 15631, 15717, 16091, 14553, 14968, 15632, 15718, 16092, 14554, 14969, 15633, 15719, 16093, 14555, 14970, 15634, 15720, 16094, 14556, 14971, 15635, 15721, 16095, 14557, 14972, 15636, 15722, 16096, 14558, 14973, 15637, 15723, 16097, 14559, 14974, 15638, 15724, 16098, 14560, 14975, 15639, 15725, 16099, 14561, 14976, 15640, 15726, 16100, 14562, 14977, 15641, 15727, 16101, 14563, 14978, 15642, 15728, 16102, 14564, 14979, 15643, 15729, 16103, 14565, 14980, 15644, 15730, 16106, 14568, 14983, 15647, 15733, 16107, 14569, 14984, 15648, 15734, 16108, 14570, 14985, 15649, 15735, 16602, 17741, 18425, 18491, 18588, 18717, 18718, 18850, 18943, 16069, 14530, 14940, 15609, 15695, 16062, 14525, 14933, 15604, 15688, 16064, 14527, 14935, 15606, 15690, 18685, 18065, 17851, 18686, 18025, 18435, 18113, 17951, 17715, 18485, 18408, 18365, 18583, 18417, 18388, 16267, 16268, 16269, 16228, 16229, 15911, 15799, 15800, 15990, 17745, 18121, 16117, 14577, 17857}, -- 168 [slips.storages[2]] = L{12421, 12549, 12677, 12805, 12933, 13911, 14370, 14061, 14283, 14163, 12429, 12557, 12685, 12813, 12941, 13924, 14371, 14816, 14296, 14175, 13934, 14387, 14821, 14303, 14184, 13935, 14388, 14822, 14304, 14185, 13876, 13787, 14006, 14247, 14123, 13877, 13788, 14007, 14248, 14124, 13908, 14367, 14058, 14280, 14160, 13909, 14368, 14059, 14281, 14161, 16113, 14573, 14995, 15655, 15740, 16115, 14575, 14997, 15657, 15742, 16114, 14574, 14996, 15656, 15741, 16116, 14576, 14998, 15658, 15743, 12818, 18198, 12946, 18043, 12690, 17659, 12296, 12434, 15471, 15472, 15473, 15508, 15509, 15510, 15511, 15512, 15513, 15514, 17710, 17595, 18397, 18360, 18222, 17948, 18100, 15475, 15476, 15477, 15488, 15961, 14815, 14812, 14813, 15244, 15240, 14488, 14905, 15576, 15661, 15241, 14489, 14906, 15577, 15662, 13927, 14378, 14076, 14308, 14180, 13928, 14379, 14077, 14309, 14181, 10438, 10276, 10320, 10326, 10367, 10439, 10277, 10321, 10327, 10368, 10440, 10278, 10322, 10328, 10369, 10441, 10279, 10323, 10329, 10370, 25734, 25735, 25736, 25737, 25738, 25739, 25740, 25741, 25742, 25743, 25744}, -- 155 - [slips.storages[3]] = L{16155, 11282, 15021, 16341, 11376, 16156, 11283, 15022, 16342, 11377, 16157, 11284, 15023, 16343, 11378, 16148, 14590, 15011, 16317, 15757, 16143, 14591, 15012, 16318, 15758, 16146, 14588, 15009, 16315, 15755, 16147, 14589, 15010, 16316, 15756, 15966, 15967, 19041, 17684, 17685, 11636, 15844, 15934, 16258, 18735, 18734, 16291, 16292, 19042, 15935, 16293, 16294, 15936, 18618, 11588, 11545, 16158, 16159, 16160, 16149, 14583, 15007, 16314, 15751, 16141, 14581, 15005, 16312, 15749, 16142, 14582, 15006, 16313, 15750, 10876, 10450, 10500, 11969, 10600, 10877, 10451, 10501, 11970, 10601, 10878, 10452, 10502, 11971, 10602, 19132, 18551, 11798, 11362, 11363, 11625, 15959, 16259, 22299, 26414, 21623, 26219, 21886, 23792, 23793, 23794, 23795, 23796, 22032, 22043}, -- 109 + [slips.storages[3]] = L{16155, 11282, 15021, 16341, 11376, 16156, 11283, 15022, 16342, 11377, 16157, 11284, 15023, 16343, 11378, 16148, 14590, 15011, 16317, 15757, 16143, 14591, 15012, 16318, 15758, 16146, 14588, 15009, 16315, 15755, 16147, 14589, 15010, 16316, 15756, 15966, 15967, 19041, 17684, 17685, 11636, 15844, 15934, 16258, 18735, 18734, 16291, 16292, 19042, 15935, 16293, 16294, 15936, 18618, 11588, 11545, 16158, 16159, 16160, 16149, 14583, 15007, 16314, 15751, 16141, 14581, 15005, 16312, 15749, 16142, 14582, 15006, 16313, 15750, 10876, 10450, 10500, 11969, 10600, 10877, 10451, 10501, 11970, 10601, 10878, 10452, 10502, 11971, 10602, 19132, 18551, 11798, 11362, 11363, 11625, 15959, 16259, 22299, 26414, 21623, 26219, 21886, 23792, 23793, 23794, 23795, 23796, 22032, 22043, 21530, 22044, 26273}, -- 112 [slips.storages[4]] = L{12511, 12638, 13961, 14214, 14089, 12512, 12639, 13962, 14215, 14090, 13855, 12640, 13963, 14216, 14091, 13856, 12641, 13964, 14217, 14092, 12513, 12642, 13965, 14218, 14093, 12514, 12643, 13966, 14219, 14094, 12515, 12644, 13967, 14220, 14095, 12516, 12645, 13968, 14221, 14096, 12517, 12646, 13969, 14222, 14097, 13857, 12647, 13970, 14223, 14098, 12518, 12648, 13971, 14099, 14224, 13868, 13781, 13972, 14225, 14100, 13869, 13782, 13973, 14226, 14101, 12519, 12649, 13974, 14227, 14102, 12520, 12650, 13975, 14228, 14103, 15265, 14521, 14928, 15600, 15684, 15266, 14522, 14929, 15601, 15685, 15267, 14523, 14930, 15602, 15686, 16138, 14578, 15002, 15659, 15746, 16139, 14579, 15003, 15660, 15747, 16140, 14580, 15004, 16311, 15748, 16678, 17478, 17422, 17423, 16829, 16764, 17643, 16798, 16680, 16766, 17188, 17812, 17771, 17772, 16887, 17532, 17717, 18702, 17858, 19203, 21461, 21124, 20776, 27786, 27926, 28066, 28206, 28346, 27787, 27927, 28067, 28207, 28347}, -- 138 [slips.storages[5]] = L{15225, 14473, 14890, 15561, 15352, 15226, 14474, 14891, 15562, 15353, 15227, 14475, 14892, 15563, 15354, 15228, 14476, 14893, 15564, 15355, 15229, 14477, 14894, 15565, 15356, 15230, 14478, 14895, 15566, 15357, 15231, 14479, 14896, 15567, 15358, 15232, 14480, 14897, 15568, 15359, 15233, 14481, 14898, 15569, 15360, 15234, 14482, 14899, 15570, 15361, 15235, 14483, 14900, 15362, 15571, 15236, 14484, 14901, 15572, 15363, 15237, 14485, 14902, 15573, 15364, 15238, 14486, 14903, 15574, 15365, 15239, 14487, 14904, 15575, 15366, 11464, 11291, 15024, 16345, 11381, 11467, 11294, 15027, 16348, 11384, 11470, 11297, 15030, 16351, 11387, 11475, 11302, 15035, 16357, 11393, 11476, 11303, 15036, 16358, 11394, 11477, 11304, 15037, 16359, 11395}, -- 105 [slips.storages[6]] = L{15072, 15087, 15102, 15117, 15132, 15871, 15073, 15088, 15103, 15118, 15133, 15478, 15074, 15089, 15104, 15119, 15134, 15872, 15075, 15090, 15105, 15120, 15135, 15874, 15076, 15091, 15106, 15121, 15136, 15873, 15077, 15092, 15107, 15122, 15137, 15480, 15078, 15093, 15108, 15123, 15138, 15481, 15079, 15094, 15109, 15124, 15139, 15479, 15080, 15095, 15110, 15125, 15140, 15875, 15081, 15096, 15111, 15126, 15141, 15482, 15082, 15097, 15112, 15127, 15142, 15876, 15083, 15098, 15113, 15128, 15143, 15879, 15084, 15099, 15114, 15129, 15144, 15877, 15085, 15100, 15115, 15130, 15145, 15878, 15086, 15101, 15116, 15131, 15146, 15484, 11465, 11292, 15025, 16346, 11382, 16244, 11468, 11295, 15028, 16349, 11385, 15920, 11471, 11298, 15031, 16352, 11388, 16245, 11478, 11305, 15038, 16360, 11396, 16248, 11480, 11307, 15040, 16362, 11398, 15925}, -- 120 @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757, 25909}, -- 192 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749}, -- 142 SE Skipped an index hence the 0 as one of the items + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750}, -- 143 SE Skipped an index hence the 0 as one of the items [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067, 21680}, --176 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, --115 From d2ac675b35ce0ea96f76888e3ec47bf852052628 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Sun, 12 Dec 2021 18:21:42 +0100 Subject: [PATCH 0744/1002] Libs/resources: Fixed lookup table name generation --- addons/libs/packets.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets.lua b/addons/libs/packets.lua index f3ab5b096d..86c4fbbcb4 100644 --- a/addons/libs/packets.lua +++ b/addons/libs/packets.lua @@ -146,7 +146,7 @@ parse = function(fields, data, index, max, lookup, depth) if lookup then -- Look up index name in provided table local resource = lookup[1][count + lookup[2] - 1] - field.label = '%s %s':format(resource and resource.name or 'Unknown %d':format(count + lookup[2] - 1), field.label) + field.label = '%s %s':format(resource and resource.english or 'Unknown %d':format(count + lookup[2] - 1), field.label) else -- Just increment numerically field.label = '%s %d':format(field.label, count) From 168fa7d9574a6cfbbc3bc0657e48a12e3c6e35fd Mon Sep 17 00:00:00 2001 From: trevor Date: Mon, 13 Dec 2021 22:05:44 -0500 Subject: [PATCH 0745/1002] Make it easy to get the dialog files. --- addons/libs/dialog.lua | 44 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/addons/libs/dialog.lua b/addons/libs/dialog.lua index 01473c0e3b..2cf28f2448 100644 --- a/addons/libs/dialog.lua +++ b/addons/libs/dialog.lua @@ -186,6 +186,50 @@ end dialog.decode_string = dialog.encode_string +-- If a zone has a dialog message dat file, this function will +-- return a file descriptor for it in "read/binary" mode. +function dialog.dat(zone_id) + local dat_id + if zone_id < 256 then + dat_id = zone_id + 6420 + else + dat_id = zone_id + 85335 + end + + local dat_path = windower.ffxi_path + local path + local vtable = dat_path .. 'VTABLE.DAT' + local ftable = dat_path .. 'FTABLE.DAT' + local n = 1 + local rom = dat_path .. 'ROM/' + repeat + local f = io.open(vtable, 'rb') + f:seek('set', dat_id) + if byte(f:read(1)) > 0 then + local f = io.open(ftable, 'rb') + local dat = f:read('*a') + f:close() + + local offset = 2*dat_id+1 + local packed_16bit = byte(dat, offset + 1) * 256 + byte(dat, offset) + local dir = floor(packed_16bit / 128) + local file = packed_16bit - dir * 128 + + path = rom .. tostring(dir) .. '/' .. tostring(file) .. '.DAT' + end + f:close() + n = n + 1 + local d = tostring(n) + rom = dat_path .. 'ROM' .. d .. '/' + vtable = rom .. 'VTABLE' .. d .. '.DAT' + ftable = rom .. 'FTABLE' .. d .. '.DAT' + until path or not windower.dir_exists(rom) + + if path then + return io.open(path, 'rb') + end +end + dialog.dev = {} -- Returns the hex offset of the dialog entry with the given ID. From b4d33cf70ddc28174217132f6d55e27f4f9ba474 Mon Sep 17 00:00:00 2001 From: trevor Date: Tue, 14 Dec 2021 01:01:31 -0500 Subject: [PATCH 0746/1002] Shadowing Turn off shadows to reduce lag --- addons/libs/dialog.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/libs/dialog.lua b/addons/libs/dialog.lua index 2cf28f2448..87c335d8f8 100644 --- a/addons/libs/dialog.lua +++ b/addons/libs/dialog.lua @@ -203,8 +203,8 @@ function dialog.dat(zone_id) local n = 1 local rom = dat_path .. 'ROM/' repeat - local f = io.open(vtable, 'rb') - f:seek('set', dat_id) + local v = io.open(vtable, 'rb') + v:seek('set', dat_id) if byte(f:read(1)) > 0 then local f = io.open(ftable, 'rb') local dat = f:read('*a') @@ -217,7 +217,7 @@ function dialog.dat(zone_id) path = rom .. tostring(dir) .. '/' .. tostring(file) .. '.DAT' end - f:close() + v:close() n = n + 1 local d = tostring(n) rom = dat_path .. 'ROM' .. d .. '/' From a1200c6c3068dd0ff4bb40b82d2a97a59ba9530b Mon Sep 17 00:00:00 2001 From: trevor Date: Tue, 14 Dec 2021 01:26:23 -0500 Subject: [PATCH 0747/1002] Japanese dats --- addons/libs/dialog.lua | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/addons/libs/dialog.lua b/addons/libs/dialog.lua index 87c335d8f8..02f4ef06f8 100644 --- a/addons/libs/dialog.lua +++ b/addons/libs/dialog.lua @@ -188,13 +188,18 @@ dialog.decode_string = dialog.encode_string -- If a zone has a dialog message dat file, this function will -- return a file descriptor for it in "read/binary" mode. -function dialog.dat(zone_id) +function dialog.open_dat_by_zone_id(zone_id, language) local dat_id - if zone_id < 256 then - dat_id = zone_id + 6420 - else - dat_id = zone_id + 85335 - end + if zone_id < 256 then + dat_id = zone_id + 6120 + else + dat_id = zone_id + 85035 + end + if language == 'english' then + dat_id = dat_id + 300 + elseif language ~= 'japanese' then + return io.tmpfile() + end local dat_path = windower.ffxi_path local path From 497f5fbf1158f7a541f8ffb445e61ed34241de3b Mon Sep 17 00:00:00 2001 From: trevor Date: Tue, 14 Dec 2021 02:48:04 -0500 Subject: [PATCH 0748/1002] It would have been funny --- addons/libs/dialog.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/addons/libs/dialog.lua b/addons/libs/dialog.lua index 02f4ef06f8..8be08663b6 100644 --- a/addons/libs/dialog.lua +++ b/addons/libs/dialog.lua @@ -198,7 +198,12 @@ function dialog.open_dat_by_zone_id(zone_id, language) if language == 'english' then dat_id = dat_id + 300 elseif language ~= 'japanese' then - return io.tmpfile() + print( + _addon and _addon.name or '???', + 'Dialog library: open_dat_by_zone_id expected ' + .. '"english" or "japanese". (Got: ' .. language .. ')' + ) + return end local dat_path = windower.ffxi_path From fce08482b6f537acdc567d5b19affe919a6c9b13 Mon Sep 17 00:00:00 2001 From: trevor Date: Tue, 14 Dec 2021 18:43:53 -0500 Subject: [PATCH 0749/1002] Missed formatting --- addons/libs/dialog.lua | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/addons/libs/dialog.lua b/addons/libs/dialog.lua index 8be08663b6..0599fb8efe 100644 --- a/addons/libs/dialog.lua +++ b/addons/libs/dialog.lua @@ -190,21 +190,21 @@ dialog.decode_string = dialog.encode_string -- return a file descriptor for it in "read/binary" mode. function dialog.open_dat_by_zone_id(zone_id, language) local dat_id - if zone_id < 256 then - dat_id = zone_id + 6120 - else - dat_id = zone_id + 85035 - end - if language == 'english' then - dat_id = dat_id + 300 - elseif language ~= 'japanese' then - print( - _addon and _addon.name or '???', - 'Dialog library: open_dat_by_zone_id expected ' - .. '"english" or "japanese". (Got: ' .. language .. ')' - ) - return - end + if zone_id < 256 then + dat_id = zone_id + 6120 + else + dat_id = zone_id + 85035 + end + if language == 'english' then + dat_id = dat_id + 300 + elseif language ~= 'japanese' then + print( + _addon and _addon.name or '???', + 'Dialog library: open_dat_by_zone_id expected ' + .. '"english" or "japanese". (Got: ' .. language .. ')' + ) + return + end local dat_path = windower.ffxi_path local path @@ -215,7 +215,7 @@ function dialog.open_dat_by_zone_id(zone_id, language) repeat local v = io.open(vtable, 'rb') v:seek('set', dat_id) - if byte(f:read(1)) > 0 then + if byte(v:read(1)) > 0 then local f = io.open(ftable, 'rb') local dat = f:read('*a') f:close() From 930a13601ec0fbabe9d16528c568c7aaf19c26a6 Mon Sep 17 00:00:00 2001 From: trevor Date: Tue, 14 Dec 2021 18:50:30 -0500 Subject: [PATCH 0750/1002] Prevent id overlap They're pretty close! --- addons/libs/dialog.lua | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/addons/libs/dialog.lua b/addons/libs/dialog.lua index 0599fb8efe..7565c92bef 100644 --- a/addons/libs/dialog.lua +++ b/addons/libs/dialog.lua @@ -190,10 +190,17 @@ dialog.decode_string = dialog.encode_string -- return a file descriptor for it in "read/binary" mode. function dialog.open_dat_by_zone_id(zone_id, language) local dat_id - if zone_id < 256 then - dat_id = zone_id + 6120 - else + if zone_id > 299 then + -- The English dialog files are currently 300 ids + -- ahead of the Japanese dialog files. If a zone with + -- id 300 or greater is added, SE will have to move to + -- a new range of ids which someone will need to locate. + print('Dialog library: zone id out of range.') + return + elseif zone_id > 255 then dat_id = zone_id + 85035 + else + dat_id = zone_id + 6120 end if language == 'english' then dat_id = dat_id + 300 From 127ef936b48bc2f07f39a0c4c38add9468f299a8 Mon Sep 17 00:00:00 2001 From: trevor Date: Tue, 14 Dec 2021 19:12:40 -0500 Subject: [PATCH 0751/1002] Moved id conversion to dialog lib --- addons/pointwatch/message_ids.lua | 57 ++++++------------------------- 1 file changed, 11 insertions(+), 46 deletions(-) diff --git a/addons/pointwatch/message_ids.lua b/addons/pointwatch/message_ids.lua index e996fdc0d7..9f893399e1 100644 --- a/addons/pointwatch/message_ids.lua +++ b/addons/pointwatch/message_ids.lua @@ -189,53 +189,18 @@ local messages = { local function update_offset(zone_id) -- zone to dat ID mapping for Abyssean zones local t = { - [15] = 6435, -- 23/80 - [45] = 6465, -- 23/110 - [132] = 6552, -- 24/69 - [215] = 6635, -- 25/24 - [216] = 6636, -- 25/25 - [217] = 6637, -- 25/26 - [218] = 6638, -- 25/27 - [253] = 6673, -- 25/62 - [254] = 6674, -- 25/63 + [15] = true, + [45] = true, + [132] = true, + [215] = true, + [216] = true, + [217] = true, + [218] = true, + [253] = true, + [254] = true, } if t[zone_id] then - -- convert dat ID to dat file path - local floor = require('math').floor - local byte = require('string').byte - local dat_id = t[zone_id] - local dat_path = windower.ffxi_path - local path - local vtable = dat_path .. 'VTABLE.DAT' - local ftable = dat_path .. 'FTABLE.DAT' - local n = 1 - local rom = dat_path .. 'ROM/' - repeat - local f = io.open(vtable, 'rb') - f:seek('set', dat_id) - if byte(f:read(1)) > 0 then - local f = io.open(ftable, 'rb') - local offset = 2*dat_id - f:seek('set', offset) - local dat = f:read(2) - f:close() - - local packed_16bit = byte(dat, 2) * 256 + byte(dat, 1) - local dir = floor(packed_16bit / 128) - local file = packed_16bit - dir * 128 - - path = rom .. tostring(dir) .. '/' .. tostring(file) .. '.DAT' - end - f:close() - n = n + 1 - local d = tostring(n) - rom = dat_path .. 'ROM' .. d .. '/' - vtable = rom .. 'VTABLE' .. d .. '.DAT' - ftable = rom .. 'FTABLE' .. d .. '.DAT' - until path or not windower.dir_exists(rom) - if not path then print('Could not convert dat ID', dat_id) return end - -- convert dialog entry to dialog ID local dialog = require('dialog') local search_phrase = string.char( @@ -246,12 +211,12 @@ local function update_offset(zone_id) 229,238,186,160,138,130,160,175,160,211,233,236,246,229,242, 249,186,160,138,131,255,177,128,135 ) - local f = io.open(path, 'rb') + local f = dialog.open_dat_by_zone_id(zone_id, 'english') local dat = f:read('*a') f:close() local res = dialog.get_ids_matching_entry(dat, search_phrase) if #res ~= 1 then - print('In pointwatch/message_ids.lua: matched multiple entries') + print('In pointwatch/message_ids.lua: matched multiple or no entries.') print('Could not update message ID.') return end From cfada1ddf2c21afacd4f4ec50f2d132285b2ae77 Mon Sep 17 00:00:00 2001 From: trevor Date: Thu, 16 Dec 2021 18:26:13 -0500 Subject: [PATCH 0752/1002] Scrape the top two bits off the message ID --- addons/pointwatch/pointwatch.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/pointwatch/pointwatch.lua b/addons/pointwatch/pointwatch.lua index b1f453e474..23fc89587c 100644 --- a/addons/pointwatch/pointwatch.lua +++ b/addons/pointwatch/pointwatch.lua @@ -65,11 +65,11 @@ packet_handlers = { local p = packets.parse('incoming',org) local zone = 'z'..windower.ffxi.get_info().zone if settings.options.message_printing then - print('Message ID: '..p['Message ID']) + print('Message ID: '..bit.band(p['Message ID'], 16383)) end if messages[zone] then - local msg = p['Message ID'] + local msg = bit.band(p['Message ID'], 16383) for i,v in pairs(messages[zone]) do if tonumber(v) and v + messages[zone].offset == msg then -- print(p['Param 1'],p['Param 2'],p['Param 3'],p['Param 4']) -- DEBUGGING STATEMENT ------------------------- From 5a2080536c4f4a275d0ec0c10f0e12e2d84aefa5 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Sun, 19 Dec 2021 13:55:22 -0500 Subject: [PATCH 0753/1002] Exemplar Points Documentation --- addons/pointwatch/ReadMe.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/addons/pointwatch/ReadMe.txt b/addons/pointwatch/ReadMe.txt index b3f1964d22..a0d78fa284 100644 --- a/addons/pointwatch/ReadMe.txt +++ b/addons/pointwatch/ReadMe.txt @@ -32,7 +32,7 @@ Here are the available values: * xp.total = Total Experience Points gained since the last time the addon was loaded (number) * lp.current = Current Experience Points (number from 0 to 55,999 XP) -* lp.tnl = Similar to a "To Next Level", but this value is always 10,000 because that's always the number of Limit Points per merit point. +* lp.tnm = Similar to a "To Next Level", but this value is always 10,000 because that's always the number of Limit Points per merit point. * lp.number_of_merits = Number of merit points you have. * lp.maximum_merits = Maximum number of merits you can store. @@ -42,6 +42,10 @@ Here are the available values: * cp.tnjp = Similar to a "To Next Level", but this value is always 30,000 because that's always the number of CPs per job point. * cp.number_of_job_points = Number of job points you currently have on your current job. +* ep.current = Current Exemplar Points +* ep.rate = Current Exemplar Points gain rate per hour. This is calculated over a 10 minute window and requires at least two gains within the window. +* ep.tnml = Required Exemplar Points for your next Master Level + * sparks.current = Current number of RoE Sparks (number between 0 and 50,000) * sparks.maximum = Maximum number of RoE Sparks (always 50,000) @@ -67,6 +71,7 @@ Here are the available values: Version History: +0.211112 - Added ep.current, ep.rate, and ep.tnml. 0.150811 - Changed job_points from a char to a short. 0.150201 - Added Unity Accolades. 0.141111 - Adjusted Pointwatch to account for a recent packet change. From 087d17378c495f65a783b603c2fde69a6cb66177 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Sun, 19 Dec 2021 16:17:45 -0500 Subject: [PATCH 0754/1002] More modifiers --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index be0a844d54..01e3bb3899 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1792,7 +1792,7 @@ func.incoming[0x028].action_base = L{ {ctype='bit[3]', label='Knockback'}, -- 03:0 Knockback effect, the more value the more distance {ctype='bit[17]', label='Param'}, -- 03:3 {ctype='bit[10]', label='Message'}, -- 06:2 - {ctype='bit[31]', label='_unknown'}, -- 07:4 --Message Modifier? If you get a complete (Resist!) this is set to 2 otherwise a regular Resist is 0. + {ctype='bit[31]', label='_unknown'}, -- 07:4 Message Modifier: Cover=0x01 Resist!=0x02 Magic Burst=0x03 Immunobreak=0x04 Critical Hit=0x05 } func.incoming[0x028].add_effect_base = L{ From b667688fd69c0ec23ca84749d972382622e5fd52 Mon Sep 17 00:00:00 2001 From: Byrth Date: Tue, 21 Dec 2021 06:48:39 -0500 Subject: [PATCH 0755/1002] Update for 0x0B6 outgoing changes --- addons/answeringmachine/answeringmachine.lua | 4 ++-- addons/libs/packets/fields.lua | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/addons/answeringmachine/answeringmachine.lua b/addons/answeringmachine/answeringmachine.lua index 7a86d27708..e73400b7cf 100644 --- a/addons/answeringmachine/answeringmachine.lua +++ b/addons/answeringmachine/answeringmachine.lua @@ -97,8 +97,8 @@ end) windower.register_event('outgoing chunk',function(id,original,modified,injected,blocked) if not blocked and id == 0x0B6 then - local name = trim(original:sub(0x6,0x14)) - local message = trim(original:sub(0x15)) + local name = trim(original:sub(0x07,0x15)) + local message = trim(original:sub(0x16)) if recording[name:upper()] then recording[name:upper()][#recording[name:upper()]+1] = {message=message,outgoing=true,timestamp=os.time(),seen=true} else diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 01e3bb3899..093363760e 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -890,9 +890,9 @@ fields.outgoing[0x0B5] = L{ -- Tell fields.outgoing[0x0B6] = L{ - {ctype='unsigned char', label='_unknown1', const=0x00}, -- 04 00 for a normal tell -- Varying this does nothing. - {ctype='char[15]', label='Target Name'}, -- 05 - {ctype='char*', label='Message'}, -- 14 + {ctype='unsigned short', label='_unknown1', const=0x0003}, -- 04 03 00 for a normal tell -- Varying this did nothing. + {ctype='char[15]', label='Target Name'}, -- 06 + {ctype='char*', label='Message'}, -- 15 } -- Merit Point Increase From 7e6962ccd0bd61dba587ac2b100f9f80085e56c1 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Wed, 22 Dec 2021 20:20:19 -0700 Subject: [PATCH 0756/1002] Correct improper ID range check (GearSwap) --- addons/GearSwap/targets.lua | 44 ++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/addons/GearSwap/targets.lua b/addons/GearSwap/targets.lua index 3e47b74da8..9bac1ae929 100644 --- a/addons/GearSwap/targets.lua +++ b/addons/GearSwap/targets.lua @@ -28,30 +28,34 @@ -- Target Processing -- function valid_target(targ) + local targ = targ or false local spelltarget = {} - local spell_targ - if pass_through_targs[targ] then + + if targ and pass_through_targs[targ] then local j = windower.ffxi.get_mob_by_target(targ) - - if j then spelltarget = target_complete(j) end - - spelltarget.raw = targ - return targ, spelltarget - elseif targ and tonumber(targ) and tonumber(targ) > 255 then - local j = windower.ffxi.get_mob_by_id(tonumber(targ)) - - if j then spelltarget = target_complete(j) end - + if j then + spelltarget = target_complete(j) + end spelltarget.raw = targ return targ, spelltarget - elseif targ and not tonumber(targ) and targ ~= '' then - local mob_array = windower.ffxi.get_mob_array() - for i,v in pairs(mob_array) do - if v.name:lower()==targ:lower() and (not v.is_npc or v.spawn_type == 14) then - spelltarget = target_complete(v) - spelltarget.raw = targ - return targ, spelltarget + elseif targ then + local id = tonumber(targ) + if id then + local j = windower.ffxi.get_mob_by_id(id) + if j then + spelltarget = target_complete(j) + end + spelltarget.raw = targ + return targ, spelltarget + elseif targ ~= '' then + local mob_array = windower.ffxi.get_mob_array() + for i,v in pairs(mob_array) do + if v.name:lower()==targ:lower() and (not v.is_npc or v.spawn_type == 14) then + spelltarget = target_complete(v) + spelltarget.raw = targ + return targ, spelltarget + end end end end @@ -146,4 +150,4 @@ function target_type_check(spell) if spell.targets[temptype] then return true end return false -end \ No newline at end of file +end From fb5dd082517e5b7d2ffbb6fce3b0d14befd70dcd Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Thu, 23 Dec 2021 00:20:50 -0700 Subject: [PATCH 0757/1002] remove unnecessary line and move lower out of loop --- addons/GearSwap/targets.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/GearSwap/targets.lua b/addons/GearSwap/targets.lua index 9bac1ae929..d4f0249e44 100644 --- a/addons/GearSwap/targets.lua +++ b/addons/GearSwap/targets.lua @@ -28,7 +28,6 @@ -- Target Processing -- function valid_target(targ) - local targ = targ or false local spelltarget = {} local spell_targ @@ -49,9 +48,10 @@ function valid_target(targ) spelltarget.raw = targ return targ, spelltarget elseif targ ~= '' then + local targ_name = targ:lower() local mob_array = windower.ffxi.get_mob_array() for i,v in pairs(mob_array) do - if v.name:lower()==targ:lower() and (not v.is_npc or v.spawn_type == 14) then + if v.name:lower()==targ_name and (not v.is_npc or v.spawn_type == 14) then spelltarget = target_complete(v) spelltarget.raw = targ return targ, spelltarget From 83cc01e1eb21d1fefa48eeb5e7cb8993c40482f6 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Sun, 26 Dec 2021 22:45:52 -0500 Subject: [PATCH 0758/1002] Pilgrim/Nomad support/fix --- addons/organizer/items.lua | 2 +- addons/organizer/organizer.lua | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/addons/organizer/items.lua b/addons/organizer/items.lua index 20d9160ae2..56d591a813 100644 --- a/addons/organizer/items.lua +++ b/addons/organizer/items.lua @@ -30,7 +30,7 @@ local bags = {} local item_tab = {} do - local names = {'Nomad Moogle'} -- don't add Pilgrim Moogle to this list, organizer currently does not work in Odyssey. + local names = {'Nomad Moogle','Pilgrim Moogle'} local moogles = {} local poked = false local block_menu = false diff --git a/addons/organizer/organizer.lua b/addons/organizer/organizer.lua index 8e526d9d8c..a9509c08e1 100644 --- a/addons/organizer/organizer.lua +++ b/addons/organizer/organizer.lua @@ -39,7 +39,7 @@ packets = require('packets') _addon.name = 'Organizer' _addon.author = 'Byrth, maintainer: Rooks' -_addon.version = 0.20210721 +_addon.version = 0.20211226 _addon.commands = {'organizer','org'} _static = { @@ -555,7 +555,11 @@ function get_dump_bags() local dump_bags = {} for i,v in pairs(settings.dump_bags) do if i and s_to_bag(i) then - dump_bags[tonumber(v)] = s_to_bag(i) + if windower.ffxi.get_info().mog_house then + dump_bags[tonumber(v)] = s_to_bag(i) + elseif s_to_bag(i) ~= 2 then -- Storage is not available at Nomad Moogles + dump_bags[tonumber(v)] = s_to_bag(i) + end elseif i then org_error('The bag name ("'..tostring(i)..'") in dump_bags entry #'..tostring(v)..' in the ../addons/organizer/data/settings.xml file is not valid.\nValid options are '..tostring(res.bags)) return From 8496aa120d0147a4a082167dcb3dcc4a549ead23 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Tue, 4 Jan 2022 15:52:40 -0700 Subject: [PATCH 0759/1002] GearSwap Motes Command-- set mode with spaces Allow to set a specific mode name with a space in it via `gs c set` (previously would ignore anything after a space, even if contained in quotes) --- addons/GearSwap/libs/Mote-SelfCommands.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/GearSwap/libs/Mote-SelfCommands.lua b/addons/GearSwap/libs/Mote-SelfCommands.lua index 3015e1fcc1..694b2a515d 100644 --- a/addons/GearSwap/libs/Mote-SelfCommands.lua +++ b/addons/GearSwap/libs/Mote-SelfCommands.lua @@ -53,7 +53,7 @@ function handle_set(cmdParams) if state_var then local oldVal = state_var.value - state_var:set(cmdParams[2]) + state_var:set(T{cmdParams:select(2)}:concat(' ')) local newVal = state_var.value local descrip = state_var.description or cmdParams[1] From 0cfbe6d3f2c3718860038c467638d8d4ebdb0cd3 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Tue, 4 Jan 2022 16:08:31 -0700 Subject: [PATCH 0760/1002] Gearswap Motes Command Fix oops, this is the correct change, my bad --- addons/GearSwap/libs/Mote-SelfCommands.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/GearSwap/libs/Mote-SelfCommands.lua b/addons/GearSwap/libs/Mote-SelfCommands.lua index 694b2a515d..082a04ce70 100644 --- a/addons/GearSwap/libs/Mote-SelfCommands.lua +++ b/addons/GearSwap/libs/Mote-SelfCommands.lua @@ -53,7 +53,7 @@ function handle_set(cmdParams) if state_var then local oldVal = state_var.value - state_var:set(T{cmdParams:select(2)}:concat(' ')) + state_var:set(cmdParams:slice(2):concat(' ')) local newVal = state_var.value local descrip = state_var.description or cmdParams[1] From 39a945894a4c9e5b0ece18bc54e38a70797016d3 Mon Sep 17 00:00:00 2001 From: Byrth Date: Sun, 9 Jan 2022 07:52:06 -0500 Subject: [PATCH 0761/1002] Index res.monster_abilities once --- addons/GearSwap/gearswap.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/GearSwap/gearswap.lua b/addons/GearSwap/gearswap.lua index 516840635e..2d5d37129a 100644 --- a/addons/GearSwap/gearswap.lua +++ b/addons/GearSwap/gearswap.lua @@ -113,7 +113,7 @@ require 'actions' packets = require 'packets' -- Resources Checks -if res.items and res.bags and res.slots and res.statuses and res.jobs and res.elements and res.skills and res.buffs and res.spells and res.job_abilities and res.weapon_skills and res.monster_skills and res.action_messages and res.skills and res.monstrosity and res.weather and res.moon_phases and res.races then +if res.items and res.bags and res.slots and res.statuses and res.jobs and res.elements and res.skills and res.buffs and res.spells and res.job_abilities and res.weapon_skills and res.monster_skills and res.action_messages and res.skills and res.monstrosity and res.weather and res.moon_phases and res.races and res.monster_abilities then else error('Missing resources!') end From e740ca35f95bd10c0db0ae68b53ce0a3e82827f4 Mon Sep 17 00:00:00 2001 From: Byrth Date: Sun, 9 Jan 2022 08:02:03 -0500 Subject: [PATCH 0762/1002] Also fix it in the actions library --- addons/libs/actions.lua | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/addons/libs/actions.lua b/addons/libs/actions.lua index 14254ce77c..5ec28658e3 100644 --- a/addons/libs/actions.lua +++ b/addons/libs/actions.lua @@ -356,6 +356,14 @@ local cat_to_res_map = {['weaponskill_finish']='weapon_skills', ['spell_finish'] ['casting_begin']='spells', ['item_begin']='items', ['mob_tp_finish']='monster_abilities', ['avatar_tp_finish']='job_abilities', ['job_ability_unblinkable']='job_abilities', ['job_ability_run']='job_abilities'} +-- This library uses rawget() to index the resources for performance reasons. +-- However, the resources library lazy-loads resources using its metatable. +-- Thus we need to index each of the required resources once to force an eager-load. +for _,resource_name in pairs(cat_to_res_map) do + if not res[resource_name] then + print(resource_name.." not detected.") + end +end local begin_categories = {['weaponskill_begin']=true, ['casting_begin']=true, ['item_begin']=true, ['ranged_begin']=true} local finish_categories = {['melee']=true,['ranged_finish']=true,['weaponskill_finish']=true, ['spell_finish']=true, ['item_finish']=true, ['job_ability']=true, ['mob_tp_finish']=true, ['avatar_tp_finish']=true, ['job_ability_unblinkable']=true, From ad04602c6141c9d7b835499451a48966c6f89e7a Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Sun, 9 Jan 2022 18:51:26 +0100 Subject: [PATCH 0763/1002] Libs/actions: Adjusted to not use rawget for resources --- addons/libs/actions.lua | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/addons/libs/actions.lua b/addons/libs/actions.lua index 5ec28658e3..4ff11b6df4 100644 --- a/addons/libs/actions.lua +++ b/addons/libs/actions.lua @@ -200,9 +200,9 @@ end function actionpacket:get_spell() local info = self:get_targets()():get_actions()():get_basic_info() - if rawget(info,'resource') and rawget(info,'spell_id') and rawget(rawget(res,rawget(info,'resource')),rawget(info,'spell_id')) then + if rawget(info,'resource') and rawget(info,'spell_id') and rawget(res[rawget(info,'resource')],rawget(info,'spell_id')) then local copied_line = {} - for i,v in pairs(rawget(rawget(res,rawget(info,'resource')),rawget(info,'spell_id'))) do + for i,v in pairs(rawget(res[rawget(info,'resource')],rawget(info,'spell_id'))) do rawset(copied_line,i,v) end setmetatable(copied_line,getmetatable(res[rawget(info,'resource')][rawget(info,'spell_id')])) @@ -356,14 +356,6 @@ local cat_to_res_map = {['weaponskill_finish']='weapon_skills', ['spell_finish'] ['casting_begin']='spells', ['item_begin']='items', ['mob_tp_finish']='monster_abilities', ['avatar_tp_finish']='job_abilities', ['job_ability_unblinkable']='job_abilities', ['job_ability_run']='job_abilities'} --- This library uses rawget() to index the resources for performance reasons. --- However, the resources library lazy-loads resources using its metatable. --- Thus we need to index each of the required resources once to force an eager-load. -for _,resource_name in pairs(cat_to_res_map) do - if not res[resource_name] then - print(resource_name.." not detected.") - end -end local begin_categories = {['weaponskill_begin']=true, ['casting_begin']=true, ['item_begin']=true, ['ranged_begin']=true} local finish_categories = {['melee']=true,['ranged_finish']=true,['weaponskill_finish']=true, ['spell_finish']=true, ['item_finish']=true, ['job_ability']=true, ['mob_tp_finish']=true, ['avatar_tp_finish']=true, ['job_ability_unblinkable']=true, From 1094a0a067061507f5520b19c650f82fa497cf69 Mon Sep 17 00:00:00 2001 From: Byrth Date: Mon, 10 Jan 2022 07:35:40 -0500 Subject: [PATCH 0764/1002] Switch indinope to use the modified packet --- addons/indinope/indinope.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/indinope/indinope.lua b/addons/indinope/indinope.lua index e085b2b79b..9e8a6678f5 100644 --- a/addons/indinope/indinope.lua +++ b/addons/indinope/indinope.lua @@ -38,11 +38,11 @@ windower.register_event('incoming chunk', function(id, original, modified, injec if injected or blocked or not offsets[id] then return end offset = offsets[id] - flags = original:byte(offsets[id]) + flags = modified:byte(offsets[id]) -- if any of the bits 0 through 7 are set, a bubble is shown and we want to block it. if bit.band(flags, 0x7F) ~= 0 then - packet = original:sub(1, offset - 1) .. string.char(bit.band(flags, 0x80)) .. original:sub(offset + 1) -- preserve bit 8 (Job Master stars) + packet = modified:sub(1, offset - 1) .. string.char(bit.band(flags, 0x80)) .. modified:sub(offset + 1) -- preserve bit 8 (Job Master stars) return packet end end) From 78af443ee17a778848d9ecd8fe47e135b129f008 Mon Sep 17 00:00:00 2001 From: trevor Date: Mon, 10 Jan 2022 22:35:09 -0500 Subject: [PATCH 0765/1002] Verify logged in. Only update once. --- addons/pointwatch/message_ids.lua | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/addons/pointwatch/message_ids.lua b/addons/pointwatch/message_ids.lua index 9f893399e1..de950c313f 100644 --- a/addons/pointwatch/message_ids.lua +++ b/addons/pointwatch/message_ids.lua @@ -187,20 +187,9 @@ local messages = { } local function update_offset(zone_id) - -- zone to dat ID mapping for Abyssean zones - local t = { - [15] = true, - [45] = true, - [132] = true, - [215] = true, - [216] = true, - [217] = true, - [218] = true, - [253] = true, - [254] = true, - } - - if t[zone_id] then + local z_string = 'z' .. tostring(zone_id) + local m = messages[z_string] + if m and m.name then -- convert dialog entry to dialog ID local dialog = require('dialog') local search_phrase = string.char( @@ -221,12 +210,17 @@ local function update_offset(zone_id) return end - messages['z'..tostring(zone_id)].offset = res[1] - t[zone_id] = nil + m.offset = res[1] + m.name = nil end end -update_offset(windower.ffxi.get_info().zone) +do + local info = windower.ffxi.get_info() + if info.logged_in then + update_offset(info.zone) + end +end windower.register_event('zone change', update_offset) return messages From 8851c783215489feed4711e696e3b53ba8a1afd5 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Tue, 11 Jan 2022 00:56:43 -0500 Subject: [PATCH 0766/1002] Jan 10th, 2022 Update --- addons/boxdestroyer/messages.lua | 120 +++++++++++++++---------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/addons/boxdestroyer/messages.lua b/addons/boxdestroyer/messages.lua index 198d7c1fc6..268ef49e3f 100644 --- a/addons/boxdestroyer/messages.lua +++ b/addons/boxdestroyer/messages.lua @@ -1,63 +1,63 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination" for the associated zone IDs - [100] = 8071, - [101] = 7509, - [102] = 7922, - [103] = 8097, - [104] = 8662, - [105] = 7713, - [106] = 8087, - [107] = 7548, - [108] = 7617, - [109] = 8480, - [110] = 7604, - [111] = 8581, - [112] = 8183, - [113] = 7932, - [114] = 7782, - [115] = 7878, - [116] = 7574, - [117] = 7581, - [118] = 8123, - [119] = 8360, - [120] = 7520, - [121] = 8100, - [122] = 7438, - [123] = 7883, - [124] = 7834, - [125] = 7644, - [126] = 8067, - [127] = 7355, - [128] = 7510, - [130] = 7574, - [153] = 11400, - [157] = 7380, - [158] = 7386, - [159] = 8449, - [160] = 7413, - [166] = 10582, - [167] = 10596, - [169] = 7543, - [172] = 7416, - [173] = 10521, - [174] = 11399, - [176] = 7608, - [177] = 11223, - [178] = 11403, - [184] = 8633, - [190] = 8257, - [191] = 8377, - [192] = 7413, - [193] = 8389, - [194] = 8269, - [195] = 7600, - [196] = 8309, - [197] = 7354, - [198] = 8275, - [200] = 7531, - [204] = 7519, - [205] = 11486, - [208] = 8288, - [212] = 10642, - [213] = 10452, + [100] = 8074, + [101] = 7512, + [102] = 7925, + [103] = 8100, + [104] = 8665, + [105] = 7716, + [106] = 8090, + [107] = 7551, + [108] = 7620, + [109] = 8483, + [110] = 7607, + [111] = 8584, + [112] = 8186, + [113] = 7935, + [114] = 7785, + [115] = 7881, + [116] = 7577, + [117] = 7584, + [118] = 8126, + [119] = 8363, + [120] = 7523, + [121] = 8103, + [122] = 7441, + [123] = 7886, + [124] = 7837, + [125] = 7647, + [126] = 8070, + [127] = 7358, + [128] = 7513, + [130] = 7577, + [153] = 11403, + [157] = 7383, + [158] = 7389, + [159] = 8452, + [160] = 7416, + [166] = 10585, + [167] = 10599, + [169] = 7546, + [172] = 7419, + [173] = 10524, + [174] = 11402, + [176] = 7611, + [177] = 11226, + [178] = 11406, + [184] = 8636, + [190] = 8260, + [191] = 8380, + [192] = 7416, + [193] = 8392, + [194] = 8272, + [195] = 7603, + [196] = 8312, + [197] = 7357, + [198] = 8278, + [200] = 7534, + [204] = 7522, + [205] = 11489, + [208] = 8291, + [212] = 10645, + [213] = 10455, } offsets = {greater_less=1, failure=2, success=4, second_even_odd=5, first_even_odd=6, range=7, less=8, greater=9, equal=10, second_multiple=11, first_multiple=12, tool_failure=13} From 6be9eb8b650462f7fb2f0ca92ee4fd65863fb20b Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Thu, 13 Jan 2022 14:24:36 +0100 Subject: [PATCH 0767/1002] Add New items to Slips lib Adding Feline Hagoita and Feline Hagoita +1 --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index ebe9143e96..9fd59b1568 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757, 25909}, -- 192 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750}, -- 143 SE Skipped an index hence the 0 as one of the items + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046}, -- 145 SE Skipped an index hence the 0 as one of the items [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067, 21680}, --176 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, --115 From ffb2679e8ef8174b4b7ec2e20fb10089b6799a30 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Thu, 13 Jan 2022 06:29:15 -0700 Subject: [PATCH 0768/1002] GearSwap SelfCommand handle_update fix some luas apparently call this function directly so, have to convert to library table before calling slice --- addons/GearSwap/libs/Mote-SelfCommands.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/GearSwap/libs/Mote-SelfCommands.lua b/addons/GearSwap/libs/Mote-SelfCommands.lua index 082a04ce70..d32ff81c4e 100644 --- a/addons/GearSwap/libs/Mote-SelfCommands.lua +++ b/addons/GearSwap/libs/Mote-SelfCommands.lua @@ -53,7 +53,7 @@ function handle_set(cmdParams) if state_var then local oldVal = state_var.value - state_var:set(cmdParams:slice(2):concat(' ')) + state_var:set(T(cmdParams):slice(2):concat(' ')) local newVal = state_var.value local descrip = state_var.description or cmdParams[1] From 37daa710cbc7763bb849a3c5474073ccb9144f6c Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Thu, 13 Jan 2022 14:41:56 +0100 Subject: [PATCH 0769/1002] Lib/tables: Forwarded table.sconcat parameters --- addons/libs/tables.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/libs/tables.lua b/addons/libs/tables.lua index 24417a2524..8a654c2c7e 100644 --- a/addons/libs/tables.lua +++ b/addons/libs/tables.lua @@ -563,8 +563,8 @@ function table.concat(t, delim, from, to) end -- Concatenates all elements with a whitespace in between. -function table.sconcat(t) - return table.concat(t, ' ') +function table.sconcat(t, ...) + return table.concat(t, ' ', ...) end -- Check if table is empty. @@ -583,7 +583,7 @@ function table.empty(t, rec) end end end - + return true end From 612ea7d45e1d94eecedd7e8f24da0bd28b0db8f3 Mon Sep 17 00:00:00 2001 From: Byrth Date: Thu, 13 Jan 2022 09:18:22 -0500 Subject: [PATCH 0770/1002] Minor update to translate in 2022 --- addons/translate/ReadMe.txt | 4 +- addons/translate/dicts/bgthread_guide.lua | 38 +++++++++---------- addons/translate/dicts/captainhowdy_guide.lua | 15 +++----- addons/translate/katakana_to_romanji.lua | 8 ++-- addons/translate/translate.lua | 19 ++++++---- 5 files changed, 43 insertions(+), 41 deletions(-) diff --git a/addons/translate/ReadMe.txt b/addons/translate/ReadMe.txt index d6eab5e0f1..73c120eee0 100644 --- a/addons/translate/ReadMe.txt +++ b/addons/translate/ReadMe.txt @@ -1,4 +1,4 @@ -Last Updated: 01/02/15 +Last Updated: 2022/01/13 Description: Translate is an addon designed to automatically translate chat text and search comments from JP to EN. It creates a dictionary using the windower resources and custom-made dictionaries (../windower/addons/translate/dicts/), and replaces incoming chat lines with the matching translation in order of longest JP phrase to shortest. @@ -10,4 +10,4 @@ This approach is not without its problems, and occasionally phrases will be tran Commands: //trans -* show original - Displays the original text. Known to double-up autotranslated phrases sometimes in search comments. Reason unclear. \ No newline at end of file +* show - Toggles display of the original text. Known to double-up autotranslated phrases sometimes in search comments. Reason unclear. \ No newline at end of file diff --git a/addons/translate/dicts/bgthread_guide.lua b/addons/translate/dicts/bgthread_guide.lua index f49fa126a2..bfc7976908 100644 --- a/addons/translate/dicts/bgthread_guide.lua +++ b/addons/translate/dicts/bgthread_guide.lua @@ -6,7 +6,7 @@ local dict = { {en="Normal",ja="普通"}, {en="Difficult",ja="むず"}, {en="Very Difficult",ja="とてもむず"}, - + {en="Menace",ja="メナス"}, {en="Voidwatch",ja="ヴォッチ"}, {en="Burrows",ja="バローズ"}, @@ -14,20 +14,19 @@ local dict = { {en="Ra'Kaznar Skirmish",ja="カザスカ"}, {en="Ra'Kaznar Skirmish",ja="スカカザ"}, {en="Ra'Kaznar Skirmish",ja="かざすか"}, - + {en="Leveling",ja="レベリング"}, {en="Aby",ja="アビ"}, {en="Altepa",ja="アルテパ"}, {en="Misareaux",ja="セア ミザレオ"}, {en="Doll",ja="ド-ル"}, - + {en="Recruiting",ja="募集"}, {en="Check seacom for jobs",ja="サチコ参照ジョブを添えてテルください"}, {en="Search Comment",ja="サチコ"}, {en="Job doesn't matter",ja="ジョブ不問"}, {en="currently",ja="現在"}, - - + {en="Hennetiel",ja="NTL"}, {en="Morimar",ja="モリマ"}, {en="Kamihr",ja="カミール"}, @@ -37,7 +36,7 @@ local dict = { {en="Foret",ja="水林"}, {en="Ceizak",ja="ケイザ"}, {en="Cirdas",ja="シルダス"}, - + {en="Trial by Fire",ja="火の試練"}, {en="Trial by Lightning",ja="雷の試練"}, {en="Trial by Earth",ja="土の試練"}, @@ -46,34 +45,34 @@ local dict = { {en="Trial by Wind",ja="風の試練"}, {en="Leviathan",ja="リヴァイアサン"}, {en="Levi",ja="リヴァ"}, - + {en="Tenzen",ja="てんぜん"}, {en="Tenzen",ja="テンゼン"}, {en="Warrior's Path",ja="武士道とは"}, - + {en="Return to Delkfutt's Tower",ja="デルクフの塔 再び"}, {en="Return to Delkfutt's Tower",ja="テルクフの塔再び"}, {en="Eald'narche",ja="エルド"}, {en="Kam'lanaut",ja="カムラ"}, {en="Stellar Fulcrum",ja="天輪"}, {en="Celestial Nexus",ja="宿星"}, - + {en="BRD",ja="吟"}, {en="GEO",ja="風"}, - + {en="Wanted (Battle)",ja="ウォンテッド"}, {en="Dragonfly",ja="トンボ"}, {en="Cost",ja="コスト"}, - + {en="Incursion",ja="インカ"}, {en="Tryl",ja="トリル"}, - + {en="*waves*",ja="ノシ"}, {en="Full Alliance",ja="フルアラ"}, - + {en="EIN",ja="エイン"}, {en="Ampuole",ja="アンプル"}, - + -- These are from wiki.ffo.jp: {en="Hugemaw Harold",ja="ひゅーじまうへらるど"}, {en="Bouncing Bertha",ja="ばうんしんぐばーさ"}, @@ -102,8 +101,7 @@ local dict = { {en="Douma Weapon",ja="どうまうぇぽん"}, {en="King Ugoprygid",ja="きんぐうるぴじっど"}, {en="Vedrfolnir",ja="う゛ぇどるふぉるにる"}, - - + {en="Ark Angel",ja="あーくえんじぇる"}, {en="Hume",ja="ひゅーむ"}, {en="Tarutaru",ja="たるたる"}, @@ -148,8 +146,7 @@ local dict = { {en="Diabolos",ja="でぃあぼろす"}, {en="Cait Sith",ja="けっとしー"}, {en="Atomos",ja="あともす"}, - - + {en="Vagary",ja="ベガリ"}, {en="Vagary",ja="ベガリーインスペクター"}, {en="Balamor",ja="バラモア"}, @@ -162,8 +159,11 @@ local dict = { {en="Hades",ja="ハデス"}, {en="upper",ja="上位"}, {en="lower",ja="下位"}, - + {en="Sinister Reign",ja="シニスターレイン"}, + + {en="Ambuscade",ja="アンバス"}, + {en="segments",ja="セグポ"} } return dict \ No newline at end of file diff --git a/addons/translate/dicts/captainhowdy_guide.lua b/addons/translate/dicts/captainhowdy_guide.lua index 60d3ca824f..e5b5855828 100644 --- a/addons/translate/dicts/captainhowdy_guide.lua +++ b/addons/translate/dicts/captainhowdy_guide.lua @@ -23,7 +23,7 @@ local dict = { {en="They are already there",ja="もおむこおにいっています"}, {en="Welcome back",ja="お帰りー"}, {en="What job?",ja="すみません、私のジョブなんですか?"}, - + -- During an event section {en="pop",ja="わかす"}, {en="Go ahead",ja="先にどうぞ"}, @@ -51,7 +51,7 @@ local dict = { {en="When is the ending?",ja="おわりますか"}, {en="You can pop next",ja="つぎわかせていいよ"}, --(You Find Nothing In The Riftworn Pyxis) || Tanakasan wa daikirai desuyo! || (ノ ゜Д゜)ノ三┸┸ - + -- Coming and Going {en="Bad",ja="だめ"}, {en="Cheap",ja="やすい"}, @@ -92,7 +92,7 @@ local dict = { {en="What happened?",ja="何かあった"}, {en="Yes, I'm coming",ja="はい行きます"}, {en="Yes, that's right",ja="はいそうです"}, - + {en="Brb, I'm going to the store",ja="りせき、コンビニで行きます"}, {en="Dont be late",ja="ちこくしないで"}, {en="Don't lie",ja="うそつかないで"}, @@ -239,8 +239,7 @@ local dict = { {en="Wyvern",ja="飛竜"}, {en="Pet",ja="ペット"}, {en="Pet",ja="よぶだす"}, - - + -- Useful words {en="Synergy",ja="相乗効果"}, {en="Carbuncle",ja="カーバンクル"}, @@ -255,8 +254,7 @@ local dict = { {en="Odin",ja="オーディン"}, {en="Alexander",ja="アレキサンダー"}, {en="Cait Sith",ja="ケット・シー"}, - - + {en="Weakness",ja="弱点"}, {en="Trigger",ja="狙って"}, {en="Blue",ja="青"}, @@ -314,8 +312,7 @@ local dict = { {en="Plasm farming",ja="メナポ"}, {en="Falling asleep",ja="寝落ち"}, {en="losing claim",ja="横取り"}, - - + -- 10/4/14 update {en="Dismemberment Brigade",ja="八つ裂き旅団"}, {en="The Worm's Turn",ja="地竜大王"}, diff --git a/addons/translate/katakana_to_romanji.lua b/addons/translate/katakana_to_romanji.lua index 40fcd83dc4..9297deb48a 100644 --- a/addons/translate/katakana_to_romanji.lua +++ b/addons/translate/katakana_to_romanji.lua @@ -47,7 +47,7 @@ katakana_to_romanji = { {en="wi",ja="ヰ"}, {en="we",ja="ヱ"}, {en="wo",ja="ヲ"}, - + {en="ga",ja="ガ"}, {en="gi",ja="ギ"}, {en="gu",ja="グ"}, @@ -73,9 +73,9 @@ katakana_to_romanji = { {en="pu",ja="プ"}, {en="pe",ja="ペ"}, {en="po",ja="ポ"}, - + {en="n",ja="ン"}, - + {en="kya",ja="キャ"}, {en="kyu",ja="キュ"}, {en="kyo",ja="キョ"}, @@ -97,7 +97,7 @@ katakana_to_romanji = { {en="rya",ja="リャ"}, {en="ryu",ja="リュ"}, {en="ryo",ja="リョ"}, - + {en="gya",ja="ギャ"}, {en="gyu",ja="ギュ"}, {en="gyo",ja="ギョ"}, diff --git a/addons/translate/translate.lua b/addons/translate/translate.lua index a33bbdab52..78306bc87f 100644 --- a/addons/translate/translate.lua +++ b/addons/translate/translate.lua @@ -49,11 +49,15 @@ handled_resources = S{ 'items', 'job_abilities', 'job_traits', + 'job_points', 'jobs', 'key_items', + 'merit_points', 'monster_abilities', + 'monster_skills', 'monstrosity', 'moon_phases', + 'mounts', 'races', 'regions', 'skills', @@ -308,17 +312,18 @@ windower.register_event('addon command', function(...) local commands = {...} if not commands[1] then return end if commands[1]:lower() == 'show' then - if commands[2] and commands[2]:lower() == 'original' then - show_original=not show_original - if show_original then - print('Translate: Showing the original text line.') - else - print('Translate: Hiding the original text line.') - end + show_original=not show_original + if show_original then + print('Translate: Showing the original text line.') + else + print('Translate: Hiding the original text line.') end elseif commands[1]:lower() == 'eval' and commands[2] then table.remove(commands,1) assert(loadstring(table.concat(commands, ' ')))() + elseif comamnds[1]:lower() == 'help' then + print('Translate:') + print(' show: toggles whether to show the original text (default: hide)') end end) From ce39e194059318995ce033a4ede30f51b42ddad7 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Fri, 14 Jan 2022 06:18:46 -0500 Subject: [PATCH 0771/1002] Formatting Not saying I will ever touch this v4 version again but if I do I want to be able to read some of it. --- addons/Stubborn/Stubborn.lua | 108 ++++++++++++++--------------- addons/rolltracker/rolltracker.lua | 62 ++++++++--------- 2 files changed, 85 insertions(+), 85 deletions(-) diff --git a/addons/Stubborn/Stubborn.lua b/addons/Stubborn/Stubborn.lua index 54dac73b9f..69865fac44 100644 --- a/addons/Stubborn/Stubborn.lua +++ b/addons/Stubborn/Stubborn.lua @@ -1,54 +1,54 @@ ---[[Copyright © 2021, Arico -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 Stubborn 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 Arico 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.name = 'Stubborn' -_addon.author = 'Arico' -_addon.version = '1' -_addon.commands = {'stubborn','cfh'} - -require('logger') -packets = require('packets') - -windower.register_event('outgoing chunk', function(id, original, modified, injected, blocked) - if id == 0x01A and not injected then - local p = packets.parse('outgoing', original) - if p['Category'] == 5 then - return true - end - end -end) - -windower.register_event('addon command', function(...) - local target = windower.ffxi.get_mob_by_target('t') - if target and target.claim_id ~= 0 then - local p = packets.new('outgoing', 0x01A, { - ['Target'] = target['id'], - ['Target Index'] = target['index'], - ['Category'] = 5, - }) - packets.inject(p) - end -end) +--[[Copyright © 2021, Arico +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 Stubborn 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 Arico 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.name = 'Stubborn' +_addon.author = 'Arico' +_addon.version = '1' +_addon.commands = {'stubborn','cfh'} + +require('logger') +packets = require('packets') + +windower.register_event('outgoing chunk', function(id, original, modified, injected, blocked) + if id == 0x01A and not injected then + local p = packets.parse('outgoing', original) + if p['Category'] == 5 then + return true + end + end +end) + +windower.register_event('addon command', function(...) + local target = windower.ffxi.get_mob_by_target('t') + if target and target.claim_id ~= 0 then + local p = packets.new('outgoing', 0x01A, { + ['Target'] = target['id'], + ['Target Index'] = target['index'], + ['Category'] = 5, + }) + packets.inject(p) + end +end) diff --git a/addons/rolltracker/rolltracker.lua b/addons/rolltracker/rolltracker.lua index b688d09ddf..f95a5e2815 100644 --- a/addons/rolltracker/rolltracker.lua +++ b/addons/rolltracker/rolltracker.lua @@ -109,37 +109,37 @@ windower.register_event('load', function() } local rollInfoTemp = { -- Okay, this goes 1-11 boost, Bust effect, Effect, Lucky, Unlucky, +1 Phantom Roll Effect, Job Bonus, Bonus Equipment and Effect, - ['Allies\''] = {6,7,17,9,11,13,15,17,17,5,17,'?','% Skillchain Damage',3,10, 1,{nil,0},{6,11120, 27084, 27085, 5}},--Needs Eval - ['Avenger\'s'] = {'?','?','?','?','?','?','?','?','?','?','?','?',' Counter Rate',4,8, 0,{nil,0}}, - ['Beast'] = {64,80,96,256,112,128,160,32,176,192,320,'0','% Pet: Attack Bonus',4,8, 32,{'bst',100}},--/1024 Confirmed - ['Blitzer\'s'] = {2,3.4,4.5,11.3,5.3,6.4,7.2,8.3,1.5,10.2,12.1,'-3','% Attack delay reduction',4,9, 1,{nil,0},{4,11080, 26772, 26773, 5}},--Limited Testing for Bust, Needs more data for sure probably /1024 - ['Bolter\'s'] = {0.3,0.3,0.8,0.4,0.4,0.5,0.5,0.6,0.2,0.7,1.0,'0','% Movement Speed',3,9, 0.2,{nil,0}}, - ['Caster\'s'] = {6,15,7,8,9,10,5,11,12,13,20,'-10','% Fast Cast',2,7, 3,{nil,0},{7, 11140, 27269, 27269, 10}}, - ['Chaos'] = {64,80,96,256,112,128,160,32,176,192,320,"-9.76",'% Attack!', 4,8, 32,{'drk',100}},--/1024 Confirmed - ['Choral'] = {8,42,11,15,19,4,23,27,31,35,50,'+25','- Spell Interruption Rate',2,6, 4,{'brd',25}},--SE listed Values and hell if I'm testing this - ['Companion\'s'] = {{4,20},{20,50},{6,20},{8,20},{10,30},{12,30},{14,30},{16,40},{18,40},{3,10},{25,60},'0',' Pet: Regen/Regain',2,10, {2,5},{nil,0}}, - ['Corsair\'s'] = {10, 11, 11, 12, 20, 13, 15, 16, 8, 17, 24,'-6','% Experience Bonus',5,9, 2,{'cor',5}},--Needs Eval on Bust/Job Bonus - ['Courser\'s'] = {'?','?','?','?','?','?','?','?','?','?','?','?',' Snapshot',3,9, 0,{nil,0}}, --11160, 27443, 27444 - ['Dancer\'s'] = {3,4,12,5,6,7,1,8,9,10,16,'-4',' Regen',3,7, 2,{'dnc',4}},--Confirmed - ['Drachen'] = {10,13,15,40,18,20,25,5,28,30,50,'0',' Pet: Accuracy Bonus',4,8, 5,{'drg',15}},--Confirmed - ['Evoker\'s'] = {1,1,1,1,3,2,2,2,1,3,4,'-1',' Refresh!',5,9, 1,{'smn',1}},--Confirmed - ['Fighter\'s'] = {2,2,3,4,12,5,6,7,1,9,18,'-4','% Double-Attack!',5,9, 1,{'war',5}}, - ['Gallant\'s'] = {48,60,200,72,88,104,32,120,140,160,240,'-11.72','% Defense Bonus',3,7, 24,{'pld',120}},--/1024 Confirmed - ['Healer\'s'] = {3,4,12,5,6,7,1,8,9,10,16,'-4','% Cure Potency Received',3,7, 1,{'whm',4}},--Confirmed - ['Hunter\'s'] = {10,13,15,40,18,20,25,5,28,30,50,'-15',' Accuracy Bonus',4,8, 5,{'rng',15}},--Confirmed - ['Magus\'s'] = {5,20,6,8,9,3,10,13,14,15,25,'-8',' Magic Defense Bonus',2,6, 2,{'blu',8}}, - ['Miser\'s'] = {30,50,70,90,200,110,20,130,150,170,250,'0',' Save TP',5,7, 15,{nil,0}}, - ['Monk\'s'] = {8,10,32,12,14,15,4,20,22,24,40,'-?',' Subtle Blow', 3,7, 4,{'mnk',10}}, - ['Naturalist\'s'] = {6,7,15,8,9,10,5,11,12,13,20,'-5','% Enhancing Magic Duration',3,7, 1,{'geo',5}},--Confirmed - ['Ninja'] = {10,13,15,40,18,20,25,5,28,30,50,'-15',' Evasion Bonus',4,8, 5,{'nin',15}},--Confirmed - ['Puppet'] = {5,8,35,11,14,18,2,22,26,30,40,'-8',' Pet: MAB/MAcc',3,7, 3,{'pup',12}}, - ['Rogue\'s'] = {2,2,3,4,12,5,6,6,1,8,14,'-6','% Critical Hit Rate!',5,9, 1,{'thf',5}}, - ['Runeist\'s'] = {10,13,15,40,18,20,25,5,28,30,50,'-15',' Evasion Bonus',4,8, 5,{'run',15}},--Needs Eval - ['Samurai'] = {8,32,10,12,14,4,16,20,22,24,40,'-10',' Store TP Bonus',2,6, 4,{'sam',10}},--Confirmed 1(Was bad),2,3,4,5,6,7,8,11 (I Wing Test) - ['Scholar\'s'] = {2,10,3,4,4,1,5,6,7,7,12,'-3','% Conserve MP',2,6, 1,{'sch',3}}, --Needs Eval Source ATM: JP Wiki - ['Tactician\'s'] = {10,10,10,10,30,10,10,0,20,20,40,'-10',' Regain',5,8, 2,{nil,0},{5, 11100, 26930, 26931, 10}},--Confirmed - ['Warlock\'s'] = {10,13,15,40,18,20,25,5,28,30,50,'-15',' Magic Accuracy Bonus',4,8, 5,{'rdm',15}},-- - ['Wizard\'s'] = {4,6,8,10,25,12,14,17,2,20,30, "-10",' MAB',5,9, 2,{'blm',10}}, + ['Allies\''] = {6,7,17,9,11,13,15,17,17,5,17,'?','% Skillchain Damage',3,10, 1,{nil,0},{6,11120, 27084, 27085, 5}}, -- Needs Eval + ['Avenger\'s'] = {'?','?','?','?','?','?','?','?','?','?','?','?',' Counter Rate',4,8, 0,{nil,0}}, + ['Beast'] = {64,80,96,256,112,128,160,32,176,192,320,'0','% Pet: Attack Bonus',4,8, 32,{'bst',100}}, -- /1024 Confirmed + ['Blitzer\'s'] = {2,3.4,4.5,11.3,5.3,6.4,7.2,8.3,1.5,10.2,12.1,'-3','% Attack delay reduction',4,9, 1,{nil,0},{4,11080, 26772, 26773, 5}}, -- Limited Testing for Bust, Needs more data for sure probably /1024 + ['Bolter\'s'] = {0.3,0.3,0.8,0.4,0.4,0.5,0.5,0.6,0.2,0.7,1.0,'0','% Movement Speed',3,9, 0.2,{nil,0}}, + ['Caster\'s'] = {6,15,7,8,9,10,5,11,12,13,20,'-10','% Fast Cast',2,7, 3,{nil,0},{7, 11140, 27269, 27269, 10}}, + ['Chaos'] = {64,80,96,256,112,128,160,32,176,192,320,"-9.76",'% Attack!', 4,8, 32,{'drk',100}}, -- /1024 Confirmed + ['Choral'] = {8,42,11,15,19,4,23,27,31,35,50,'+25','- Spell Interruption Rate',2,6, 4,{'brd',25}}, -- SE listed Values and hell if I'm testing this + ['Companion\'s'] = {{4,20},{20,50},{6,20},{8,20},{10,30},{12,30},{14,30},{16,40},{18,40},{3,10},{25,60},'0',' Pet: Regen/Regain',2,10, {2,5},{nil,0}}, + ['Corsair\'s'] = {10, 11, 11, 12, 20, 13, 15, 16, 8, 17, 24,'-6','% Experience Bonus',5,9, 2,{'cor',5}}, -- Needs Eval on Bust/Job Bonus + ['Courser\'s'] = {'?','?','?','?','?','?','?','?','?','?','?','?',' Snapshot',3,9, 0,{nil,0}}, -- 11160, 27443, 27444 + ['Dancer\'s'] = {3,4,12,5,6,7,1,8,9,10,16,'-4',' Regen',3,7, 2,{'dnc',4}}, -- Confirmed + ['Drachen'] = {10,13,15,40,18,20,25,5,28,30,50,'0',' Pet: Accuracy Bonus',4,8, 5,{'drg',15}}, -- Confirmed + ['Evoker\'s'] = {1,1,1,1,3,2,2,2,1,3,4,'-1',' Refresh!',5,9, 1,{'smn',1}}, -- Confirmed + ['Fighter\'s'] = {2,2,3,4,12,5,6,7,1,9,18,'-4','% Double-Attack!',5,9, 1,{'war',5}}, + ['Gallant\'s'] = {48,60,200,72,88,104,32,120,140,160,240,'-11.72','% Defense Bonus',3,7, 24,{'pld',120}}, -- /1024 Confirmed + ['Healer\'s'] = {3,4,12,5,6,7,1,8,9,10,16,'-4','% Cure Potency Received',3,7, 1,{'whm',4}}, -- Confirmed + ['Hunter\'s'] = {10,13,15,40,18,20,25,5,28,30,50,'-15',' Accuracy Bonus',4,8, 5,{'rng',15}}, -- Confirmed + ['Magus\'s'] = {5,20,6,8,9,3,10,13,14,15,25,'-8',' Magic Defense Bonus',2,6, 2,{'blu',8}}, + ['Miser\'s'] = {30,50,70,90,200,110,20,130,150,170,250,'0',' Save TP',5,7, 15,{nil,0}}, + ['Monk\'s'] = {8,10,32,12,14,15,4,20,22,24,40,'-?',' Subtle Blow', 3,7, 4,{'mnk',10}}, + ['Naturalist\'s'] = {6,7,15,8,9,10,5,11,12,13,20,'-5','% Enhancing Magic Duration',3,7, 1,{'geo',5}}, -- Confirmed + ['Ninja'] = {10,13,15,40,18,20,25,5,28,30,50,'-15',' Evasion Bonus',4,8, 5,{'nin',15}}, -- Confirmed + ['Puppet'] = {5,8,35,11,14,18,2,22,26,30,40,'-8',' Pet: MAB/MAcc',3,7, 3,{'pup',12}}, + ['Rogue\'s'] = {2,2,3,4,12,5,6,6,1,8,14,'-6','% Critical Hit Rate!',5,9, 1,{'thf',5}}, + ['Runeist\'s'] = {10,13,15,40,18,20,25,5,28,30,50,'-15',' Evasion Bonus',4,8, 5,{'run',15}}, -- Needs Eval + ['Samurai'] = {8,32,10,12,14,4,16,20,22,24,40,'-10',' Store TP Bonus',2,6, 4,{'sam',10}}, -- Confirmed 1(Was bad),2,3,4,5,6,7,8,11 (I Wing Test) + ['Scholar\'s'] = {2,10,3,4,4,1,5,6,7,7,12,'-3','% Conserve MP',2,6, 1,{'sch',3}}, --Needs Eval Source ATM: JP Wiki + ['Tactician\'s'] = {10,10,10,10,30,10,10,0,20,20,40,'-10',' Regain',5,8, 2,{nil,0},{5, 11100, 26930, 26931, 10}}, -- Confirmed + ['Warlock\'s'] = {10,13,15,40,18,20,25,5,28,30,50,'-15',' Magic Accuracy Bonus',4,8, 5,{'rdm',15}}, -- + ['Wizard\'s'] = {4,6,8,10,25,12,14,17,2,20,30, "-10",' MAB',5,9, 2,{'blm',10}}, } rollInfo = {} From 1fafb5ea135d1fe9f05268c16ee63cae50765ba6 Mon Sep 17 00:00:00 2001 From: Byrth Date: Sun, 16 Jan 2022 18:54:31 -0500 Subject: [PATCH 0772/1002] Add chocobo digging action enum --- addons/libs/packets/fields.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 093363760e..6962ea40ef 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -351,6 +351,7 @@ enums['action'] = { [0x0E] = 'Cast Fishing Rod', [0x0F] = 'Switch target', [0x10] = 'Ranged attack', + [0x11] = 'Chocobo dig', [0x12] = 'Dismount Chocobo', [0x13] = 'Tractor Dialogue', [0x14] = 'Zoning/Appear', -- I think, the resource for this is ambiguous. From 8c7f4d2a2b6ab24b2c2465c1db5822c59bd3b104 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Wed, 2 Feb 2022 03:43:41 +0100 Subject: [PATCH 0773/1002] [Battlemod] some fixes fixed mobwscol and mobspellcol not having effect. Also fixed items that give experience points and mweya plasm, now the simplified message after using them show what they give. --- addons/battlemod/parse_action_packet.lua | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/addons/battlemod/parse_action_packet.lua b/addons/battlemod/parse_action_packet.lua index 05cfd36011..93304ed70e 100644 --- a/addons/battlemod/parse_action_packet.lua +++ b/addons/battlemod/parse_action_packet.lua @@ -309,11 +309,11 @@ function parse_action_packet(act) 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('${spell}',act.action.spell or 'ERROR 111') :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('${weapon_skill}',act.action.weapon_skill or 'ERROR 114') :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) @@ -736,6 +736,16 @@ function get_spell(act) spell.japanese = spell.english spell.french = spell.english end + elseif msg_ID == 673 then + spell.english = 'Mweya Plasm' + spell.german = spell.english + spell.japanese = spell.english + spell.french = spell.english + elseif msg_ID == 105 then + spell.english = 'Experience Points' + spell.german = spell.english + spell.japanese = spell.english + spell.french = spell.english else if not res.action_messages[msg_ID] then if T{4,8}:contains(act['category']) then @@ -761,8 +771,8 @@ function get_spell(act) 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) + spell.name = color_it(spell[language],act.actor.type == 'mob' and color_arr.mobspellcol or color_arr.spellcol) + spell.spell = color_it(spell[language],act.actor.type == 'mob' and color_arr.mobspellcol or color_arr.spellcol) end elseif fields.ability then spell = res.job_abilities[abil_ID] @@ -783,8 +793,8 @@ function get_spell(act) 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) + spell.name = color_it(spell[language],act.actor.type == 'mob' and color_arr.mobwscol or color_arr.wscol) + spell.weapon_skill = color_it(spell[language],act.actor.type == 'mob' and color_arr.mobwscol or color_arr.wscol) end elseif msg_ID == 303 then spell = res.job_abilities[74] -- Divine Seal From b65e6efe2b00a35c4402daf23b4324faa9ba2925 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Mon, 7 Feb 2022 04:02:28 +0100 Subject: [PATCH 0774/1002] [ohShi] nil error fix Some mobs 2hr use the monster abilities version of them so the param value is not on the job_abilities.lua. --- addons/ohShi/ohShi.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/ohShi/ohShi.lua b/addons/ohShi/ohShi.lua index 567b15fe62..ad7cfcaddf 100644 --- a/addons/ohShi/ohShi.lua +++ b/addons/ohShi/ohShi.lua @@ -208,7 +208,7 @@ windower.register_event('action', function(act) local player = T(windower.ffxi.get_player()) if not settings.staggeronly then - if settings.showrolls and curact.category == 6 and res.job_abilities[extparam].type == 'CorsairRoll' then + if settings.showrolls and curact.category == 6 and res.job_abilities[extparam] and res.job_abilities[extparam].type == 'CorsairRoll' then local allyroller = false local selfroll = false for pt,member in pairs(party) do From 58e18f80ac94dce291d9e3e600e9d8d1a0977f15 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Thu, 10 Feb 2022 04:48:52 -0700 Subject: [PATCH 0775/1002] Gearswap -- update usable and equippable bags New Wardrobes --- addons/GearSwap/statics.lua | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/addons/GearSwap/statics.lua b/addons/GearSwap/statics.lua index 2e9e46da42..42fee38a4d 100644 --- a/addons/GearSwap/statics.lua +++ b/addons/GearSwap/statics.lua @@ -40,14 +40,22 @@ usable_item_bags = { res.bags[8], -- Wardrobe 1 res.bags[10], -- Wardrobe 2 res.bags[11], -- Wardrobe 3 - res.bags[12]} -- Wardrobe 4 + res.bags[12], -- Wardrobe 4 + res.bags[13], -- Wardrobe 5 + res.bags[14], -- Wardrobe 6 + res.bags[15], -- Wardrobe 7 + res.bags[16]} -- Wardrobe 8 equippable_item_bags = { res.bags[0], -- Inventory res.bags[8], -- Wardrobe 1 res.bags[10], -- Wardrobe 2 res.bags[11], -- Wardrobe 3 - res.bags[12]} -- Wardrobe 4 + res.bags[12], -- Wardrobe 4 + res.bags[13], -- Wardrobe 5 + res.bags[14], -- Wardrobe 6 + res.bags[15], -- Wardrobe 7 + res.bags[16]} -- Wardrobe 8 bag_string_lookup = {} for i,v in pairs(res.bags) do From 7f582e55ac33150b207ce6665297c9030dc8e8da Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Thu, 10 Feb 2022 04:56:18 -0700 Subject: [PATCH 0776/1002] Organizer -- add wardrobes --- addons/organizer/organizer.lua | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/addons/organizer/organizer.lua b/addons/organizer/organizer.lua index a9509c08e1..d85c2cf377 100644 --- a/addons/organizer/organizer.lua +++ b/addons/organizer/organizer.lua @@ -57,9 +57,13 @@ _static = { wardrobe2=10, wardrobe3=11, wardrobe4=12, + wardrobe5=13, + wardrobe6=14, + wardrobe7=15, + wardrobe8=16, }, - wardrobe_ids = {[8]=true,[10]=true,[11]=true,[12]=true}, - usable_bags = {1,9,4,2,5,6,7,8,10,11,12} + wardrobe_ids = {[8]=true,[10]=true,[11]=true,[12]=true,[13]=true,[14]=true,[15]=true,[16]=true}, + usable_bags = {1,9,4,2,5,6,7,8,10,11,12,13,14,15,16} } _global = { @@ -74,7 +78,7 @@ _valid_dump = {} default_settings = { dump_bags = {['Safe']=1,['Safe2']=2,['Locker']=3,['Storage']=4}, - bag_priority = {['Safe']=1,['Safe2']=2,['Locker']=3,['Storage']=4,['Satchel']=5,['Sack']=6,['Case']=7,['Inventory']=8,['Wardrobe']=9,['Wardrobe2']=10,['Wardrobe3']=11,['Wardrobe4']=12,}, + bag_priority = {['Safe']=1,['Safe2']=2,['Locker']=3,['Storage']=4,['Satchel']=5,['Sack']=6,['Case']=7,['Inventory']=8,['Wardrobe']=9,['Wardrobe2']=10,['Wardrobe3']=11,['Wardrobe4']=12,['Wardrobe5']=13,['Wardrobe6']=14,['Wardrobe7']=15,['Wardrobe8']=16}, item_delay = 0, ignore = {}, retain = { From ac5e9c305bbad391c1d61560303e7f09fc7f07ba Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Thu, 10 Feb 2022 05:00:15 -0700 Subject: [PATCH 0777/1002] FindAll -- Add Wardrobes --- addons/findAll/findAll.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/findAll/findAll.lua b/addons/findAll/findAll.lua index 83ff8d1a19..6f96455dac 100644 --- a/addons/findAll/findAll.lua +++ b/addons/findAll/findAll.lua @@ -169,7 +169,7 @@ item_names = T{} key_item_names = T{} global_storages = T{} storages_path = 'data/' -storages_order_tokens = L{'temporary', 'inventory', 'wardrobe', 'wardrobe 2', 'safe', 'safe 2', 'storage', 'locker', 'satchel', 'sack', 'case'} +storages_order_tokens = L{'temporary', 'inventory', 'wardrobe', 'wardrobe 2', 'wardrobe 3', 'wardrobe 4', 'wardrobe 5', 'wardrobe 6', 'wardrobe 7', 'wardrobe 8', 'safe', 'safe 2', 'storage', 'locker', 'satchel', 'sack', 'case'} -- This is to maintain sorting order. I don't know why this was done, but omitting this will sort the bags arbitrarily, which (I guess) was not intended storages_order = S(res.bags:map(string.gsub-{' ', ''} .. string.lower .. table.get-{'english'})):sort(function(name1, name2) local index1 = storages_order_tokens:find(name1) From 2ca24146f2ee2712f84b88c9ca569dc0d157c0a5 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Thu, 10 Feb 2022 05:19:41 -0700 Subject: [PATCH 0778/1002] Itemizer -- Add Wardrobes --- addons/itemizer/itemizer.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/itemizer/itemizer.lua b/addons/itemizer/itemizer.lua index 5074ee9f6e..31015e34ea 100644 --- a/addons/itemizer/itemizer.lua +++ b/addons/itemizer/itemizer.lua @@ -328,7 +328,7 @@ windower.register_event('outgoing text', function() if bag == 'inventory' then inventory_items:add(item.id) - elseif S{'wardrobe','wardrobe2','wardrobe3','wardrobe4'}:contains(bag) then + elseif S{'wardrobe','wardrobe2','wardrobe3','wardrobe4','wardrobe5','wardrobe6','wardrobe7','wardrobe8'}:contains(bag) then wardrobe_items:add(item.id) end end From d96559f03a03d66f75ae6a68cb4d864d0d333f03 Mon Sep 17 00:00:00 2001 From: Byrth Date: Thu, 10 Feb 2022 07:24:43 -0500 Subject: [PATCH 0779/1002] Add recycle to the ignore list --- addons/shortcuts/statics.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/addons/shortcuts/statics.lua b/addons/shortcuts/statics.lua index 4fd1219ee9..50f06af57d 100644 --- a/addons/shortcuts/statics.lua +++ b/addons/shortcuts/statics.lua @@ -123,8 +123,6 @@ command2_list = { ['kneel']=emote_table, ['laugh']=emote_table, ['muted']=emote_table, - ['kneel']=emote_table, - ['laugh']=emote_table, ['no']=emote_table, ['nod']=emote_table, ['yes']=emote_table, @@ -165,7 +163,7 @@ command2_list = { unhandled_list = {['p']=true,['s']=true,['sh']=true,['yell']=true,['echo']=true,['t']=true,['l']=true,['breaklinkshell']=true} -- List of commands to be ignored -ignore_list = {['equip']=true,['raw']=true,['fish']=true,['dig']=true,['range']=true,['map']=true,['hide']=true,['jump']=true,['attackoff']=true,['quest']=true,['recruitlist']=true,['rlist']=true,['statustimer']=true} +ignore_list = {['equip']=true,['raw']=true,['fish']=true,['dig']=true,['range']=true,['map']=true,['hide']=true,['jump']=true,['attackoff']=true,['quest']=true,['recruitlist']=true,['rlist']=true,['statustimer']=true,['recycle']=true} -- Targets to ignore and just pass through pass_through_targs = T{'','','','','','','','','','','','','', From 957c292533471a10dceb116fd20e6dff2a09d8a4 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Thu, 10 Feb 2022 06:35:15 -0700 Subject: [PATCH 0780/1002] Packets 0x01C update --- addons/libs/packets/fields.lua | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 6962ea40ef..5fe0bf2e84 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1540,7 +1540,7 @@ fields.incoming[0x01B] = L{ -- all arrived and still did not see any change in the second set of sizes, so they -- may not be max size/used size chars as I initially assumed. Adding them as shorts -- for now. --- There appears to be space for another 8 bags. +-- There appears to be space for another 3 bags. fields.incoming[0x01C] = L{ {ctype='unsigned char', label='Inventory Size'}, -- 04 {ctype='unsigned char', label='Safe Size'}, -- 05 @@ -1555,7 +1555,12 @@ fields.incoming[0x01C] = L{ {ctype='unsigned char', label='Wardrobe 2 Size'}, -- 0E {ctype='unsigned char', label='Wardrobe 3 Size'}, -- 0F {ctype='unsigned char', label='Wardrobe 4 Size'}, -- 10 - {ctype='data[19]', label='_padding1', const=''}, -- 11 + {ctype='unsigned char', label='Wardrobe 5 Size'}, -- 11 + {ctype='unsigned char', label='Wardrobe 6 Size'}, -- 12 + {ctype='unsigned char', label='Wardrobe 7 Size'}, -- 13 + {ctype='unsigned char', label='Wardrobe 8 Size'}, -- 14 + {ctype='unsigned char', label='Recycle Bin Size'}, -- 15 + {ctype='data[14]', label='_padding1', const=''}, -- 16 {ctype='unsigned short', label='_dupeInventory Size'}, -- 24 These "dupe" sizes are set to 0 if the inventory disabled. {ctype='unsigned short', label='_dupeSafe Size'}, -- 26 {ctype='unsigned short', label='_dupeStorage Size'}, -- 28 The accumulated storage from all items (uncapped) -1 @@ -1569,7 +1574,12 @@ fields.incoming[0x01C] = L{ {ctype='unsigned short', label='_dupeWardrobe 2 Size'}, -- 38 {ctype='unsigned short', label='_dupeWardrobe 3 Size'}, -- 3A This is not set to 0 despite being disabled for whatever reason {ctype='unsigned short', label='_dupeWardrobe 4 Size'}, -- 3C This is not set to 0 despite being disabled for whatever reason - {ctype='data[22]', label='_padding2', const=''}, -- 3E + {ctype='unsigned short', label='_dupeWardrobe 5 Size'}, -- 3E This is not set to 0 despite being disabled for whatever reason + {ctype='unsigned short', label='_dupeWardrobe 6 Size'}, -- 40 This is not set to 0 despite being disabled for whatever reason + {ctype='unsigned short', label='_dupeWardrobe 7 Size'}, -- 42 This is not set to 0 despite being disabled for whatever reason + {ctype='unsigned short', label='_dupeWardrobe 8 Size'}, -- 44 This is not set to 0 despite being disabled for whatever reason + {ctype='unsigned short', label='_dupeRecycle Bin Size'}, -- 46 + {ctype='data[12]', label='_padding2', const=''}, -- 3E } -- Finish Inventory From d0e537c839aa1624659f4f5454e84979a699e141 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Thu, 10 Feb 2022 22:00:32 +0100 Subject: [PATCH 0781/1002] Packets update for new wardrobes Update incoming 0x01C and 0x037 for the new wardrobes. --- addons/libs/packets/fields.lua | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 6962ea40ef..85802efecb 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1555,7 +1555,11 @@ fields.incoming[0x01C] = L{ {ctype='unsigned char', label='Wardrobe 2 Size'}, -- 0E {ctype='unsigned char', label='Wardrobe 3 Size'}, -- 0F {ctype='unsigned char', label='Wardrobe 4 Size'}, -- 10 - {ctype='data[19]', label='_padding1', const=''}, -- 11 + {ctype='unsigned char', label='Wardrobe 5 Size'}, -- 11 + {ctype='unsigned char', label='Wardrobe 6 Size'}, -- 12 + {ctype='unsigned char', label='Wardrobe 7 Size'}, -- 13 + {ctype='unsigned char', label='Wardrobe 8 Size'}, -- 14 + {ctype='data[15]', label='_padding1', const=''}, -- 15 {ctype='unsigned short', label='_dupeInventory Size'}, -- 24 These "dupe" sizes are set to 0 if the inventory disabled. {ctype='unsigned short', label='_dupeSafe Size'}, -- 26 {ctype='unsigned short', label='_dupeStorage Size'}, -- 28 The accumulated storage from all items (uncapped) -1 @@ -1569,7 +1573,11 @@ fields.incoming[0x01C] = L{ {ctype='unsigned short', label='_dupeWardrobe 2 Size'}, -- 38 {ctype='unsigned short', label='_dupeWardrobe 3 Size'}, -- 3A This is not set to 0 despite being disabled for whatever reason {ctype='unsigned short', label='_dupeWardrobe 4 Size'}, -- 3C This is not set to 0 despite being disabled for whatever reason - {ctype='data[22]', label='_padding2', const=''}, -- 3E + {ctype='unsigned short', label='_dupeWardrobe 5 Size'}, -- 3C This is not set to 0 despite being disabled for whatever reason + {ctype='unsigned short', label='_dupeWardrobe 6 Size'}, -- 3C This is not set to 0 despite being disabled for whatever reason + {ctype='unsigned short', label='_dupeWardrobe 7 Size'}, -- 3C This is not set to 0 despite being disabled for whatever reason + {ctype='unsigned short', label='_dupeWardrobe 8 Size'}, -- 3C This is not set to 0 despite being disabled for whatever reason + {ctype='data[30]', label='_padding2', const=''}, -- 3E } -- Finish Inventory @@ -2164,7 +2172,12 @@ fields.incoming[0x037] = L{ {ctype='unsigned char', label='Mount'}, -- 5B Related to Mounts, seems to be mount id + 1, except for chocobo. The value doesn't get zeroed after dismount {ctype='boolbit', label='Wardrobe 3'}, -- 5C {ctype='boolbit', label='Wardrobe 4'}, -- 5C - {ctype='bit[6]', label='_flags8'}, -- 5C + {ctype='bit', label='_unknown6'}, -- 5C + {ctype='boolbit', label='Wardrobe 5'}, -- 5C + {ctype='boolbit', label='Wardrobe 6'}, -- 5C + {ctype='boolbit', label='Wardrobe 7'}, -- 5C + {ctype='boolbit', label='Wardrobe 8'}, -- 5C + {ctype='bit', label='_flags8'}, -- 5C {ctype='data[3]', label='_junk1'}, -- 5D } From e452fcd9a2a68e59ed245fb2917b945e13fb1d2d Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Thu, 10 Feb 2022 16:22:00 -0700 Subject: [PATCH 0782/1002] Packets -- Update 0x01D --- addons/libs/packets/fields.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 85802efecb..16dc325a5c 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1582,8 +1582,9 @@ fields.incoming[0x01C] = L{ -- Finish Inventory fields.incoming[0x01D] = L{ - {ctype='unsigned char', label='Flag', const=0x01}, -- 04 - {ctype='data[3]', label='_junk1'}, -- 06 + {ctype='unsigned char', label='Flag'}, -- 04 0 for bag finished updates, 1 for finished loading inventories + {ctype='unsigned char', label='Bag'}, -- 05 18 (0x12) when flag is 1, and 18 is not a valid bag id (last bag + 1) + {ctype='data[6]', label='_junk1'}, -- 06 } -- Modify Inventory From 985bf489dfaf74e845669fb5387dfdd0744c1c0c Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Thu, 10 Feb 2022 16:29:02 -0700 Subject: [PATCH 0783/1002] Packets 0x01C Update --- addons/libs/packets/fields.lua | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index e0ab0616d5..17d7d82898 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1540,7 +1540,7 @@ fields.incoming[0x01B] = L{ -- all arrived and still did not see any change in the second set of sizes, so they -- may not be max size/used size chars as I initially assumed. Adding them as shorts -- for now. --- There appears to be space for another 3 bags. +-- There appears to be space for another 8 bags. fields.incoming[0x01C] = L{ {ctype='unsigned char', label='Inventory Size'}, -- 04 {ctype='unsigned char', label='Safe Size'}, -- 05 @@ -1559,7 +1559,8 @@ fields.incoming[0x01C] = L{ {ctype='unsigned char', label='Wardrobe 6 Size'}, -- 12 {ctype='unsigned char', label='Wardrobe 7 Size'}, -- 13 {ctype='unsigned char', label='Wardrobe 8 Size'}, -- 14 - {ctype='data[15]', label='_padding1', const=''}, -- 15 + {ctype='unsigned char', label='Recycle Bin Size'}, -- 15 + {ctype='data[14]', label='_padding1', const=''}, -- 16 {ctype='unsigned short', label='_dupeInventory Size'}, -- 24 These "dupe" sizes are set to 0 if the inventory disabled. {ctype='unsigned short', label='_dupeSafe Size'}, -- 26 {ctype='unsigned short', label='_dupeStorage Size'}, -- 28 The accumulated storage from all items (uncapped) -1 @@ -1573,11 +1574,12 @@ fields.incoming[0x01C] = L{ {ctype='unsigned short', label='_dupeWardrobe 2 Size'}, -- 38 {ctype='unsigned short', label='_dupeWardrobe 3 Size'}, -- 3A This is not set to 0 despite being disabled for whatever reason {ctype='unsigned short', label='_dupeWardrobe 4 Size'}, -- 3C This is not set to 0 despite being disabled for whatever reason - {ctype='unsigned short', label='_dupeWardrobe 5 Size'}, -- 3C This is not set to 0 despite being disabled for whatever reason - {ctype='unsigned short', label='_dupeWardrobe 6 Size'}, -- 3C This is not set to 0 despite being disabled for whatever reason - {ctype='unsigned short', label='_dupeWardrobe 7 Size'}, -- 3C This is not set to 0 despite being disabled for whatever reason - {ctype='unsigned short', label='_dupeWardrobe 8 Size'}, -- 3C This is not set to 0 despite being disabled for whatever reason - {ctype='data[30]', label='_padding2', const=''}, -- 3E + {ctype='unsigned short', label='_dupeWardrobe 5 Size'}, -- 3E This is not set to 0 despite being disabled for whatever reason + {ctype='unsigned short', label='_dupeWardrobe 6 Size'}, -- 40 This is not set to 0 despite being disabled for whatever reason + {ctype='unsigned short', label='_dupeWardrobe 7 Size'}, -- 42 This is not set to 0 despite being disabled for whatever reason + {ctype='unsigned short', label='_dupeWardrobe 8 Size'}, -- 44 This is not set to 0 despite being disabled for whatever reason + {ctype='unsigned short', label='_dupeRecycle Bin Size'}, -- 46 + {ctype='data[12]', label='_padding2', const=''}, -- 3E } -- Finish Inventory From fdfbc6d3fff120f9d6929b3a0c97d3d1a5ae3aec Mon Sep 17 00:00:00 2001 From: Byrth Date: Thu, 10 Feb 2022 18:37:46 -0500 Subject: [PATCH 0784/1002] Fix padding for 0x01C --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 17d7d82898..02d4c60cd9 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1579,7 +1579,7 @@ fields.incoming[0x01C] = L{ {ctype='unsigned short', label='_dupeWardrobe 7 Size'}, -- 42 This is not set to 0 despite being disabled for whatever reason {ctype='unsigned short', label='_dupeWardrobe 8 Size'}, -- 44 This is not set to 0 despite being disabled for whatever reason {ctype='unsigned short', label='_dupeRecycle Bin Size'}, -- 46 - {ctype='data[12]', label='_padding2', const=''}, -- 3E + {ctype='data[28]', label='_padding2', const=''}, -- 48 } -- Finish Inventory From d4bd4d414211f0cacebe82374f02017166b492a2 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Fri, 11 Feb 2022 08:51:36 -0700 Subject: [PATCH 0785/1002] Organizer-Lib -- Add Wardrobes --- addons/GearSwap/libs/organizer-lib.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/GearSwap/libs/organizer-lib.lua b/addons/GearSwap/libs/organizer-lib.lua index c3111f6a8a..9ee65aab48 100644 --- a/addons/GearSwap/libs/organizer-lib.lua +++ b/addons/GearSwap/libs/organizer-lib.lua @@ -60,7 +60,7 @@ function org.export_set() -- #trans_item_list[i] = Number of a given item -- trans_item_list[i].id = item ID - local ward_ids = {8,10,11,12} + local ward_ids = {8,10,11,12,13,14,15,16} local wardrobes = {} local ward = {} @@ -234,4 +234,4 @@ function org.string_augments(tab) if tab.augment ~= 'none' then aug_str = aug_str.."'"..augment.."'," end end if aug_str ~= '' then return '{\n'..aug_str..'}' end -end \ No newline at end of file +end From 01140fe846b3eea1429b862be9d9a70c27d9f13f Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Fri, 11 Feb 2022 13:42:56 -0700 Subject: [PATCH 0786/1002] Packets - 0x01D new boolbits and more info --- addons/libs/packets/fields.lua | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 02d4c60cd9..5c82cafce2 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -164,7 +164,7 @@ local function emote(val) end local function bag(val) - return res.bags[val].name + return res.bags[val] and res.bags[val].name or 'Unknown' end local function race(val) @@ -1582,11 +1582,16 @@ fields.incoming[0x01C] = L{ {ctype='data[28]', label='_padding2', const=''}, -- 48 } +types.bagbits= L{ + {ctype='boolbit', label='Finished'} +} -- Finish Inventory fields.incoming[0x01D] = L{ - {ctype='unsigned char', label='Flag'}, -- 04 0 for bag finished updates, 1 for finished loading inventories - {ctype='unsigned char', label='Bag'}, -- 05 18 (0x12) when flag is 1, and 18 is not a valid bag id (last bag + 1) - {ctype='data[6]', label='_junk1'}, -- 06 + {ctype='unsigned char', label='Flag'}, -- 04 0 for bag finished updates, 1 for finished loading all bags + {ctype='unsigned char', label='Bag', fn=bag}, -- 05 18 (0x12) when Flag is 1, and 18 is not a valid bag id (currently last bag + 1) + {ctype='data[2]', label='_junk1'}, -- 06 + {ref=types.bagbits, lookup={res.bags, 0x00}, count=0x12}, -- 08 due to the way packets are sent, false does not necsarilly mean its not Finished, true simple means that it is Finished. + {ctype='data[1]', label='_junk2'}, -- 0B } -- Modify Inventory From 0e85f4c6608db23d37ad4ef3e19dc76b10fe7dc5 Mon Sep 17 00:00:00 2001 From: funkworkz Date: Sun, 13 Feb 2022 00:01:24 -0600 Subject: [PATCH 0787/1002] Update setbgm.lua New song added in Feb update. We still do not know the names. Once we get an OST I will add names. --- addons/setbgm/setbgm.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/setbgm/setbgm.lua b/addons/setbgm/setbgm.lua index 000c7be8f6..88e99c45d7 100644 --- a/addons/setbgm/setbgm.lua +++ b/addons/setbgm/setbgm.lua @@ -50,7 +50,7 @@ music_types = { } songs = { - [25]='Voracious Resurgence Unknown 1', [26]='Voracious Resurgence Unknown 2', [27]='Voracious Resurgence Unknown 3', [28]='Voracious Resurgence Unknown 4', [29]="Devils' Delight", [30]="Odyssey - Bumba", [31]='Voracious Resurgence Unknown 5', [32]='Voracious Resurgence Unknown 6', + [25]='Voracious Resurgence Unknown 1', [26]='Voracious Resurgence Unknown 2', [27]='Voracious Resurgence Unknown 3', [28]='Voracious Resurgence Unknown 4', [29]="Devils' Delight", [30]="Odyssey - Bumba", [31]='Voracious Resurgence Unknown 5', [32]='Voracious Resurgence Unknown 6', [33]='Voracious Resurgence Unknown 7', [40]='Cloister of Time and Souls', [41]='Royal Wanderlust', [42]='Snowdrift Waltz', [43]='Troubled Shadows', [44]='Where Lords Rule Not', [45]='Summers Lost', [46]='Goddess Divine', [47]='Echoes of Creation', [48]='Main Theme', [49]='Luck of the Mog', [50]='Feast of the Ladies', [51]='Abyssea - Scarlet Skies, Shadowed Plains', [52]='Melodies Errant', [53]='Shinryu', [54]='Everlasting Bonds', [55]='Provenance Watcher', [56]='Where it All Begins', [57]='Steel Sings, Blades Dance', [58]='A New Direction', [59]='The Pioneers', [60]='Into Lands Primeval - Ulbuka', [61]="Water's Umbral Knell", [62]='Keepers of the Wild', [63]='The Sacred City of Adoulin', [64]='Breaking Ground', [65]='Hades', [66]='Arciela', [67]='Mog Resort', [68]='Worlds Away', [69]="Distant Worlds (Nanaa Mihgo's version)", From 33a2b536a74202d6322deffd84cddb2bfe84963c Mon Sep 17 00:00:00 2001 From: Byrth Date: Sun, 13 Feb 2022 07:40:29 -0500 Subject: [PATCH 0788/1002] add new 0x01D handling to instaLS --- addons/instaLS/instaLS.lua | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/addons/instaLS/instaLS.lua b/addons/instaLS/instaLS.lua index 26b7e8b784..5a6de182f4 100644 --- a/addons/instaLS/instaLS.lua +++ b/addons/instaLS/instaLS.lua @@ -25,27 +25,27 @@ --SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'instaLS' -_addon.version = 0.160309 +_addon.version = 0.220213 _addon.author = 'Byrth' -flag=false +linkshell_inventories_loaded = true chatmode = {} chatcolor = {} message = false require 'strings' - +bit = require 'bit' function translate_escape(str) return str:escape():gsub(string.char(0xFD)..".-"..string.char(0xFD),string.char(0xEF,0x27).."(.-)"..string.char(0xEF,0x25,0x25,0x28)) end windower.register_event('zone change',function() - flag=false + linkshell_inventories_loaded = false end) -windower.register_event('incoming chunk',function(id) - if id == 0x1D then - flag = true +windower.register_event('incoming chunk', function(id,org) + if not linkshell_inventories_loaded and id == 0x01D then + linkshell_inventories_loaded = bit.band(org:byte(0x09), 225) == 225 end end) @@ -68,7 +68,8 @@ windower.register_event('incoming text',function(org, mod, col) end) windower.register_event('outgoing text',function(org,mod,bool) - if bool or flag then return end + if bool or linkshell_inventories_loaded then return end + windower.add_to_chat(8,'using instaLS') if mod:sub(1,3) == '/l ' then chatmode[#chatmode+1] = 0x05 chatcolor[#chatcolor+1] = 6 From f21d2f9d9b8fe314b5b1bc2ae7a842f8961baace Mon Sep 17 00:00:00 2001 From: Byrth Date: Sun, 13 Feb 2022 08:44:59 -0500 Subject: [PATCH 0789/1002] Update instaLS.lua --- addons/instaLS/instaLS.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/addons/instaLS/instaLS.lua b/addons/instaLS/instaLS.lua index 5a6de182f4..ca729bec52 100644 --- a/addons/instaLS/instaLS.lua +++ b/addons/instaLS/instaLS.lua @@ -69,7 +69,6 @@ end) windower.register_event('outgoing text',function(org,mod,bool) if bool or linkshell_inventories_loaded then return end - windower.add_to_chat(8,'using instaLS') if mod:sub(1,3) == '/l ' then chatmode[#chatmode+1] = 0x05 chatcolor[#chatcolor+1] = 6 @@ -91,4 +90,4 @@ windower.register_event('outgoing text',function(org,mod,bool) end return '/s '..message -end) \ No newline at end of file +end) From df9082dc0dfb2128594c4239b4797f90442fb9e1 Mon Sep 17 00:00:00 2001 From: Byrth Date: Mon, 14 Feb 2022 16:54:49 -0500 Subject: [PATCH 0790/1002] fix both problems --- addons/boxdestroyer/boxdestroyer.lua | 37 ++++++++++++++-------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/addons/boxdestroyer/boxdestroyer.lua b/addons/boxdestroyer/boxdestroyer.lua index af70616bba..b537b642f9 100644 --- a/addons/boxdestroyer/boxdestroyer.lua +++ b/addons/boxdestroyer/boxdestroyer.lua @@ -48,6 +48,7 @@ config = require('config') defaults = { HighlightResult = false, HighlightColor = 36, + DisplayRemainingCombinations = false, } settings = config.load(defaults) -- global constants @@ -265,39 +266,37 @@ end -- display helper function function display(id, chances) - if #box[id] == 90 then - windower.add_to_chat(207, 'Possible combinations: 10~99') - else - windower.add_to_chat(207, 'Possible combinations: ' .. table.concat(box[id], ' ')) + if settings.DisplayRemainingCombinations then + if #box[id] == 90 then + windower.add_to_chat(207, 'Possible combinations: 10~99') + else + windower.add_to_chat(207, 'Possible combinations: ' .. table.concat(box[id], ' ')) + end end - local remaining = math.floor(#box[id] / math.pow(2, (chances - 1))) + local probability = math.min(100, math.floor(100 * (math.pow(2, chances) - 1) / #box[id] )) + local remaining = math.floor(#box[id] / math.pow(2, chances - 1)) if remaining == 0 then remaining = 1 end + + local guess_number = box[id][math.ceil(#box[id] / 2)] if chances == 1 and observed[id].equal then - -- The "equal" message (== "X") for X in 1..9 gives an unequal probability to the remaining options + -- The "equal" message (== "X") for X in 1..9 gives an unequal probability to the remaining options -- because "XX" is twice as likely to be indicated by the "equal" message. -- This is too annoying to propagate to the rest of the addon, although it should be some day. - local printed = false for _,v in pairs(box[id]) do if math.floor(v/10) == v%10 then - windower.add_to_chat(207, 'Best guess: %d (%d%%)':format(v, 1 / remaining * 100)) - printed = true + guess_number = v break end end - if not printed then - windower.add_to_chat(207, 'Best guess: %d (%d%%)':format(box[id][math.ceil(#box[id] / 2)], 1 / remaining * 100)) - end - else - windower.add_to_chat(207, 'best guess: %d (%d%%)':format(box[id][math.ceil(#box[id] / 2)], 1 / remaining * 100)) - local clue_value,guess_value = calculate_odds(id,chances) - local result = clue_value > guess_value and remaining ~= 1 and 'examining the chest' or 'guessing ' .. '%d':format(box[id][math.ceil(#box[id] / 2)]) - local formatted_result = settings.HighlightResult and result:color(settings.HighlightColor) or result - windower.add_to_chat(207, 'boxdestroyer recommends ' .. formatted_result .. '.') end - + local clue_value,guess_value = calculate_odds(id,chances) + local result = clue_value > guess_value and remaining ~= 1 and 'examining the lock' or 'guessing %d (%d%%)':format(guess_number, probability) + local formatted_result = settings.HighlightResult and result:color(settings.HighlightColor) or result + windower.add_to_chat(207, 'boxdestroyer recommends ' .. formatted_result) + end -- ID obtaining helper function From d1b0d03293a997e219e04ce8be45afcc7ac8eb20 Mon Sep 17 00:00:00 2001 From: Byrth Date: Mon, 14 Feb 2022 16:56:38 -0500 Subject: [PATCH 0791/1002] bump version --- addons/boxdestroyer/boxdestroyer.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/boxdestroyer/boxdestroyer.lua b/addons/boxdestroyer/boxdestroyer.lua index b537b642f9..7b538a774d 100644 --- a/addons/boxdestroyer/boxdestroyer.lua +++ b/addons/boxdestroyer/boxdestroyer.lua @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- addon information _addon.name = 'boxdestroyer' -_addon.version = '1.0.5' +_addon.version = '1.0.6' _addon.command = 'boxdestroyer' _addon.author = 'Seth VanHeulen (Acacia@Odin)' From 22fabff162267f429d328e29b816f1b824f8cd88 Mon Sep 17 00:00:00 2001 From: Byrth Date: Mon, 14 Feb 2022 18:11:38 -0500 Subject: [PATCH 0792/1002] Update README for changes --- addons/boxdestroyer/README | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/addons/boxdestroyer/README b/addons/boxdestroyer/README index a34f5b9833..a8d0983c69 100644 --- a/addons/boxdestroyer/README +++ b/addons/boxdestroyer/README @@ -8,5 +8,6 @@ Donations are welcome in the form of Alexandrite: Acacia on Odin (http://www.ffxiah.com/player/Odin/Acacia) With this addon loaded, just click on any brown treasure casket and it -will display info about possible combinations, the best number to guess -and the worst case chance of guessing correctly. +will recommend whether to examine the chest or guess a number. When it +recommends guessing a number, your probability of success with an +optimal guess-only strategy is also displayed. From d7fde530ba350ad46e1e7b081270ef63e3c4c748 Mon Sep 17 00:00:00 2001 From: zetaepyon Date: Mon, 14 Feb 2022 17:11:52 -0600 Subject: [PATCH 0793/1002] Update README.md Escape on `` --- addons/plugin_manager/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/plugin_manager/README.md b/addons/plugin_manager/README.md index dc4cbd0c6b..f6822552da 100644 --- a/addons/plugin_manager/README.md +++ b/addons/plugin_manager/README.md @@ -26,4 +26,4 @@ ## Settings Files The settings file for Plugin Manager are found in a single XML file with a format similar to the settings files for plugins. -* `data/settings.xml` - contains plugins and addons specific to each character. is loaded if there is not a set of plugins/addons inside tags that are a case-sensitive match to the player's name. +* `data/settings.xml` - contains plugins and addons specific to each character. \ is loaded if there is not a set of plugins/addons inside tags that are a case-sensitive match to the player's name. From e0123399cdc501e4ecf3075e0a2806dd87935355 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Wed, 16 Feb 2022 04:48:29 +0100 Subject: [PATCH 0794/1002] Slips lib update Adding February items to the slips lib. --- addons/libs/slips.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 9fd59b1568..c7d7b74208 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -15,7 +15,7 @@ slips.storages = L{29312, 29313, 29314, 29315, 29316, 29317, 29318, 2931 slips.items = { [slips.storages[1]] = L{16084, 14546, 14961, 15625, 15711, 16085, 14547, 14962, 15626, 15712, 16086, 14548, 14963, 15627, 15713, 16087, 14549, 14964, 15628, 15714, 16088, 14550, 14965, 15629, 15715, 16089, 14551, 14966, 15630, 15716, 16090, 14552, 14967, 15631, 15717, 16091, 14553, 14968, 15632, 15718, 16092, 14554, 14969, 15633, 15719, 16093, 14555, 14970, 15634, 15720, 16094, 14556, 14971, 15635, 15721, 16095, 14557, 14972, 15636, 15722, 16096, 14558, 14973, 15637, 15723, 16097, 14559, 14974, 15638, 15724, 16098, 14560, 14975, 15639, 15725, 16099, 14561, 14976, 15640, 15726, 16100, 14562, 14977, 15641, 15727, 16101, 14563, 14978, 15642, 15728, 16102, 14564, 14979, 15643, 15729, 16103, 14565, 14980, 15644, 15730, 16106, 14568, 14983, 15647, 15733, 16107, 14569, 14984, 15648, 15734, 16108, 14570, 14985, 15649, 15735, 16602, 17741, 18425, 18491, 18588, 18717, 18718, 18850, 18943, 16069, 14530, 14940, 15609, 15695, 16062, 14525, 14933, 15604, 15688, 16064, 14527, 14935, 15606, 15690, 18685, 18065, 17851, 18686, 18025, 18435, 18113, 17951, 17715, 18485, 18408, 18365, 18583, 18417, 18388, 16267, 16268, 16269, 16228, 16229, 15911, 15799, 15800, 15990, 17745, 18121, 16117, 14577, 17857}, -- 168 [slips.storages[2]] = L{12421, 12549, 12677, 12805, 12933, 13911, 14370, 14061, 14283, 14163, 12429, 12557, 12685, 12813, 12941, 13924, 14371, 14816, 14296, 14175, 13934, 14387, 14821, 14303, 14184, 13935, 14388, 14822, 14304, 14185, 13876, 13787, 14006, 14247, 14123, 13877, 13788, 14007, 14248, 14124, 13908, 14367, 14058, 14280, 14160, 13909, 14368, 14059, 14281, 14161, 16113, 14573, 14995, 15655, 15740, 16115, 14575, 14997, 15657, 15742, 16114, 14574, 14996, 15656, 15741, 16116, 14576, 14998, 15658, 15743, 12818, 18198, 12946, 18043, 12690, 17659, 12296, 12434, 15471, 15472, 15473, 15508, 15509, 15510, 15511, 15512, 15513, 15514, 17710, 17595, 18397, 18360, 18222, 17948, 18100, 15475, 15476, 15477, 15488, 15961, 14815, 14812, 14813, 15244, 15240, 14488, 14905, 15576, 15661, 15241, 14489, 14906, 15577, 15662, 13927, 14378, 14076, 14308, 14180, 13928, 14379, 14077, 14309, 14181, 10438, 10276, 10320, 10326, 10367, 10439, 10277, 10321, 10327, 10368, 10440, 10278, 10322, 10328, 10369, 10441, 10279, 10323, 10329, 10370, 25734, 25735, 25736, 25737, 25738, 25739, 25740, 25741, 25742, 25743, 25744}, -- 155 - [slips.storages[3]] = L{16155, 11282, 15021, 16341, 11376, 16156, 11283, 15022, 16342, 11377, 16157, 11284, 15023, 16343, 11378, 16148, 14590, 15011, 16317, 15757, 16143, 14591, 15012, 16318, 15758, 16146, 14588, 15009, 16315, 15755, 16147, 14589, 15010, 16316, 15756, 15966, 15967, 19041, 17684, 17685, 11636, 15844, 15934, 16258, 18735, 18734, 16291, 16292, 19042, 15935, 16293, 16294, 15936, 18618, 11588, 11545, 16158, 16159, 16160, 16149, 14583, 15007, 16314, 15751, 16141, 14581, 15005, 16312, 15749, 16142, 14582, 15006, 16313, 15750, 10876, 10450, 10500, 11969, 10600, 10877, 10451, 10501, 11970, 10601, 10878, 10452, 10502, 11971, 10602, 19132, 18551, 11798, 11362, 11363, 11625, 15959, 16259, 22299, 26414, 21623, 26219, 21886, 23792, 23793, 23794, 23795, 23796, 22032, 22043, 21530, 22044, 26273}, -- 112 + [slips.storages[3]] = L{16155, 11282, 15021, 16341, 11376, 16156, 11283, 15022, 16342, 11377, 16157, 11284, 15023, 16343, 11378, 16148, 14590, 15011, 16317, 15757, 16143, 14591, 15012, 16318, 15758, 16146, 14588, 15009, 16315, 15755, 16147, 14589, 15010, 16316, 15756, 15966, 15967, 19041, 17684, 17685, 11636, 15844, 15934, 16258, 18735, 18734, 16291, 16292, 19042, 15935, 16293, 16294, 15936, 18618, 11588, 11545, 16158, 16159, 16160, 16149, 14583, 15007, 16314, 15751, 16141, 14581, 15005, 16312, 15749, 16142, 14582, 15006, 16313, 15750, 10876, 10450, 10500, 11969, 10600, 10877, 10451, 10501, 11970, 10601, 10878, 10452, 10502, 11971, 10602, 19132, 18551, 11798, 11362, 11363, 11625, 15959, 16259, 22299, 26414, 21623, 26219, 21886, 23792, 23793, 23794, 23795, 23796, 22032, 22043, 21530, 22044, 26273, 25415}, -- 113 [slips.storages[4]] = L{12511, 12638, 13961, 14214, 14089, 12512, 12639, 13962, 14215, 14090, 13855, 12640, 13963, 14216, 14091, 13856, 12641, 13964, 14217, 14092, 12513, 12642, 13965, 14218, 14093, 12514, 12643, 13966, 14219, 14094, 12515, 12644, 13967, 14220, 14095, 12516, 12645, 13968, 14221, 14096, 12517, 12646, 13969, 14222, 14097, 13857, 12647, 13970, 14223, 14098, 12518, 12648, 13971, 14099, 14224, 13868, 13781, 13972, 14225, 14100, 13869, 13782, 13973, 14226, 14101, 12519, 12649, 13974, 14227, 14102, 12520, 12650, 13975, 14228, 14103, 15265, 14521, 14928, 15600, 15684, 15266, 14522, 14929, 15601, 15685, 15267, 14523, 14930, 15602, 15686, 16138, 14578, 15002, 15659, 15746, 16139, 14579, 15003, 15660, 15747, 16140, 14580, 15004, 16311, 15748, 16678, 17478, 17422, 17423, 16829, 16764, 17643, 16798, 16680, 16766, 17188, 17812, 17771, 17772, 16887, 17532, 17717, 18702, 17858, 19203, 21461, 21124, 20776, 27786, 27926, 28066, 28206, 28346, 27787, 27927, 28067, 28207, 28347}, -- 138 [slips.storages[5]] = L{15225, 14473, 14890, 15561, 15352, 15226, 14474, 14891, 15562, 15353, 15227, 14475, 14892, 15563, 15354, 15228, 14476, 14893, 15564, 15355, 15229, 14477, 14894, 15565, 15356, 15230, 14478, 14895, 15566, 15357, 15231, 14479, 14896, 15567, 15358, 15232, 14480, 14897, 15568, 15359, 15233, 14481, 14898, 15569, 15360, 15234, 14482, 14899, 15570, 15361, 15235, 14483, 14900, 15362, 15571, 15236, 14484, 14901, 15572, 15363, 15237, 14485, 14902, 15573, 15364, 15238, 14486, 14903, 15574, 15365, 15239, 14487, 14904, 15575, 15366, 11464, 11291, 15024, 16345, 11381, 11467, 11294, 15027, 16348, 11384, 11470, 11297, 15030, 16351, 11387, 11475, 11302, 15035, 16357, 11393, 11476, 11303, 15036, 16358, 11394, 11477, 11304, 15037, 16359, 11395}, -- 105 [slips.storages[6]] = L{15072, 15087, 15102, 15117, 15132, 15871, 15073, 15088, 15103, 15118, 15133, 15478, 15074, 15089, 15104, 15119, 15134, 15872, 15075, 15090, 15105, 15120, 15135, 15874, 15076, 15091, 15106, 15121, 15136, 15873, 15077, 15092, 15107, 15122, 15137, 15480, 15078, 15093, 15108, 15123, 15138, 15481, 15079, 15094, 15109, 15124, 15139, 15479, 15080, 15095, 15110, 15125, 15140, 15875, 15081, 15096, 15111, 15126, 15141, 15482, 15082, 15097, 15112, 15127, 15142, 15876, 15083, 15098, 15113, 15128, 15143, 15879, 15084, 15099, 15114, 15129, 15144, 15877, 15085, 15100, 15115, 15130, 15145, 15878, 15086, 15101, 15116, 15131, 15146, 15484, 11465, 11292, 15025, 16346, 11382, 16244, 11468, 11295, 15028, 16349, 11385, 15920, 11471, 11298, 15031, 16352, 11388, 16245, 11478, 11305, 15038, 16360, 11396, 16248, 11480, 11307, 15040, 16362, 11398, 15925}, -- 120 @@ -34,8 +34,8 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757, 25909}, -- 192 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046}, -- 145 SE Skipped an index hence the 0 as one of the items - [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067, 21680}, --176 + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751}, -- 146 SE Skipped an index hence the 0 as one of the items + [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067, 21680, 22071}, --177 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, --115 [slips.storages[26]] = L{23063, 23130, 23197, 23264, 23331, 23064, 23131, 23198, 23265, 23332, 23065, 23132, 23199, 23266, 23333, 23066, 23133, 23200, 23267, 23334, 23067, 23134, 23201, 23268, 23335, 23068, 23135, 23202, 23269, 23336, 23069, 23136, 23203, 23270, 23337, 23070, 23137, 23204, 23271, 23338, 23071, 23138, 23205, 23272, 23339, 23072, 23139, 23206, 23273, 23340, 23073, 23140, 23207, 23274, 23341, 23074, 23141, 23208, 23275, 23342, 23075, 23142, 23209, 23276, 23343, 23076, 23143, 23210, 23277, 23344, 23077, 23144, 23211, 23278, 23345, 23078, 23145, 23212, 23279, 23346, 23079, 23146, 23213, 23280, 23347, 23080, 23147, 23214, 23281, 23348, 23081, 23148, 23215, 23282, 23349, 23082, 23149, 23216, 23283, 23350, 23083, 23150, 23217, 23284, 23351, 23084, 23151, 23218, 23285, 23352}, --110 From c636840c9d80a6118c812697eb3ad8cc248be653 Mon Sep 17 00:00:00 2001 From: Sechs Date: Wed, 16 Feb 2022 11:29:58 +0100 Subject: [PATCH 0795/1002] Update validate.lua Hi, I expanded the "Validate inventory" function. Normally it just works on a single repository (your inventory). I modified so you can do it on any repository, one at a time. Validate wardrobe3, validate safe, validate storage etc. It's updated with the newest additions of Wardrobes5-8. If you use a custom Lua that includes all the Sets from all your jobs lua, you can basically check one repository at a time to find items that are present in those repositories but no longer present in any lua, i.e. items you no longer use. It's basically a tool to clean up repositories from items you no longer use but are not aware of. Multiple people have been using this tool but until now it required to temporarily overwrite the default validate with my custom one, then restore the original one after you're done with the cleaning. Implemeting these changes in the basic Validate.lua would make this step no longer necessary. More detailed info on how it works can be find in the related FFXIAH thread https://www.ffxiah.com/forum/topic/54596/custom-gearswap-validate-to-clean-up-inventory/#3495138 There is one thing I'm unsure of. I originally developed this custom lua several years ago, and I recently updated it adding Wardrobe5-8. This means the original Validate.lua I used as a core for my custom might have been older than the current Validate.lua Someone more competent than me would need to doublecheck that I didn't miss any important (new) feature in my custom version. Shouldn't take long, I didn't really add too many lines to the original code in the end. Thanks for your time. --- addons/GearSwap/validate.lua | 89 +++++++++++++++++++++++++----------- 1 file changed, 63 insertions(+), 26 deletions(-) diff --git a/addons/GearSwap/validate.lua b/addons/GearSwap/validate.lua index 596987842f..d7800b4ea4 100644 --- a/addons/GearSwap/validate.lua +++ b/addons/GearSwap/validate.lua @@ -37,17 +37,63 @@ function validate(options) local validateType = 'sets' if options and #options > 0 then if S{'sets','set','s'}:contains(options[1]:lower()) then + validateType = 'sets' table.remove(options,1) elseif S{'inventory','inv','i'}:contains(options[1]:lower()) then - validateType = 'inv' + validateType = 'inventory' table.remove(options,1) - end + elseif S{'mogsafe','safe','ms','bank'}:contains(options[1]:lower()) then + validateType = 'safe' + table.remove(options,1) + elseif S{'mogsafe2','safe2','ms2','bank2'}:contains(options[1]:lower()) then + validateType = 'safe2' + table.remove(options,1) + elseif S{'storage','st'}:contains(options[1]:lower()) then + validateType = 'storage' + table.remove(options,1) + elseif S{'moglocker','locker','ml'}:contains(options[1]:lower()) then + validateType = 'locker' + table.remove(options,1) + elseif S{'mogsatchel','satchel','sa'}:contains(options[1]:lower()) then + validateType = 'satchel' + table.remove(options,1) + elseif S{'mogsack','sack','sk'}:contains(options[1]:lower()) then + validateType = 'sack' + table.remove(options,1) + elseif S{'mogcase','case','c'}:contains(options[1]:lower()) then + validateType = 'case' + table.remove(options,1) + elseif S{'wardrobe','w'}:contains(options[1]:lower()) then + validateType = 'wardrobe' + table.remove(options,1) + elseif S{'wardrobe2','w2'}:contains(options[1]:lower()) then + validateType = 'wardrobe2' + table.remove(options,1) + elseif S{'wardrobe3','w3'}:contains(options[1]:lower()) then + validateType = 'wardrobe3' + table.remove(options,1) + elseif S{'wardrobe4','w4'}:contains(options[1]:lower()) then + validateType = 'wardrobe4' + table.remove(options,1) + elseif S{'wardrobe5','w5'}:contains(options[1]:lower()) then + validateType = 'wardrobe5' + table.remove(options,1) + elseif S{'wardrobe6','w6'}:contains(options[1]:lower()) then + validateType = 'wardrobe6' + table.remove(options,1) + elseif S{'wardrobe7','w7'}:contains(options[1]:lower()) then + validateType = 'wardrobe7' + table.remove(options,1) + elseif S{'wardrobe8','w8'}:contains(options[1]:lower()) then + validateType = 'wardrobe8' + table.remove(options,1) + end end - - if validateType == 'inv' then - validate_inventory(options) - else + + if validateType == 'sets' then validate_sets(options) + else + validate_inventory(options, validateType) end end @@ -55,11 +101,13 @@ end -- Functions to handle the primary logic separation. ------------------------------------------------------------------------------------------------------------------- --- Function for determining and displaying which items from a player's inventory are not in their gear sets. -function validate_inventory(filter) - msg.addon_msg(123,'Checking for items in inventory that are not used in your gear sets.') - - local extra_items = search_sets_for_items_in_bag(items.inventory, filter) +-- Function for determining and displaying which items from a player's selected repository are not in their gear sets. +function validate_inventory(filter, repository) + msg.addon_msg(123,'Checking for items in '..repository..' that are not used in your gear sets.') + + --msg.addon_msg(123,items.repository) + + local extra_items = search_sets_for_items_in_bag(items[repository], filter) local display_list = get_item_names(extra_items):sort(insensitive_sort) display_list:map(function(item) msg.add_to_chat(120, windower.to_shift_jis((string.gsub(item, "^%l", string.upper))) ) end) @@ -99,9 +147,8 @@ function get_item_name(item) elseif item.name then name = item.name end - - - local aug = item.aug and table.concat(item.aug,', ') or get_augment_string(item) + + local aug = get_augment_string(item) if aug then name = name .. ' {' .. aug .. '}' end @@ -188,9 +235,8 @@ function search_bags_for_items_in_set(gear_table, filter, missing_items, stack) if type(name) == 'string' and name ~= 'empty' and name ~= '' and type(i) == 'string' then if not slot_map[i] then msg.addon_msg(123,windower.to_shift_jis(tostring(i))..' contains a "name" element but is not a valid slot.') - elseif tryfilter(lowercase_name(name), filter) and not find_in_equippable_inventories(name, aug) then - -- This is one spot where inventory names will be left hardcoded until an equippable bool is added to the resources - missing_items:add({name=lowercase_name(name),aug=aug}) + elseif tryfilter(lowercase_name(name), filter) and not find_in_inv(items.inventory, name, aug) and not find_in_inv(items.wardrobe, name, aug) and not find_in_inv(items.wardrobe2, name, aug) then + missing_items:add(lowercase_name(name)) end elseif type(name) == 'table' and name ~= empty then if not stack then stack = S{} end @@ -204,15 +250,6 @@ function search_bags_for_items_in_set(gear_table, filter, missing_items, stack) return missing_items end --- Utility function to search equippable inventories -function find_in_equippable_inventories(name,aug) - for _,bag in pairs(equippable_item_bags) do - if find_in_inv(items[to_windower_bag_api(bag.en)], name, aug) then - return true - end - end -end - -- Utility function to help search sets function find_in_sets(item, tab, stack) if stack and stack:contains(tab) then From 66d14c3b107b057cb769861efc03f884943ebce5 Mon Sep 17 00:00:00 2001 From: Sechs Date: Wed, 16 Feb 2022 11:47:40 +0100 Subject: [PATCH 0796/1002] Update validate.lua Updated indentation for better reading --- addons/GearSwap/validate.lua | 54 ++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/addons/GearSwap/validate.lua b/addons/GearSwap/validate.lua index d7800b4ea4..bf955a57eb 100644 --- a/addons/GearSwap/validate.lua +++ b/addons/GearSwap/validate.lua @@ -37,57 +37,57 @@ function validate(options) local validateType = 'sets' if options and #options > 0 then if S{'sets','set','s'}:contains(options[1]:lower()) then - validateType = 'sets' + validateType = 'sets' table.remove(options,1) elseif S{'inventory','inv','i'}:contains(options[1]:lower()) then validateType = 'inventory' table.remove(options,1) - elseif S{'mogsafe','safe','ms','bank'}:contains(options[1]:lower()) then - validateType = 'safe' - table.remove(options,1) - elseif S{'mogsafe2','safe2','ms2','bank2'}:contains(options[1]:lower()) then - validateType = 'safe2' - table.remove(options,1) - elseif S{'storage','st'}:contains(options[1]:lower()) then + elseif S{'mogsafe','safe','ms','bank'}:contains(options[1]:lower()) then + validateType = 'safe' + table.remove(options,1) + elseif S{'mogsafe2','safe2','ms2','bank2'}:contains(options[1]:lower()) then + validateType = 'safe2' + table.remove(options,1) + elseif S{'storage','st'}:contains(options[1]:lower()) then validateType = 'storage' - table.remove(options,1) - elseif S{'moglocker','locker','ml'}:contains(options[1]:lower()) then - validateType = 'locker' - table.remove(options,1) - elseif S{'mogsatchel','satchel','sa'}:contains(options[1]:lower()) then + table.remove(options,1) + elseif S{'moglocker','locker','ml'}:contains(options[1]:lower()) then + validateType = 'locker' + table.remove(options,1) + elseif S{'mogsatchel','satchel','sa'}:contains(options[1]:lower()) then validateType = 'satchel' - table.remove(options,1) - elseif S{'mogsack','sack','sk'}:contains(options[1]:lower()) then + table.remove(options,1) + elseif S{'mogsack','sack','sk'}:contains(options[1]:lower()) then validateType = 'sack' - table.remove(options,1) - elseif S{'mogcase','case','c'}:contains(options[1]:lower()) then + table.remove(options,1) + elseif S{'mogcase','case','c'}:contains(options[1]:lower()) then validateType = 'case' - table.remove(options,1) - elseif S{'wardrobe','w'}:contains(options[1]:lower()) then + table.remove(options,1) + elseif S{'wardrobe','w'}:contains(options[1]:lower()) then validateType = 'wardrobe' table.remove(options,1) - elseif S{'wardrobe2','w2'}:contains(options[1]:lower()) then + elseif S{'wardrobe2','w2'}:contains(options[1]:lower()) then validateType = 'wardrobe2' table.remove(options,1) - elseif S{'wardrobe3','w3'}:contains(options[1]:lower()) then + elseif S{'wardrobe3','w3'}:contains(options[1]:lower()) then validateType = 'wardrobe3' table.remove(options,1) - elseif S{'wardrobe4','w4'}:contains(options[1]:lower()) then + elseif S{'wardrobe4','w4'}:contains(options[1]:lower()) then validateType = 'wardrobe4' table.remove(options,1) - elseif S{'wardrobe5','w5'}:contains(options[1]:lower()) then + elseif S{'wardrobe5','w5'}:contains(options[1]:lower()) then validateType = 'wardrobe5' table.remove(options,1) - elseif S{'wardrobe6','w6'}:contains(options[1]:lower()) then + elseif S{'wardrobe6','w6'}:contains(options[1]:lower()) then validateType = 'wardrobe6' table.remove(options,1) - elseif S{'wardrobe7','w7'}:contains(options[1]:lower()) then + elseif S{'wardrobe7','w7'}:contains(options[1]:lower()) then validateType = 'wardrobe7' table.remove(options,1) - elseif S{'wardrobe8','w8'}:contains(options[1]:lower()) then + elseif S{'wardrobe8','w8'}:contains(options[1]:lower()) then validateType = 'wardrobe8' table.remove(options,1) - end + end end if validateType == 'sets' then From 21c1d1056ae29b078edc7fca8d7f24034ec9edfe Mon Sep 17 00:00:00 2001 From: Sechs Date: Wed, 16 Feb 2022 11:51:57 +0100 Subject: [PATCH 0797/1002] Update validate.lua fixed indentation some more >_> --- addons/GearSwap/validate.lua | 52 ++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/addons/GearSwap/validate.lua b/addons/GearSwap/validate.lua index bf955a57eb..f1b4d80fb0 100644 --- a/addons/GearSwap/validate.lua +++ b/addons/GearSwap/validate.lua @@ -37,57 +37,57 @@ function validate(options) local validateType = 'sets' if options and #options > 0 then if S{'sets','set','s'}:contains(options[1]:lower()) then - validateType = 'sets' + validateType = 'sets' table.remove(options,1) elseif S{'inventory','inv','i'}:contains(options[1]:lower()) then validateType = 'inventory' table.remove(options,1) - elseif S{'mogsafe','safe','ms','bank'}:contains(options[1]:lower()) then - validateType = 'safe' - table.remove(options,1) - elseif S{'mogsafe2','safe2','ms2','bank2'}:contains(options[1]:lower()) then - validateType = 'safe2' - table.remove(options,1) - elseif S{'storage','st'}:contains(options[1]:lower()) then + elseif S{'mogsafe','safe','ms','bank'}:contains(options[1]:lower()) then + validateType = 'safe' + table.remove(options,1) + elseif S{'mogsafe2','safe2','ms2','bank2'}:contains(options[1]:lower()) then + validateType = 'safe2' + table.remove(options,1) + elseif S{'storage','st'}:contains(options[1]:lower()) then validateType = 'storage' - table.remove(options,1) - elseif S{'moglocker','locker','ml'}:contains(options[1]:lower()) then - validateType = 'locker' - table.remove(options,1) - elseif S{'mogsatchel','satchel','sa'}:contains(options[1]:lower()) then + table.remove(options,1) + elseif S{'moglocker','locker','ml'}:contains(options[1]:lower()) then + validateType = 'locker' + table.remove(options,1) + elseif S{'mogsatchel','satchel','sa'}:contains(options[1]:lower()) then validateType = 'satchel' - table.remove(options,1) - elseif S{'mogsack','sack','sk'}:contains(options[1]:lower()) then + table.remove(options,1) + elseif S{'mogsack','sack','sk'}:contains(options[1]:lower()) then validateType = 'sack' table.remove(options,1) - elseif S{'mogcase','case','c'}:contains(options[1]:lower()) then + elseif S{'mogcase','case','c'}:contains(options[1]:lower()) then validateType = 'case' - table.remove(options,1) - elseif S{'wardrobe','w'}:contains(options[1]:lower()) then + table.remove(options,1) + elseif S{'wardrobe','w'}:contains(options[1]:lower()) then validateType = 'wardrobe' table.remove(options,1) - elseif S{'wardrobe2','w2'}:contains(options[1]:lower()) then + elseif S{'wardrobe2','w2'}:contains(options[1]:lower()) then validateType = 'wardrobe2' table.remove(options,1) - elseif S{'wardrobe3','w3'}:contains(options[1]:lower()) then + elseif S{'wardrobe3','w3'}:contains(options[1]:lower()) then validateType = 'wardrobe3' table.remove(options,1) - elseif S{'wardrobe4','w4'}:contains(options[1]:lower()) then + elseif S{'wardrobe4','w4'}:contains(options[1]:lower()) then validateType = 'wardrobe4' table.remove(options,1) - elseif S{'wardrobe5','w5'}:contains(options[1]:lower()) then + elseif S{'wardrobe5','w5'}:contains(options[1]:lower()) then validateType = 'wardrobe5' table.remove(options,1) - elseif S{'wardrobe6','w6'}:contains(options[1]:lower()) then + elseif S{'wardrobe6','w6'}:contains(options[1]:lower()) then validateType = 'wardrobe6' table.remove(options,1) - elseif S{'wardrobe7','w7'}:contains(options[1]:lower()) then + elseif S{'wardrobe7','w7'}:contains(options[1]:lower()) then validateType = 'wardrobe7' table.remove(options,1) - elseif S{'wardrobe8','w8'}:contains(options[1]:lower()) then + elseif S{'wardrobe8','w8'}:contains(options[1]:lower()) then validateType = 'wardrobe8' table.remove(options,1) - end + end end if validateType == 'sets' then From 91f90cde14bdc2c6d2501167351899665f664511 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Wed, 16 Feb 2022 14:45:41 +0100 Subject: [PATCH 0798/1002] [Battlemod] Fix for aoe ws skillchains Fixing for aoe ws skillschains reporting all targets and not just the one that effectively got the skillchain. Reported on issue https://github.com/Windower/Lua/issues/2154 --- addons/battlemod/parse_action_packet.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/addons/battlemod/parse_action_packet.lua b/addons/battlemod/parse_action_packet.lua index 93304ed70e..f7736d703d 100644 --- a/addons/battlemod/parse_action_packet.lua +++ b/addons/battlemod/parse_action_packet.lua @@ -334,7 +334,7 @@ function parse_action_packet(act) 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 targ = assemble_targets(act.actor,v.target,act.category,m.add_effect_message,m.has_add_effect) 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] @@ -385,7 +385,7 @@ function parse_action_packet(act) 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 targ = assemble_targets(act.actor,v.target,act.category,m.spike_effect_message, m.has_spike_effect) local col = res.action_messages[m.spike_effect_message].color local color = color_filt(col,act.actor.id==Self.id) @@ -559,7 +559,7 @@ function simplify_message(msg_ID) return msg end -function assemble_targets(actor,targs,category,msg) +function assemble_targets(actor,targs,category,msg,add_effect) local targets = {} local samename = {} local total = 0 @@ -575,6 +575,7 @@ function assemble_targets(actor,targs,category,msg) end total = total + 1 end + if add_effect then break end end local out_str if targetnumber and total > 1 then From c52809a3eec47af3acd75d9146dffedbefc05a42 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Wed, 16 Feb 2022 14:51:17 +0100 Subject: [PATCH 0799/1002] GearSwap: Minor adjustments to bag validation --- addons/GearSwap/validate.lua | 111 +++++++++++++---------------------- 1 file changed, 42 insertions(+), 69 deletions(-) diff --git a/addons/GearSwap/validate.lua b/addons/GearSwap/validate.lua index f1b4d80fb0..1757a92328 100644 --- a/addons/GearSwap/validate.lua +++ b/addons/GearSwap/validate.lua @@ -28,6 +28,26 @@ -- Primary entry point. ------------------------------------------------------------------------------------------------------------------- +local validate_keys = { + sets = 'sets', set = 'sets', s = 'sets', + inventory = 'inventory', inv = 'inventory', i = 'inventory' + mogsafe = 'safe', safe = 'safe', ms = 'safe', bank = 'safe', + mogsafe2 = 'safe2', safe2 = 'safe2', ms2 = 'safe2', bank2 = 'safe2', + storage = 'storage', st = 'storage', + moglocker = 'locker', locker = 'locker', ml = 'locker', + mogsatchel = 'satchel', satchel = 'satchel', sa = 'satchel', + mogsack = 'sack', sack = 'sack', sk = 'sack', + mogcase = 'case', case = 'case', c = 'case', + wardrobe = 'wardrobe', w = 'wardrobe', + wardrobe2 = 'wardrobe2', w2 = 'wardrobe2', + wardrobe3 = 'wardrobe3', w3 = 'wardrobe3', + wardrobe4 = 'wardrobe4', w4 = 'wardrobe4', + wardrobe5 = 'wardrobe5', w5 = 'wardrobe5', + wardrobe6 = 'wardrobe6', w6 = 'wardrobe6', + wardrobe7 = 'wardrobe7', w7 = 'wardrobe7', + wardrobe8 = 'wardrobe8', w8 = 'wardrobe8', +} + -- Validate either gear sets or inventory. -- gs validate [inv|set] [filterlist] -- Where inv == i or inv or inventory @@ -36,60 +56,13 @@ function validate(options) local validateType = 'sets' if options and #options > 0 then - if S{'sets','set','s'}:contains(options[1]:lower()) then - validateType = 'sets' - table.remove(options,1) - elseif S{'inventory','inv','i'}:contains(options[1]:lower()) then - validateType = 'inventory' - table.remove(options,1) - elseif S{'mogsafe','safe','ms','bank'}:contains(options[1]:lower()) then - validateType = 'safe' - table.remove(options,1) - elseif S{'mogsafe2','safe2','ms2','bank2'}:contains(options[1]:lower()) then - validateType = 'safe2' - table.remove(options,1) - elseif S{'storage','st'}:contains(options[1]:lower()) then - validateType = 'storage' - table.remove(options,1) - elseif S{'moglocker','locker','ml'}:contains(options[1]:lower()) then - validateType = 'locker' - table.remove(options,1) - elseif S{'mogsatchel','satchel','sa'}:contains(options[1]:lower()) then - validateType = 'satchel' - table.remove(options,1) - elseif S{'mogsack','sack','sk'}:contains(options[1]:lower()) then - validateType = 'sack' - table.remove(options,1) - elseif S{'mogcase','case','c'}:contains(options[1]:lower()) then - validateType = 'case' - table.remove(options,1) - elseif S{'wardrobe','w'}:contains(options[1]:lower()) then - validateType = 'wardrobe' - table.remove(options,1) - elseif S{'wardrobe2','w2'}:contains(options[1]:lower()) then - validateType = 'wardrobe2' - table.remove(options,1) - elseif S{'wardrobe3','w3'}:contains(options[1]:lower()) then - validateType = 'wardrobe3' - table.remove(options,1) - elseif S{'wardrobe4','w4'}:contains(options[1]:lower()) then - validateType = 'wardrobe4' - table.remove(options,1) - elseif S{'wardrobe5','w5'}:contains(options[1]:lower()) then - validateType = 'wardrobe5' - table.remove(options,1) - elseif S{'wardrobe6','w6'}:contains(options[1]:lower()) then - validateType = 'wardrobe6' - table.remove(options,1) - elseif S{'wardrobe7','w7'}:contains(options[1]:lower()) then - validateType = 'wardrobe7' - table.remove(options,1) - elseif S{'wardrobe8','w8'}:contains(options[1]:lower()) then - validateType = 'wardrobe8' - table.remove(options,1) + local match = validate_keys[options[1]:lower()] + if match then + validateType = match + table.remove(options, 1) end end - + if validateType == 'sets' then validate_sets(options) else @@ -104,11 +77,11 @@ end -- Function for determining and displaying which items from a player's selected repository are not in their gear sets. function validate_inventory(filter, repository) msg.addon_msg(123,'Checking for items in '..repository..' that are not used in your gear sets.') - - --msg.addon_msg(123,items.repository) - + + --msg.addon_msg(123,items.repository) + local extra_items = search_sets_for_items_in_bag(items[repository], filter) - + local display_list = get_item_names(extra_items):sort(insensitive_sort) display_list:map(function(item) msg.add_to_chat(120, windower.to_shift_jis((string.gsub(item, "^%l", string.upper))) ) end) msg.addon_msg(123,'Final count = '..tostring(display_list:length())) @@ -117,7 +90,7 @@ end -- Function for determining and displaying which items of a player's gear sets are not in their inventory. function validate_sets(filter) msg.addon_msg(123,'Checking for items in gear sets that are not in your inventory.') - + local missing_items = search_bags_for_items_in_set(sets, filter) local display_list = get_item_names(missing_items):sort(insensitive_sort) @@ -162,7 +135,7 @@ end function get_formal_name_by_item_id(id) local shortname = get_short_name_by_item_id(id) local logname = get_log_name_by_item_id(id) - + return (#logname > #shortname) and logname or shortname end @@ -193,12 +166,12 @@ function get_augment_string(item) if started then aug_str = aug_str .. ',' end - + aug_str = aug_str.."'"..augment.."'" started = true end end - + return aug_str end end @@ -217,7 +190,7 @@ function search_sets_for_items_in_bag(bag, filter) end end end - + return extra_bag_items end @@ -226,11 +199,11 @@ function search_bags_for_items_in_set(gear_table, filter, missing_items, stack) if stack and stack:contains(gear_table) then return end if type(gear_table) ~= 'table' then return end if missing_items == nil then missing_items = S{} end - + for i,v in pairs(gear_table) do local name = (type(v) == 'table' and v.name) or v local aug = (type (v) == 'table' and (v.augments or v.augment)) - + if type(aug) == 'string' then aug = {aug} end if type(name) == 'string' and name ~= 'empty' and name ~= '' and type(i) == 'string' then if not slot_map[i] then @@ -246,7 +219,7 @@ function search_bags_for_items_in_set(gear_table, filter, missing_items, stack) stack:remove(gear_table) end end - + return missing_items end @@ -279,12 +252,12 @@ function find_in_sets(item, tab, stack) end end end - + return false end -- Utility function to help search inventory -function find_in_inv(bag, name, aug) +function find_in_inv(bag, name, aug) for _,item in ipairs(bag) do if compare_item(item, name, aug) then return true @@ -298,7 +271,7 @@ function compare_item(item, name, aug, item_short_name, item_log_name) if item.id == 0 or not res.items[item.id] then return false end - + name = lowercase_name(name) item_short_name = lowercase_name(item_short_name or get_short_name_by_item_id(item.id)) item_log_name = lowercase_name(item_log_name or get_log_name_by_item_id(item.id)) @@ -308,7 +281,7 @@ function compare_item(item, name, aug, item_short_name, item_log_name) return true end end - + return false end @@ -321,7 +294,7 @@ function tryfilter(itemname, filter) if not filter or #filter == 0 then return true end - + local pass = true for _,v in pairs(filter) do if v[1] == '-' then From a0246d3796d26f0c5307ffc5a87ca4162e1da74e Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Wed, 16 Feb 2022 16:01:48 -0700 Subject: [PATCH 0800/1002] Gearswap Validate syntax fix --- addons/GearSwap/validate.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/GearSwap/validate.lua b/addons/GearSwap/validate.lua index 1757a92328..0a0bcbaa0a 100644 --- a/addons/GearSwap/validate.lua +++ b/addons/GearSwap/validate.lua @@ -30,7 +30,7 @@ local validate_keys = { sets = 'sets', set = 'sets', s = 'sets', - inventory = 'inventory', inv = 'inventory', i = 'inventory' + inventory = 'inventory', inv = 'inventory', i = 'inventory', mogsafe = 'safe', safe = 'safe', ms = 'safe', bank = 'safe', mogsafe2 = 'safe2', safe2 = 'safe2', ms2 = 'safe2', bank2 = 'safe2', storage = 'storage', st = 'storage', From 2c943c530209ab8dae94682c35718f8bab24653e Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Fri, 18 Feb 2022 11:46:47 -0700 Subject: [PATCH 0801/1002] equipviewer validate bags fix --- addons/GearSwap/validate.lua | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/addons/GearSwap/validate.lua b/addons/GearSwap/validate.lua index 0a0bcbaa0a..11763fc7ec 100644 --- a/addons/GearSwap/validate.lua +++ b/addons/GearSwap/validate.lua @@ -208,8 +208,8 @@ function search_bags_for_items_in_set(gear_table, filter, missing_items, stack) if type(name) == 'string' and name ~= 'empty' and name ~= '' and type(i) == 'string' then if not slot_map[i] then msg.addon_msg(123,windower.to_shift_jis(tostring(i))..' contains a "name" element but is not a valid slot.') - elseif tryfilter(lowercase_name(name), filter) and not find_in_inv(items.inventory, name, aug) and not find_in_inv(items.wardrobe, name, aug) and not find_in_inv(items.wardrobe2, name, aug) then - missing_items:add(lowercase_name(name)) + elseif tryfilter(lowercase_name(name), filter) and not find_in_equippable_inventories(name, aug) then + missing_items:add({name=lowercase_name(name),aug=aug}) end elseif type(name) == 'table' and name ~= empty then if not stack then stack = S{} end @@ -223,6 +223,15 @@ function search_bags_for_items_in_set(gear_table, filter, missing_items, stack) return missing_items end +-- Utility function to search equippable inventories +function find_in_equippable_inventories(name,aug) + for _,bag in pairs(equippable_item_bags) do + if find_in_inv(items[to_windower_bag_api(bag.en)], name, aug) then + return true + end + end +end + -- Utility function to help search sets function find_in_sets(item, tab, stack) if stack and stack:contains(tab) then From 47852d5aeb4671b5c8cdd47f7397758cf8f34111 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Fri, 18 Feb 2022 11:53:43 -0700 Subject: [PATCH 0802/1002] Wardrobe Fix --- addons/GearSwap/statics.lua | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/addons/GearSwap/statics.lua b/addons/GearSwap/statics.lua index 42fee38a4d..80d99399f5 100644 --- a/addons/GearSwap/statics.lua +++ b/addons/GearSwap/statics.lua @@ -34,28 +34,9 @@ action_type_map = {['/ja']='Ability',['/jobability']='Ability',['/so']='Magic',[ ['/ra']='Ranged Attack',['/range']='Ranged Attack',['/throw']='Ranged Attack',['/shoot']='Ranged Attack',['/ms']='Ability',['/monsterskill']='Ability', ['/ws']='Ability',['/weaponskill']='Ability',['/item']='Item',['/pet']='Ability',['/bstpet']='Ability',['Monster']='Monster Move'} -usable_item_bags = { - res.bags[3], -- Temporary Items - res.bags[0], -- Inventory - res.bags[8], -- Wardrobe 1 - res.bags[10], -- Wardrobe 2 - res.bags[11], -- Wardrobe 3 - res.bags[12], -- Wardrobe 4 - res.bags[13], -- Wardrobe 5 - res.bags[14], -- Wardrobe 6 - res.bags[15], -- Wardrobe 7 - res.bags[16]} -- Wardrobe 8 - -equippable_item_bags = { - res.bags[0], -- Inventory - res.bags[8], -- Wardrobe 1 - res.bags[10], -- Wardrobe 2 - res.bags[11], -- Wardrobe 3 - res.bags[12], -- Wardrobe 4 - res.bags[13], -- Wardrobe 5 - res.bags[14], -- Wardrobe 6 - res.bags[15], -- Wardrobe 7 - res.bags[16]} -- Wardrobe 8 +equippable_item_bags = res.bags:equippable(true) + +usable_item_bags = equippable_item_bags:amend(res.bags:command('temporary')) bag_string_lookup = {} for i,v in pairs(res.bags) do From db10bd436316c568a877f9f15f1eaf0984682c6b Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Fri, 18 Feb 2022 16:48:45 -0700 Subject: [PATCH 0803/1002] Gearswap Wardrobe inventories fix fix --- addons/GearSwap/statics.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/GearSwap/statics.lua b/addons/GearSwap/statics.lua index 80d99399f5..49863a1d49 100644 --- a/addons/GearSwap/statics.lua +++ b/addons/GearSwap/statics.lua @@ -34,9 +34,9 @@ action_type_map = {['/ja']='Ability',['/jobability']='Ability',['/so']='Magic',[ ['/ra']='Ranged Attack',['/range']='Ranged Attack',['/throw']='Ranged Attack',['/shoot']='Ranged Attack',['/ms']='Ability',['/monsterskill']='Ability', ['/ws']='Ability',['/weaponskill']='Ability',['/item']='Item',['/pet']='Ability',['/bstpet']='Ability',['Monster']='Monster Move'} -equippable_item_bags = res.bags:equippable(true) +equippable_item_bags = {res.bags:equippable(true):extract()} -usable_item_bags = equippable_item_bags:amend(res.bags:command('temporary')) +usable_item_bags = {res.bags:with('command','temporary'), table.extract(equippable_item_bags)} bag_string_lookup = {} for i,v in pairs(res.bags) do From 869a24db52d33f1ab73047ae59ed3d630933681e Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Sat, 19 Feb 2022 08:29:35 -0700 Subject: [PATCH 0804/1002] Gearswap Motes increase macro books --- addons/GearSwap/libs/Mote-Utility.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/GearSwap/libs/Mote-Utility.lua b/addons/GearSwap/libs/Mote-Utility.lua index ad7a0ffebe..0f734f37ef 100644 --- a/addons/GearSwap/libs/Mote-Utility.lua +++ b/addons/GearSwap/libs/Mote-Utility.lua @@ -523,7 +523,7 @@ function set_macro_page(set,book) add_to_chat(123,'Error setting macro page: book is not a valid number ('..tostring(book)..').') return end - if book < 1 or book > 20 then + if book < 1 or book > 40 then add_to_chat(123,'Error setting macro page: Macro book ('..tostring(book)..') must be between 1 and 20.') return end From 8e6c09f8fc310ac8aa9f8f56605fb92c0b3937a2 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Thu, 10 Mar 2022 01:27:27 -0500 Subject: [PATCH 0805/1002] March 9th, 2022 Update --- addons/boxdestroyer/messages.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/boxdestroyer/messages.lua b/addons/boxdestroyer/messages.lua index 268ef49e3f..f9667ce353 100644 --- a/addons/boxdestroyer/messages.lua +++ b/addons/boxdestroyer/messages.lua @@ -24,7 +24,7 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination [122] = 7441, [123] = 7886, [124] = 7837, - [125] = 7647, + [125] = 7654, [126] = 8070, [127] = 7358, [128] = 7513, From 19ac22618848781b20bb702414c1e92242d42ec5 Mon Sep 17 00:00:00 2001 From: Byrth Date: Thu, 10 Mar 2022 05:59:13 -0500 Subject: [PATCH 0806/1002] update digger messages for 2022-03 --- addons/digger/messages.lua | 120 ++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/addons/digger/messages.lua b/addons/digger/messages.lua index 8da59e02dc..dd53a7f91c 100644 --- a/addons/digger/messages.lua +++ b/addons/digger/messages.lua @@ -1,61 +1,61 @@ messages = {} -messages[2] = {bayld=7368, ease=7360, fail=7285, full=7283, notes=7367, points=7365, standing=7366, success=6388} -messages[4] = {bayld=7362, ease=7354, fail=7279, full=7277, notes=7361, points=7359, standing=7360, success=6388} -messages[5] = {bayld=7319, ease=7311, fail=7236, full=7234, notes=7318, points=7316, standing=7317, success=6401} -messages[7] = {bayld=7313, ease=7305, fail=7230, full=7228, notes=7312, points=7310, standing=7311, success=6388} -messages[24] = {bayld=7649, ease=7641, fail=7566, full=7564, notes=7648, points=7646, standing=7647, success=6388} -messages[25] = {bayld=7169, ease=7161, fail=7086, full=7084, notes=7168, points=7166, standing=7167, success=6388} -messages[51] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} -messages[52] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} -messages[61] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} -messages[79] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} -messages[81] = {bayld=7828, ease=7820, fail=7745, full=7743, notes=7827, points=7825, standing=7826, success=6388} -messages[82] = {bayld=7460, ease=7452, fail=7377, full=7375, notes=7459, points=7457, standing=7458, success=6388} -messages[83] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} -messages[84] = {bayld=7167, ease=7159, fail=7084, full=7082, notes=7166, points=7164, standing=7165, success=6388} -messages[88] = {bayld=7453, ease=7445, fail=7370, full=7368, notes=7452, points=7450, standing=7451, success=6388} -messages[89] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} -messages[90] = {bayld=7244, ease=7236, fail=7161, full=7159, notes=7243, points=7241, standing=7242, success=6388} -messages[91] = {bayld=7167, ease=7159, fail=7084, full=7082, notes=7166, points=7164, standing=7165, success=6388} -messages[95] = {bayld=7174, ease=7166, fail=7091, full=7089, notes=7173, points=7171, standing=7172, success=6388} -messages[96] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} -messages[97] = {bayld=7705, ease=7697, fail=7622, full=7620, notes=7704, points=7702, standing=7703, success=6388} -messages[98] = {bayld=7705, ease=7697, fail=7622, full=7620, notes=7704, points=7702, standing=7703, success=6388} -messages[100] = {bayld=7328, ease=7320, fail=7245, full=7243, notes=7327, points=7325, standing=7326, success=6410} -messages[101] = {bayld=7328, ease=7320, fail=7245, full=7243, notes=7327, points=7325, standing=7326, success=6410} -messages[102] = {bayld=7310, ease=7302, fail=7227, full=7225, notes=7309, points=7307, standing=7308, success=6388} -messages[103] = {bayld=7328, ease=7320, fail=7245, full=7243, notes=7327, points=7325, standing=7326, success=6410} -messages[104] = {bayld=7802, ease=7794, fail=7719, full=7717, notes=7801, points=7799, standing=7800, success=6410} -messages[105] = {bayld=7328, ease=7320, fail=7245, full=7243, notes=7327, points=7325, standing=7326, success=6410} -messages[106] = {bayld=7328, ease=7320, fail=7245, full=7243, notes=7327, points=7325, standing=7326, success=6569} -messages[107] = {bayld=7328, ease=7320, fail=7245, full=7243, notes=7327, points=7325, standing=7326, success=6410} -messages[108] = {bayld=7310, ease=7302, fail=7227, full=7225, notes=7309, points=7307, standing=7308, success=6388} -messages[109] = {bayld=7328, ease=7320, fail=7245, full=7243, notes=7327, points=7325, standing=7326, success=6410} -messages[110] = {bayld=7328, ease=7320, fail=7245, full=7243, notes=7327, points=7325, standing=7326, success=6410} -messages[111] = {bayld=7328, ease=7320, fail=7245, full=7243, notes=7327, points=7325, standing=7326, success=6569} -messages[112] = {bayld=7345, ease=7337, fail=7262, full=7260, notes=7344, points=7342, standing=7343, success=6401} -messages[113] = {bayld=7648, ease=7640, fail=7565, full=7563, notes=7647, points=7645, standing=7646, success=6388} -messages[114] = {bayld=7648, ease=7640, fail=7565, full=7563, notes=7647, points=7645, standing=7646, success=6388} -messages[115] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} -messages[116] = {bayld=7306, ease=7298, fail=7223, full=7221, notes=7305, points=7303, standing=7304, success=6388} -messages[117] = {bayld=7328, ease=7320, fail=7245, full=7243, notes=7327, points=7325, standing=7326, success=6569} -messages[118] = {bayld=7347, ease=7339, fail=7264, full=7262, notes=7346, points=7344, standing=7345, success=6423} -messages[119] = {bayld=7328, ease=7320, fail=7245, full=7243, notes=7327, points=7325, standing=7326, success=6410} -messages[120] = {bayld=7336, ease=7328, fail=7253, full=7251, notes=7335, points=7333, standing=7334, success=6410} -messages[121] = {bayld=7648, ease=7640, fail=7565, full=7563, notes=7647, points=7645, standing=7646, success=6388} -messages[122] = {bayld=7306, ease=7298, fail=7223, full=7221, notes=7305, points=7303, standing=7304, success=6388} -messages[123] = {bayld=7648, ease=7640, fail=7565, full=7563, notes=7647, points=7645, standing=7646, success=6388} -messages[124] = {bayld=7648, ease=7640, fail=7565, full=7563, notes=7647, points=7645, standing=7646, success=6388} -messages[125] = {bayld=7306, ease=7298, fail=7223, full=7221, notes=7305, points=7303, standing=7304, success=6388} -messages[126] = {bayld=7306, ease=7298, fail=7223, full=7221, notes=7305, points=7303, standing=7304, success=6388} -messages[127] = {bayld=7306, ease=7298, fail=7223, full=7221, notes=7305, points=7303, standing=7304, success=6388} -messages[128] = {bayld=7306, ease=7298, fail=7223, full=7221, notes=7305, points=7303, standing=7304, success=6388} -messages[136] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} -messages[137] = {bayld=7669, ease=7661, fail=7586, full=7584, notes=7668, points=7666, standing=7667, success=6388} -messages[260] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} -messages[261] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} -messages[262] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} -messages[263] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} -messages[265] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} -messages[266] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} -messages[267] = {bayld=7147, ease=7139, fail=7064, full=7062, notes=7146, points=7144, standing=7145, success=6388} +messages[2] = {bayld=7375, ease=7367, fail=7292, full=7290, notes=7374, points=7372, standing=7373, success=6389} +messages[4] = {bayld=7369, ease=7361, fail=7286, full=7284, notes=7368, points=7366, standing=7367, success=6389} +messages[5] = {bayld=7326, ease=7318, fail=7243, full=7241, notes=7325, points=7323, standing=7324, success=6402} +messages[7] = {bayld=7320, ease=7312, fail=7237, full=7235, notes=7319, points=7317, standing=7318, success=6389} +messages[24] = {bayld=7656, ease=7648, fail=7573, full=7571, notes=7655, points=7653, standing=7654, success=6389} +messages[25] = {bayld=7176, ease=7168, fail=7093, full=7091, notes=7175, points=7173, standing=7174, success=6389} +messages[51] = {bayld=7151, ease=7143, fail=7068, full=7066, notes=7150, points=7148, standing=7149, success=6389} +messages[52] = {bayld=7151, ease=7143, fail=7068, full=7066, notes=7150, points=7148, standing=7149, success=6389} +messages[61] = {bayld=7151, ease=7143, fail=7068, full=7066, notes=7150, points=7148, standing=7149, success=6389} +messages[79] = {bayld=7151, ease=7143, fail=7068, full=7066, notes=7150, points=7148, standing=7149, success=6389} +messages[81] = {bayld=7835, ease=7827, fail=7752, full=7750, notes=7834, points=7832, standing=7833, success=6389} +messages[82] = {bayld=7467, ease=7459, fail=7384, full=7382, notes=7466, points=7464, standing=7465, success=6389} +messages[83] = {bayld=7154, ease=7146, fail=7071, full=7069, notes=7153, points=7151, standing=7152, success=6389} +messages[84] = {bayld=7174, ease=7166, fail=7091, full=7089, notes=7173, points=7171, standing=7172, success=6389} +messages[88] = {bayld=7460, ease=7452, fail=7377, full=7375, notes=7459, points=7457, standing=7458, success=6389} +messages[89] = {bayld=7154, ease=7146, fail=7071, full=7069, notes=7153, points=7151, standing=7152, success=6389} +messages[90] = {bayld=7251, ease=7243, fail=7168, full=7166, notes=7250, points=7248, standing=7249, success=6389} +messages[91] = {bayld=7174, ease=7166, fail=7091, full=7089, notes=7173, points=7171, standing=7172, success=6389} +messages[95] = {bayld=7181, ease=7173, fail=7098, full=7096, notes=7180, points=7178, standing=7179, success=6389} +messages[96] = {bayld=7154, ease=7146, fail=7071, full=7069, notes=7153, points=7151, standing=7152, success=6389} +messages[97] = {bayld=7712, ease=7704, fail=7629, full=7627, notes=7711, points=7709, standing=7710, success=6389} +messages[98] = {bayld=7712, ease=7704, fail=7629, full=7627, notes=7711, points=7709, standing=7710, success=6389} +messages[100] = {bayld=7335, ease=7327, fail=7252, full=7250, notes=7334, points=7332, standing=7333, success=6411} +messages[101] = {bayld=7335, ease=7327, fail=7252, full=7250, notes=7334, points=7332, standing=7333, success=6411} +messages[102] = {bayld=7317, ease=7309, fail=7234, full=7232, notes=7316, points=7314, standing=7315, success=6389} +messages[103] = {bayld=7335, ease=7327, fail=7252, full=7250, notes=7334, points=7332, standing=7333, success=6411} +messages[104] = {bayld=7809, ease=7801, fail=7726, full=7724, notes=7808, points=7806, standing=7807, success=6411} +messages[105] = {bayld=7335, ease=7327, fail=7252, full=7250, notes=7334, points=7332, standing=7333, success=6411} +messages[106] = {bayld=7335, ease=7327, fail=7252, full=7250, notes=7334, points=7332, standing=7333, success=6570} +messages[107] = {bayld=7335, ease=7327, fail=7252, full=7250, notes=7334, points=7332, standing=7333, success=6411} +messages[108] = {bayld=7317, ease=7309, fail=7234, full=7232, notes=7316, points=7314, standing=7315, success=6389} +messages[109] = {bayld=7335, ease=7327, fail=7252, full=7250, notes=7334, points=7332, standing=7333, success=6411} +messages[110] = {bayld=7335, ease=7327, fail=7252, full=7250, notes=7334, points=7332, standing=7333, success=6411} +messages[111] = {bayld=7335, ease=7327, fail=7252, full=7250, notes=7334, points=7332, standing=7333, success=6570} +messages[112] = {bayld=7352, ease=7344, fail=7269, full=7267, notes=7351, points=7349, standing=7350, success=6402} +messages[113] = {bayld=7655, ease=7647, fail=7572, full=7570, notes=7654, points=7652, standing=7653, success=6389} +messages[114] = {bayld=7655, ease=7647, fail=7572, full=7570, notes=7654, points=7652, standing=7653, success=6389} +messages[115] = {bayld=7154, ease=7146, fail=7071, full=7069, notes=7153, points=7151, standing=7152, success=6389} +messages[116] = {bayld=7313, ease=7305, fail=7230, full=7228, notes=7312, points=7310, standing=7311, success=6389} +messages[117] = {bayld=7335, ease=7327, fail=7252, full=7250, notes=7334, points=7332, standing=7333, success=6570} +messages[118] = {bayld=7354, ease=7346, fail=7271, full=7269, notes=7353, points=7351, standing=7352, success=6424} +messages[119] = {bayld=7335, ease=7327, fail=7252, full=7250, notes=7334, points=7332, standing=7333, success=6411} +messages[120] = {bayld=7343, ease=7335, fail=7260, full=7258, notes=7342, points=7340, standing=7341, success=6411} +messages[121] = {bayld=7655, ease=7647, fail=7572, full=7570, notes=7654, points=7652, standing=7653, success=6389} +messages[122] = {bayld=7313, ease=7305, fail=7230, full=7228, notes=7312, points=7310, standing=7311, success=6389} +messages[123] = {bayld=7655, ease=7647, fail=7572, full=7570, notes=7654, points=7652, standing=7653, success=6389} +messages[124] = {bayld=7655, ease=7647, fail=7572, full=7570, notes=7654, points=7652, standing=7653, success=6389} +messages[125] = {bayld=7313, ease=7305, fail=7230, full=7228, notes=7312, points=7310, standing=7311, success=6389} +messages[126] = {bayld=7313, ease=7305, fail=7230, full=7228, notes=7312, points=7310, standing=7311, success=6389} +messages[127] = {bayld=7313, ease=7305, fail=7230, full=7228, notes=7312, points=7310, standing=7311, success=6389} +messages[128] = {bayld=7313, ease=7305, fail=7230, full=7228, notes=7312, points=7310, standing=7311, success=6389} +messages[136] = {bayld=7154, ease=7146, fail=7071, full=7069, notes=7153, points=7151, standing=7152, success=6389} +messages[137] = {bayld=7676, ease=7668, fail=7593, full=7591, notes=7675, points=7673, standing=7674, success=6389} +messages[260] = {bayld=7154, ease=7146, fail=7071, full=7069, notes=7153, points=7151, standing=7152, success=6389} +messages[261] = {bayld=7154, ease=7146, fail=7071, full=7069, notes=7153, points=7151, standing=7152, success=6389} +messages[262] = {bayld=7154, ease=7146, fail=7071, full=7069, notes=7153, points=7151, standing=7152, success=6389} +messages[263] = {bayld=7154, ease=7146, fail=7071, full=7069, notes=7153, points=7151, standing=7152, success=6389} +messages[265] = {bayld=7154, ease=7146, fail=7071, full=7069, notes=7153, points=7151, standing=7152, success=6389} +messages[266] = {bayld=7154, ease=7146, fail=7071, full=7069, notes=7153, points=7151, standing=7152, success=6389} +messages[267] = {bayld=7154, ease=7146, fail=7071, full=7069, notes=7153, points=7151, standing=7152, success=6389} From ff3fcef6338f8ea3e8c3db49f10ab0f4f47919d7 Mon Sep 17 00:00:00 2001 From: charitwo Date: Fri, 11 Mar 2022 00:34:17 -0600 Subject: [PATCH 0807/1002] Update checkparam.lua Add in "magic eva" to cover items like Nyame Sollerets which wasn't capturing magic evasion --- addons/checkparam/checkparam.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/checkparam/checkparam.lua b/addons/checkparam/checkparam.lua index 7f31a57d0c..b3b6bc9821 100644 --- a/addons/checkparam/checkparam.lua +++ b/addons/checkparam/checkparam.lua @@ -224,6 +224,7 @@ integrate = { ['indicolure spell duration'] = 'indicolure effect duration', ['indi eff dur'] = 'indicolure effect duration', ['mag eva'] = 'magic evasion', + ['magic eva'] = 'magic evasion', ['magic atk bonus'] = 'magic attack bonus', ['magatkbns'] = 'magic attack bonus', ['mag atk bonus'] = 'magic attack bonus', From 9a85235787e99cd4dccbe2a4ef1f09b4cfdbaea8 Mon Sep 17 00:00:00 2001 From: Posimagi Date: Sat, 12 Mar 2022 17:37:07 -0800 Subject: [PATCH 0808/1002] [pointwatch] support Master Levels (specifically) --- addons/pointwatch/ReadMe.txt | 9 +++++---- addons/pointwatch/pointwatch.lua | 1 + addons/pointwatch/statics.lua | 1 + 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/addons/pointwatch/ReadMe.txt b/addons/pointwatch/ReadMe.txt index a0d78fa284..79a9c4e983 100644 --- a/addons/pointwatch/ReadMe.txt +++ b/addons/pointwatch/ReadMe.txt @@ -45,12 +45,13 @@ Here are the available values: * ep.current = Current Exemplar Points * ep.rate = Current Exemplar Points gain rate per hour. This is calculated over a 10 minute window and requires at least two gains within the window. * ep.tnml = Required Exemplar Points for your next Master Level +* ep.master_level = Master Level of your current job. -- Will be incorrect during Level Sync. -* sparks.current = Current number of RoE Sparks (number between 0 and 50,000) -* sparks.maximum = Maximum number of RoE Sparks (always 50,000) +* sparks.current = Current number of RoE Sparks (number between 0 and 99,999) +* sparks.maximum = Maximum number of RoE Sparks (always 99,999) -* accolades.current = Current number of Unity Accolades (number between 0 and 50,000) -* accolades.maximum = Maximum number of Unity Accolades (always 50,000) +* accolades.current = Current number of Unity Accolades (number between 0 and 99,999) +* accolades.maximum = Maximum number of Unity Accolades (always 99,999) * dynamis.KIs = Series of Xs and Os indicating whether or not you have the 5 KIs. * dynamis.entry_time = Your Dynamis entry time, in seconds. -- If the addon is loaded in dynamis, this will be the time of addon load. diff --git a/addons/pointwatch/pointwatch.lua b/addons/pointwatch/pointwatch.lua index 23fc89587c..ea47c0473d 100644 --- a/addons/pointwatch/pointwatch.lua +++ b/addons/pointwatch/pointwatch.lua @@ -117,6 +117,7 @@ packet_handlers = { accolades.current = p['Unity Points'] ep.current = p['Current Exemplar Points'] ep.tnml = p['Required Exemplar Points'] + ep.master_level = p['Master Level'] end, [0x063] = function(org) local p = packets.parse('incoming',org) diff --git a/addons/pointwatch/statics.lua b/addons/pointwatch/statics.lua index eee27f3f5a..5ad12e4559 100644 --- a/addons/pointwatch/statics.lua +++ b/addons/pointwatch/statics.lua @@ -116,6 +116,7 @@ function initialize() current = 0, rate = 0, tnml = 0, + master_level = 0, } sparks = { From 6df1e3ad08b800ddf018cf027161cb0873f11eff Mon Sep 17 00:00:00 2001 From: Posimagi Date: Sat, 12 Mar 2022 18:30:18 -0800 Subject: [PATCH 0809/1002] [pointwatch] add support for character level --- addons/pointwatch/ReadMe.txt | 1 + addons/pointwatch/pointwatch.lua | 1 + addons/pointwatch/statics.lua | 1 + 3 files changed, 3 insertions(+) diff --git a/addons/pointwatch/ReadMe.txt b/addons/pointwatch/ReadMe.txt index a0d78fa284..6b17fb3678 100644 --- a/addons/pointwatch/ReadMe.txt +++ b/addons/pointwatch/ReadMe.txt @@ -30,6 +30,7 @@ Here are the available values: * xp.tnl = Number of Experience Points in your current level (number from 500 to 56,000) * xp.rate = Current XP gain rate per hour. This is calculated over a 10 minute window and requires at least two gains within the window. * xp.total = Total Experience Points gained since the last time the addon was loaded (number) +* xp.job_level = Level of your current job. * lp.current = Current Experience Points (number from 0 to 55,999 XP) * lp.tnm = Similar to a "To Next Level", but this value is always 10,000 because that's always the number of Limit Points per merit point. diff --git a/addons/pointwatch/pointwatch.lua b/addons/pointwatch/pointwatch.lua index 23fc89587c..3861a7da7b 100644 --- a/addons/pointwatch/pointwatch.lua +++ b/addons/pointwatch/pointwatch.lua @@ -114,6 +114,7 @@ packet_handlers = { local p = packets.parse('incoming',org) xp.current = p['Current EXP'] xp.tnl = p['Required EXP'] + xp.job_level = p['Main Job Level'] accolades.current = p['Unity Points'] ep.current = p['Current Exemplar Points'] ep.tnml = p['Required Exemplar Points'] diff --git a/addons/pointwatch/statics.lua b/addons/pointwatch/statics.lua index eee27f3f5a..975b6e6376 100644 --- a/addons/pointwatch/statics.lua +++ b/addons/pointwatch/statics.lua @@ -101,6 +101,7 @@ function initialize() rate = 0, current = 0, tnl = 0, + job_level = 0; } lp = { From 9d299c8af387fceb88482849c9889316a4f0ffa8 Mon Sep 17 00:00:00 2001 From: Posimagi Date: Sat, 12 Mar 2022 18:43:59 -0800 Subject: [PATCH 0810/1002] [pointwatch] support character levels --- addons/pointwatch/ReadMe.txt | 1 + addons/pointwatch/pointwatch.lua | 1 + addons/pointwatch/statics.lua | 1 + 3 files changed, 3 insertions(+) diff --git a/addons/pointwatch/ReadMe.txt b/addons/pointwatch/ReadMe.txt index 6b17fb3678..77f09c92d4 100644 --- a/addons/pointwatch/ReadMe.txt +++ b/addons/pointwatch/ReadMe.txt @@ -31,6 +31,7 @@ Here are the available values: * xp.rate = Current XP gain rate per hour. This is calculated over a 10 minute window and requires at least two gains within the window. * xp.total = Total Experience Points gained since the last time the addon was loaded (number) * xp.job_level = Level of your current job. +* xp.sub_job_level = Level of your current support job. * lp.current = Current Experience Points (number from 0 to 55,999 XP) * lp.tnm = Similar to a "To Next Level", but this value is always 10,000 because that's always the number of Limit Points per merit point. diff --git a/addons/pointwatch/pointwatch.lua b/addons/pointwatch/pointwatch.lua index 3861a7da7b..77aaaef352 100644 --- a/addons/pointwatch/pointwatch.lua +++ b/addons/pointwatch/pointwatch.lua @@ -115,6 +115,7 @@ packet_handlers = { xp.current = p['Current EXP'] xp.tnl = p['Required EXP'] xp.job_level = p['Main Job Level'] + xp.sub_job_level = p['Sub Job Level'] accolades.current = p['Unity Points'] ep.current = p['Current Exemplar Points'] ep.tnml = p['Required Exemplar Points'] diff --git a/addons/pointwatch/statics.lua b/addons/pointwatch/statics.lua index 975b6e6376..83085b9fca 100644 --- a/addons/pointwatch/statics.lua +++ b/addons/pointwatch/statics.lua @@ -102,6 +102,7 @@ function initialize() current = 0, tnl = 0, job_level = 0; + sub_job_level = 0; } lp = { From 258f601a2b7541dd41e0b90e4c5ed31fa6c8b030 Mon Sep 17 00:00:00 2001 From: Posimagi Date: Tue, 22 Mar 2022 00:26:51 -0700 Subject: [PATCH 0811/1002] update version number --- addons/pointwatch/pointwatch.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/pointwatch/pointwatch.lua b/addons/pointwatch/pointwatch.lua index 4b6c6669b1..7911e06789 100644 --- a/addons/pointwatch/pointwatch.lua +++ b/addons/pointwatch/pointwatch.lua @@ -36,7 +36,7 @@ require('chat') _addon.name = 'PointWatch' _addon.author = 'Byrth' -_addon.version = 0.211112 +_addon.version = 0.220312 _addon.command = 'pw' settings = config.load('data\\settings.xml',default_settings) From 54621f51e3facc30e9da80e6793153759688a7fb Mon Sep 17 00:00:00 2001 From: Posimagi Date: Tue, 22 Mar 2022 00:37:54 -0700 Subject: [PATCH 0812/1002] fix syntax --- addons/pointwatch/statics.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/pointwatch/statics.lua b/addons/pointwatch/statics.lua index 8bee33fe04..af146494d7 100644 --- a/addons/pointwatch/statics.lua +++ b/addons/pointwatch/statics.lua @@ -101,8 +101,8 @@ function initialize() rate = 0, current = 0, tnl = 0, - job_level = 0; - sub_job_level = 0; + job_level = 0, + sub_job_level = 0, } lp = { From 5fa3a6632e13d2641813c7e715215479f02cfa20 Mon Sep 17 00:00:00 2001 From: Posimagi Date: Mon, 28 Mar 2022 00:54:05 -0700 Subject: [PATCH 0813/1002] [pointwatch] support job names and abbreviations --- addons/pointwatch/ReadMe.txt | 4 ++++ addons/pointwatch/pointwatch.lua | 4 ++++ addons/pointwatch/statics.lua | 5 ++++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/addons/pointwatch/ReadMe.txt b/addons/pointwatch/ReadMe.txt index a764f37d12..4616a8c477 100644 --- a/addons/pointwatch/ReadMe.txt +++ b/addons/pointwatch/ReadMe.txt @@ -30,7 +30,11 @@ Here are the available values: * xp.tnl = Number of Experience Points in your current level (number from 500 to 56,000) * xp.rate = Current XP gain rate per hour. This is calculated over a 10 minute window and requires at least two gains within the window. * xp.total = Total Experience Points gained since the last time the addon was loaded (number) +* xp.job = Your current main job. +* xp.job_abbr = The three-letter abbreviation of your current main job. * xp.job_level = Level of your current job. +* xp.sub_job = Your current subjob. +* xp.sub_job_abbr = The three-letter abbreviation of your current subjob. * xp.sub_job_level = Level of your current support job. * lp.current = Current Experience Points (number from 0 to 55,999 XP) diff --git a/addons/pointwatch/pointwatch.lua b/addons/pointwatch/pointwatch.lua index 7911e06789..33ff912598 100644 --- a/addons/pointwatch/pointwatch.lua +++ b/addons/pointwatch/pointwatch.lua @@ -114,7 +114,11 @@ packet_handlers = { local p = packets.parse('incoming',org) xp.current = p['Current EXP'] xp.tnl = p['Required EXP'] + xp.job = res.jobs[p['Main Job']].en + xp.job_abbr = res.jobs[p['Main Job']].ens xp.job_level = p['Main Job Level'] + xp.sub_job = res.jobs[p['Sub Job']].en + xp.sub_job_abbr = res.jobs[p['Sub Job']].ens xp.sub_job_level = p['Sub Job Level'] accolades.current = p['Unity Points'] ep.current = p['Current Exemplar Points'] diff --git a/addons/pointwatch/statics.lua b/addons/pointwatch/statics.lua index af146494d7..99a199baab 100644 --- a/addons/pointwatch/statics.lua +++ b/addons/pointwatch/statics.lua @@ -81,7 +81,6 @@ other_table = {Crimson=10,Azure=10,Amber=10,Alabaster=10,Obsidian=20} dynamis_map = {[185]=city_table,[186]=city_table,[187]=city_table,[188]=city_table, [134]=other_table,[135]=other_table,[39]=other_table,[40]=other_table,[41]=other_table,[42]=other_table} - -- Not technically static, but sets the initial values for all features: function initialize() cp = { @@ -101,7 +100,11 @@ function initialize() rate = 0, current = 0, tnl = 0, + job = 0, + job_abbr = 0, job_level = 0, + sub_job = 0, + sub_job_abbr = 0, sub_job_level = 0, } From bd55b5e2a86432eccc6ee9d0eb637f5aa31a6624 Mon Sep 17 00:00:00 2001 From: Posimagi Date: Mon, 28 Mar 2022 01:37:08 -0700 Subject: [PATCH 0814/1002] dynamically select client language --- addons/pointwatch/pointwatch.lua | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/addons/pointwatch/pointwatch.lua b/addons/pointwatch/pointwatch.lua index 33ff912598..ae08bd7939 100644 --- a/addons/pointwatch/pointwatch.lua +++ b/addons/pointwatch/pointwatch.lua @@ -36,12 +36,15 @@ require('chat') _addon.name = 'PointWatch' _addon.author = 'Byrth' -_addon.version = 0.220312 +_addon.version = 0.220327 _addon.command = 'pw' settings = config.load('data\\settings.xml',default_settings) config.register(settings,initialize) +lang = windower.ffxi.get_info().language:sub(1, 2):lower() +langs = lang.."s" + box = texts.new('${current_string}',settings.text_box_settings,settings) box.current_string = '' box:show() @@ -114,11 +117,11 @@ packet_handlers = { local p = packets.parse('incoming',org) xp.current = p['Current EXP'] xp.tnl = p['Required EXP'] - xp.job = res.jobs[p['Main Job']].en - xp.job_abbr = res.jobs[p['Main Job']].ens + xp.job = res.jobs[p['Main Job']][lang] + xp.job_abbr = res.jobs[p['Main Job']][langs] xp.job_level = p['Main Job Level'] - xp.sub_job = res.jobs[p['Sub Job']].en - xp.sub_job_abbr = res.jobs[p['Sub Job']].ens + xp.sub_job = res.jobs[p['Sub Job']][lang] + xp.sub_job_abbr = res.jobs[p['Sub Job']][langs] xp.sub_job_level = p['Sub Job Level'] accolades.current = p['Unity Points'] ep.current = p['Current Exemplar Points'] From 7b6c3b41ed05b04b99152b215974dc02dacc5095 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Mon, 28 Mar 2022 15:26:39 +0200 Subject: [PATCH 0815/1002] Update pointwatch.lua --- addons/pointwatch/pointwatch.lua | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/addons/pointwatch/pointwatch.lua b/addons/pointwatch/pointwatch.lua index ae08bd7939..386869e397 100644 --- a/addons/pointwatch/pointwatch.lua +++ b/addons/pointwatch/pointwatch.lua @@ -1,4 +1,4 @@ ---Copyright (c) 2014, Byrthnoth +--Copyright © 2014, Byrthnoth --All rights reserved. --Redistribution and use in source and binary forms, with or without @@ -42,9 +42,6 @@ _addon.command = 'pw' settings = config.load('data\\settings.xml',default_settings) config.register(settings,initialize) -lang = windower.ffxi.get_info().language:sub(1, 2):lower() -langs = lang.."s" - box = texts.new('${current_string}',settings.text_box_settings,settings) box.current_string = '' box:show() @@ -117,11 +114,11 @@ packet_handlers = { local p = packets.parse('incoming',org) xp.current = p['Current EXP'] xp.tnl = p['Required EXP'] - xp.job = res.jobs[p['Main Job']][lang] - xp.job_abbr = res.jobs[p['Main Job']][langs] + xp.job = res.jobs[p['Main Job']].name + xp.job_abbr = res.jobs[p['Main Job']].name_short xp.job_level = p['Main Job Level'] - xp.sub_job = res.jobs[p['Sub Job']][lang] - xp.sub_job_abbr = res.jobs[p['Sub Job']][langs] + xp.sub_job = res.jobs[p['Sub Job']].name + xp.sub_job_abbr = res.jobs[p['Sub Job']].name_short xp.sub_job_level = p['Sub Job Level'] accolades.current = p['Unity Points'] ep.current = p['Current Exemplar Points'] From dbd9910746067523306f49d7fc4709d4b4f0e276 Mon Sep 17 00:00:00 2001 From: Diego Date: Wed, 30 Mar 2022 12:39:14 +0200 Subject: [PATCH 0816/1002] add yell and linkshell2 support --- addons/blist/blist.lua | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/addons/blist/blist.lua b/addons/blist/blist.lua index 509d6c1a51..ed62fb8c0c 100644 --- a/addons/blist/blist.lua +++ b/addons/blist/blist.lua @@ -47,6 +47,7 @@ defaults.say = true defaults.shout = true defaults.bazaar = true defaults.examine = true +defaults.yell = true defaults.mutedcolor = 57 settings = T{} @@ -83,7 +84,7 @@ function addon_command(...) windower.add_to_chat(160,' '..string.color('//bl help',204,160)..' : Lists this menu.') windower.add_to_chat(160,' '..string.color('//bl status',204,160)..' : Shows current configuration.') windower.add_to_chat(160,' '..string.color('//bl list',204,160)..' : Displays blacklist.') - windower.add_to_chat(160,' '..string.color('//bl useblist|linkshell|party|tell|emote|say|shout|bazaar|examine',204,160)..' : Toggles using '.._addon.name..' for said chat mode.') + windower.add_to_chat(160,' '..string.color('//bl useblist|linkshell|party|tell|emote|say|shout|yell|bazaar|examine',204,160)..' : Toggles using '.._addon.name..' for said chat mode.') windower.add_to_chat(160,' '..string.color('//bl mutedcolor #',204,160)..' : Sets color for muted communication. Valid values 1-255.') windower.add_to_chat(160,' '..string.color('//bl add|update name # hidetype reason',204,160)..' : Adds to or updates a user on your blist.') windower.add_to_chat(160,' '..string.color(' name',204,160)..' = name of person you want to blist') @@ -188,7 +189,7 @@ function addon_command(...) settings:save() -- current character only windower.add_to_chat(55,"Saving "..string.color(_addon.name,204,55).." settings.") end - elseif S({'useblist','linkshell','party','tell','emote','say','shout','bazaar','examine'}):contains(comm) then + elseif S({'useblist','linkshell','party','tell','emote','say','shout','yell','bazaar','examine'}):contains(comm) then settings[comm] = not settings[comm] showStatus(comm) if tostring(com2) ~= tostring(dummysettings[comm]) then @@ -225,6 +226,7 @@ function showStatus(var) windower.add_to_chat(160," UseBlistOnEmote: " .. string.color(onOffPrint(settings.emote),204,160)) windower.add_to_chat(160," UseBlistOnSay: " .. string.color(onOffPrint(settings.say),204,160)) windower.add_to_chat(160," UseBlistOnShout: " .. string.color(onOffPrint(settings.shout),204,160)) + windower.add_to_chat(160," UseBlistOnYell: " .. string.color(onOffPrint(settings.yell),204,160)) windower.add_to_chat(160," UseBlistOnBazaar: " .. string.color(onOffPrint(settings.bazaar),204,160)) windower.add_to_chat(160," UseBlistOnExamine: " .. string.color(onOffPrint(settings.examine),204,160)) windower.add_to_chat(160," Muted"..string.color("Color",settings.mutedcolor,160)..": " .. string.color(tostring(settings.mutedcolor),204,160)) @@ -254,7 +256,8 @@ end) windower.register_event('incoming text',function (original, modified, mode) if settings.useblist == true then name = "blist" - if mode == 14 and settings.linkshell == true then -- linkshell (others) + --print(tostring(mode)) + if (mode == 14 or mode == 214) and settings.linkshell == true then -- linkshell (others) a,z,name = string.find(original,'<(%a+)> ') elseif mode == 13 and settings.party == true then -- party (others) a,z,name = string.find(original,'%((%a+)%) ') @@ -266,6 +269,8 @@ windower.register_event('incoming text',function (original, modified, mode) a,z,name = string.find(original,'(%a+) ') elseif mode == 2 and settings.shout == true then -- shout a,z,name = string.find(original,'(%a+) ') + elseif mode == 11 and settings.yell == true then -- yell + a,z,name = string.find(original,'([%l%u]+).*%[') elseif mode == 121 and settings.bazaar == true then -- bazaar a,z,name,filler = string.find(original,'(%a+) (.*) bazaar%.') elseif mode == 208 and settings.examine == true then -- examine From d7a74e70c59af48311c354fdf28045390e6a2559 Mon Sep 17 00:00:00 2001 From: Diego Date: Wed, 30 Mar 2022 13:53:13 +0200 Subject: [PATCH 0817/1002] remove spurious comment --- addons/blist/blist.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/blist/blist.lua b/addons/blist/blist.lua index ed62fb8c0c..dd4f2106f0 100644 --- a/addons/blist/blist.lua +++ b/addons/blist/blist.lua @@ -256,7 +256,6 @@ end) windower.register_event('incoming text',function (original, modified, mode) if settings.useblist == true then name = "blist" - --print(tostring(mode)) if (mode == 14 or mode == 214) and settings.linkshell == true then -- linkshell (others) a,z,name = string.find(original,'<(%a+)> ') elseif mode == 13 and settings.party == true then -- party (others) From 8197ae7e377569c77b5be1984e519db1f220394f Mon Sep 17 00:00:00 2001 From: Diego Date: Wed, 30 Mar 2022 14:00:36 +0200 Subject: [PATCH 0818/1002] support for split linkshell and linkshell2 --- addons/blist/blist.lua | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/addons/blist/blist.lua b/addons/blist/blist.lua index dd4f2106f0..b67e3a99e1 100644 --- a/addons/blist/blist.lua +++ b/addons/blist/blist.lua @@ -40,6 +40,7 @@ require 'logger' local defaults = T{} defaults.useblist = true defaults.linkshell = true +defaults.linkshell2 = true defaults.party = true defaults.tell = true defaults.emote = true @@ -84,7 +85,7 @@ function addon_command(...) windower.add_to_chat(160,' '..string.color('//bl help',204,160)..' : Lists this menu.') windower.add_to_chat(160,' '..string.color('//bl status',204,160)..' : Shows current configuration.') windower.add_to_chat(160,' '..string.color('//bl list',204,160)..' : Displays blacklist.') - windower.add_to_chat(160,' '..string.color('//bl useblist|linkshell|party|tell|emote|say|shout|yell|bazaar|examine',204,160)..' : Toggles using '.._addon.name..' for said chat mode.') + windower.add_to_chat(160,' '..string.color('//bl useblist|linkshell|linkshell2|party|tell|emote|say|shout|yell|bazaar|examine',204,160)..' : Toggles using '.._addon.name..' for said chat mode.') windower.add_to_chat(160,' '..string.color('//bl mutedcolor #',204,160)..' : Sets color for muted communication. Valid values 1-255.') windower.add_to_chat(160,' '..string.color('//bl add|update name # hidetype reason',204,160)..' : Adds to or updates a user on your blist.') windower.add_to_chat(160,' '..string.color(' name',204,160)..' = name of person you want to blist') @@ -189,7 +190,7 @@ function addon_command(...) settings:save() -- current character only windower.add_to_chat(55,"Saving "..string.color(_addon.name,204,55).." settings.") end - elseif S({'useblist','linkshell','party','tell','emote','say','shout','yell','bazaar','examine'}):contains(comm) then + elseif S({'useblist','linkshell','linkshell2','party','tell','emote','say','shout','yell','bazaar','examine'}):contains(comm) then settings[comm] = not settings[comm] showStatus(comm) if tostring(com2) ~= tostring(dummysettings[comm]) then @@ -221,6 +222,7 @@ function showStatus(var) else windower.add_to_chat(160," UseBlist: " .. string.color(onOffPrint(settings.useblist),204,160)) windower.add_to_chat(160," UseBlistOnLinkshell: " .. string.color(onOffPrint(settings.linkshell),204,160)) + windower.add_to_chat(160," UseBlistOnLinkshell2: " .. string.color(onOffPrint(settings.linkshell2),204,160)) windower.add_to_chat(160," UseBlistOnParty: " .. string.color(onOffPrint(settings.party),204,160)) windower.add_to_chat(160," UseBlistOnTell: " .. string.color(onOffPrint(settings.tell),204,160)) windower.add_to_chat(160," UseBlistOnEmote: " .. string.color(onOffPrint(settings.emote),204,160)) @@ -256,7 +258,9 @@ end) windower.register_event('incoming text',function (original, modified, mode) if settings.useblist == true then name = "blist" - if (mode == 14 or mode == 214) and settings.linkshell == true then -- linkshell (others) + if mode == 14 and settings.linkshell == true then -- linkshell (others) + a,z,name = string.find(original,'<(%a+)> ') + elseif mode == 214 and settings.linkshell2 == true then -- linkshell2 (others) a,z,name = string.find(original,'<(%a+)> ') elseif mode == 13 and settings.party == true then -- party (others) a,z,name = string.find(original,'%((%a+)%) ') From 88cbd1375a2324c943615b557d33bbe4c6debf94 Mon Sep 17 00:00:00 2001 From: Diego Date: Fri, 1 Apr 2022 01:40:56 +0200 Subject: [PATCH 0819/1002] Fix weird interaction with gearswap --- addons/blist/blist.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/blist/blist.lua b/addons/blist/blist.lua index b67e3a99e1..220629d58a 100644 --- a/addons/blist/blist.lua +++ b/addons/blist/blist.lua @@ -269,7 +269,7 @@ windower.register_event('incoming text',function (original, modified, mode) elseif (mode == 15 or mode == 7) and settings.emote == true then -- emote a,z,name = string.find(original,'(%a+) ') elseif mode == 1 and settings.say == true then -- say - a,z,name = string.find(original,'(%a+) ') + a,z,name = string.find(original,'(%a+) :') elseif mode == 2 and settings.shout == true then -- shout a,z,name = string.find(original,'(%a+) ') elseif mode == 11 and settings.yell == true then -- yell From 3d3fa8a21b354f4078a7fcf14d18674497f35736 Mon Sep 17 00:00:00 2001 From: alphaONE <1904368+alphaONE2@users.noreply.github.com> Date: Sat, 2 Apr 2022 13:20:09 -0500 Subject: [PATCH 0820/1002] Add luasec library --- addons/libs/ssl.lua | 286 ++++++++++++++++++++++++++++++++++++++ addons/libs/ssl/https.lua | 146 +++++++++++++++++++ 2 files changed, 432 insertions(+) create mode 100644 addons/libs/ssl.lua create mode 100644 addons/libs/ssl/https.lua diff --git a/addons/libs/ssl.lua b/addons/libs/ssl.lua new file mode 100644 index 0000000000..c71ac27af9 --- /dev/null +++ b/addons/libs/ssl.lua @@ -0,0 +1,286 @@ +------------------------------------------------------------------------------ +-- LuaSec 1.0.2 +-- +-- Copyright (C) 2006-2021 Bruno Silvestre +-- +------------------------------------------------------------------------------ + +local core = require("ssl.core") +local context = require("ssl.context") +local x509 = require("ssl.x509") +local config = require("ssl.config") + +local unpack = table.unpack or unpack + +-- We must prevent the contexts to be collected before the connections, +-- otherwise the C registry will be cleared. +local registry = setmetatable({}, {__mode="k"}) + +-- +-- +-- +local function optexec(func, param, ctx) + if param then + if type(param) == "table" then + return func(ctx, unpack(param)) + else + return func(ctx, param) + end + end + return true +end + +-- +-- Convert an array of strings to wire-format +-- +local function array2wireformat(array) + local str = "" + for k, v in ipairs(array) do + if type(v) ~= "string" then return nil end + local len = #v + if len == 0 then + return nil, "invalid ALPN name (empty string)" + elseif len > 255 then + return nil, "invalid ALPN name (length > 255)" + end + str = str .. string.char(len) .. v + end + if str == "" then return nil, "invalid ALPN list (empty)" end + return str +end + +-- +-- Convert wire-string format to array +-- +local function wireformat2array(str) + local i = 1 + local array = {} + while i < #str do + local len = str:byte(i) + array[#array + 1] = str:sub(i + 1, i + len) + i = i + len + 1 + end + return array +end + +-- +-- +-- +local function newcontext(cfg) + local succ, msg, ctx + -- Create the context + ctx, msg = context.create(cfg.protocol) + if not ctx then return nil, msg end + -- Mode + succ, msg = context.setmode(ctx, cfg.mode) + if not succ then return nil, msg end + local certificates = cfg.certificates + if not certificates then + certificates = { + { certificate = cfg.certificate, key = cfg.key, password = cfg.password } + } + end + for _, certificate in ipairs(certificates) do + -- Load the key + if certificate.key then + if certificate.password and + type(certificate.password) ~= "function" and + type(certificate.password) ~= "string" + then + return nil, "invalid password type" + end + succ, msg = context.loadkey(ctx, certificate.key, certificate.password) + if not succ then return nil, msg end + end + -- Load the certificate(s) + if certificate.certificate then + succ, msg = context.loadcert(ctx, certificate.certificate) + if not succ then return nil, msg end + if certificate.key and context.checkkey then + succ = context.checkkey(ctx) + if not succ then return nil, "private key does not match public key" end + end + end + end + -- Load the CA certificates + if cfg.cafile or cfg.capath then + succ, msg = context.locations(ctx, cfg.cafile, cfg.capath) + if not succ then return nil, msg end + end + -- Set SSL ciphers + if cfg.ciphers then + succ, msg = context.setcipher(ctx, cfg.ciphers) + if not succ then return nil, msg end + end + -- Set SSL cipher suites + if cfg.ciphersuites then + succ, msg = context.setciphersuites(ctx, cfg.ciphersuites) + if not succ then return nil, msg end + end + -- Set the verification options + succ, msg = optexec(context.setverify, cfg.verify, ctx) + if not succ then return nil, msg end + -- Set SSL options + succ, msg = optexec(context.setoptions, cfg.options, ctx) + if not succ then return nil, msg end + -- Set the depth for certificate verification + if cfg.depth then + succ, msg = context.setdepth(ctx, cfg.depth) + if not succ then return nil, msg end + end + + -- NOTE: Setting DH parameters and elliptic curves needs to come after + -- setoptions(), in case the user has specified the single_{dh,ecdh}_use + -- options. + + -- Set DH parameters + if cfg.dhparam then + if type(cfg.dhparam) ~= "function" then + return nil, "invalid DH parameter type" + end + context.setdhparam(ctx, cfg.dhparam) + end + + -- Set elliptic curves + if (not config.algorithms.ec) and (cfg.curve or cfg.curveslist) then + return false, "elliptic curves not supported" + end + if config.capabilities.curves_list and cfg.curveslist then + succ, msg = context.setcurveslist(ctx, cfg.curveslist) + if not succ then return nil, msg end + elseif cfg.curve then + succ, msg = context.setcurve(ctx, cfg.curve) + if not succ then return nil, msg end + end + + -- Set extra verification options + if cfg.verifyext and ctx.setverifyext then + succ, msg = optexec(ctx.setverifyext, cfg.verifyext, ctx) + if not succ then return nil, msg end + end + + -- ALPN + if cfg.mode == "server" and cfg.alpn then + if type(cfg.alpn) == "function" then + local alpncb = cfg.alpn + -- This callback function has to return one value only + succ, msg = context.setalpncb(ctx, function(str) + local protocols = alpncb(wireformat2array(str)) + if type(protocols) == "string" then + protocols = { protocols } + elseif type(protocols) ~= "table" then + return nil + end + return (array2wireformat(protocols)) -- use "()" to drop error message + end) + if not succ then return nil, msg end + elseif type(cfg.alpn) == "table" then + local protocols = cfg.alpn + -- check if array is valid before use it + succ, msg = array2wireformat(protocols) + if not succ then return nil, msg end + -- This callback function has to return one value only + succ, msg = context.setalpncb(ctx, function() + return (array2wireformat(protocols)) -- use "()" to drop error message + end) + if not succ then return nil, msg end + else + return nil, "invalid ALPN parameter" + end + elseif cfg.mode == "client" and cfg.alpn then + local alpn + if type(cfg.alpn) == "string" then + alpn, msg = array2wireformat({ cfg.alpn }) + elseif type(cfg.alpn) == "table" then + alpn, msg = array2wireformat(cfg.alpn) + else + return nil, "invalid ALPN parameter" + end + if not alpn then return nil, msg end + succ, msg = context.setalpn(ctx, alpn) + if not succ then return nil, msg end + end + + if config.capabilities.dane and cfg.dane then + if type(cfg.dane) == "table" then + context.setdane(ctx, unpack(cfg.dane)) + else + context.setdane(ctx) + end + end + + return ctx +end + +-- +-- +-- +local function wrap(sock, cfg) + local ctx, msg + if type(cfg) == "table" then + ctx, msg = newcontext(cfg) + if not ctx then return nil, msg end + else + ctx = cfg + end + local s, msg = core.create(ctx) + if s then + core.setfd(s, sock:getfd()) + sock:setfd(core.SOCKET_INVALID) + registry[s] = ctx + return s + end + return nil, msg +end + +-- +-- Extract connection information. +-- +local function info(ssl, field) + local str, comp, err, protocol + comp, err = core.compression(ssl) + if err then + return comp, err + end + -- Avoid parser + if field == "compression" then + return comp + end + local info = {compression = comp} + str, info.bits, info.algbits, protocol = core.info(ssl) + if str then + info.cipher, info.protocol, info.key, + info.authentication, info.encryption, info.mac = + string.match(str, + "^(%S+)%s+(%S+)%s+Kx=(%S+)%s+Au=(%S+)%s+Enc=(%S+)%s+Mac=(%S+)") + info.export = (string.match(str, "%sexport%s*$") ~= nil) + end + if protocol then + info.protocol = protocol + end + if field then + return info[field] + end + -- Empty? + return ( (next(info)) and info ) +end + +-- +-- Set method for SSL connections. +-- +core.setmethod("info", info) + +-------------------------------------------------------------------------------- +-- Export module +-- + +local _M = { + _VERSION = "1.0.2", + _COPYRIGHT = core.copyright(), + config = config, + loadcertificate = x509.load, + newcontext = newcontext, + wrap = wrap, +} + +return _M diff --git a/addons/libs/ssl/https.lua b/addons/libs/ssl/https.lua new file mode 100644 index 0000000000..21bf530bfd --- /dev/null +++ b/addons/libs/ssl/https.lua @@ -0,0 +1,146 @@ +---------------------------------------------------------------------------- +-- LuaSec 1.0.2 +-- Copyright (C) 2009-2021 PUC-Rio +-- +-- Author: Pablo Musa +-- Author: Tomas Guisasola +--------------------------------------------------------------------------- + +local socket = require("socket") +local ssl = require("ssl") +local ltn12 = require("ltn12") +local http = require("socket.http") +local url = require("socket.url") + +local try = socket.try + +-- +-- Module +-- +local _M = { + _VERSION = "1.0.2", + _COPYRIGHT = "LuaSec 1.0.2 - Copyright (C) 2009-2021 PUC-Rio", + PORT = 443, + TIMEOUT = 60 +} + +-- TLS configuration +local cfg = { + protocol = "any", + options = {"all", "no_sslv2", "no_sslv3", "no_tlsv1"}, + verify = "none", +} + +-------------------------------------------------------------------- +-- Auxiliar Functions +-------------------------------------------------------------------- + +-- Insert default HTTPS port. +local function default_https_port(u) + return url.build(url.parse(u, {port = _M.PORT})) +end + +-- Convert an URL to a table according to Luasocket needs. +local function urlstring_totable(url, body, result_table) + url = { + url = default_https_port(url), + method = body and "POST" or "GET", + sink = ltn12.sink.table(result_table) + } + if body then + url.source = ltn12.source.string(body) + url.headers = { + ["content-length"] = #body, + ["content-type"] = "application/x-www-form-urlencoded", + } + end + return url +end + +-- Forward calls to the real connection object. +local function reg(conn) + local mt = getmetatable(conn.sock).__index + for name, method in pairs(mt) do + if type(method) == "function" then + conn[name] = function (self, ...) + return method(self.sock, ...) + end + end + end +end + +-- Return a function which performs the SSL/TLS connection. +local function tcp(params) + params = params or {} + -- Default settings + for k, v in pairs(cfg) do + params[k] = params[k] or v + end + -- Force client mode + params.mode = "client" + -- 'create' function for LuaSocket + return function () + local conn = {} + conn.sock = try(socket.tcp()) + local st = getmetatable(conn.sock).__index.settimeout + function conn:settimeout(...) + return st(self.sock, _M.TIMEOUT) + end + -- Replace TCP's connection function + function conn:connect(host, port) + try(self.sock:connect(host, port)) + self.sock = try(ssl.wrap(self.sock, params)) + self.sock:sni(host) + self.sock:settimeout(_M.TIMEOUT) + try(self.sock:dohandshake()) + reg(self, getmetatable(self.sock)) + return 1 + end + return conn + end +end + +-------------------------------------------------------------------- +-- Main Function +-------------------------------------------------------------------- + +-- Make a HTTP request over secure connection. This function receives +-- the same parameters of LuaSocket's HTTP module (except 'proxy' and +-- 'redirect') plus LuaSec parameters. +-- +-- @param url mandatory (string or table) +-- @param body optional (string) +-- @return (string if url == string or 1), code, headers, status +-- +local function request(url, body) + local result_table = {} + local stringrequest = type(url) == "string" + if stringrequest then + url = urlstring_totable(url, body, result_table) + else + url.url = default_https_port(url.url) + end + if http.PROXY or url.proxy then + return nil, "proxy not supported" + elseif url.redirect then + return nil, "redirect not supported" + elseif url.create then + return nil, "create function not permitted" + end + -- New 'create' function to establish a secure connection + url.create = tcp(url) + local res, code, headers, status = http.request(url) + if res and stringrequest then + return table.concat(result_table), code, headers, status + end + return res, code, headers, status +end + +-------------------------------------------------------------------------------- +-- Export module +-- + +_M.request = request +_M.tcp = tcp + +return _M From 156480db79e9cd2b5d9b603ce4b18964f62ce47f Mon Sep 17 00:00:00 2001 From: Byrth Date: Mon, 4 Apr 2022 07:22:01 -0400 Subject: [PATCH 0821/1002] Update digger messages for 2022-04 version --- addons/digger/messages.lua | 120 ++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/addons/digger/messages.lua b/addons/digger/messages.lua index dd53a7f91c..db2e57c019 100644 --- a/addons/digger/messages.lua +++ b/addons/digger/messages.lua @@ -1,61 +1,61 @@ messages = {} -messages[2] = {bayld=7375, ease=7367, fail=7292, full=7290, notes=7374, points=7372, standing=7373, success=6389} -messages[4] = {bayld=7369, ease=7361, fail=7286, full=7284, notes=7368, points=7366, standing=7367, success=6389} -messages[5] = {bayld=7326, ease=7318, fail=7243, full=7241, notes=7325, points=7323, standing=7324, success=6402} -messages[7] = {bayld=7320, ease=7312, fail=7237, full=7235, notes=7319, points=7317, standing=7318, success=6389} -messages[24] = {bayld=7656, ease=7648, fail=7573, full=7571, notes=7655, points=7653, standing=7654, success=6389} -messages[25] = {bayld=7176, ease=7168, fail=7093, full=7091, notes=7175, points=7173, standing=7174, success=6389} -messages[51] = {bayld=7151, ease=7143, fail=7068, full=7066, notes=7150, points=7148, standing=7149, success=6389} -messages[52] = {bayld=7151, ease=7143, fail=7068, full=7066, notes=7150, points=7148, standing=7149, success=6389} -messages[61] = {bayld=7151, ease=7143, fail=7068, full=7066, notes=7150, points=7148, standing=7149, success=6389} -messages[79] = {bayld=7151, ease=7143, fail=7068, full=7066, notes=7150, points=7148, standing=7149, success=6389} -messages[81] = {bayld=7835, ease=7827, fail=7752, full=7750, notes=7834, points=7832, standing=7833, success=6389} -messages[82] = {bayld=7467, ease=7459, fail=7384, full=7382, notes=7466, points=7464, standing=7465, success=6389} -messages[83] = {bayld=7154, ease=7146, fail=7071, full=7069, notes=7153, points=7151, standing=7152, success=6389} -messages[84] = {bayld=7174, ease=7166, fail=7091, full=7089, notes=7173, points=7171, standing=7172, success=6389} -messages[88] = {bayld=7460, ease=7452, fail=7377, full=7375, notes=7459, points=7457, standing=7458, success=6389} -messages[89] = {bayld=7154, ease=7146, fail=7071, full=7069, notes=7153, points=7151, standing=7152, success=6389} -messages[90] = {bayld=7251, ease=7243, fail=7168, full=7166, notes=7250, points=7248, standing=7249, success=6389} -messages[91] = {bayld=7174, ease=7166, fail=7091, full=7089, notes=7173, points=7171, standing=7172, success=6389} -messages[95] = {bayld=7181, ease=7173, fail=7098, full=7096, notes=7180, points=7178, standing=7179, success=6389} -messages[96] = {bayld=7154, ease=7146, fail=7071, full=7069, notes=7153, points=7151, standing=7152, success=6389} -messages[97] = {bayld=7712, ease=7704, fail=7629, full=7627, notes=7711, points=7709, standing=7710, success=6389} -messages[98] = {bayld=7712, ease=7704, fail=7629, full=7627, notes=7711, points=7709, standing=7710, success=6389} -messages[100] = {bayld=7335, ease=7327, fail=7252, full=7250, notes=7334, points=7332, standing=7333, success=6411} -messages[101] = {bayld=7335, ease=7327, fail=7252, full=7250, notes=7334, points=7332, standing=7333, success=6411} -messages[102] = {bayld=7317, ease=7309, fail=7234, full=7232, notes=7316, points=7314, standing=7315, success=6389} -messages[103] = {bayld=7335, ease=7327, fail=7252, full=7250, notes=7334, points=7332, standing=7333, success=6411} -messages[104] = {bayld=7809, ease=7801, fail=7726, full=7724, notes=7808, points=7806, standing=7807, success=6411} -messages[105] = {bayld=7335, ease=7327, fail=7252, full=7250, notes=7334, points=7332, standing=7333, success=6411} -messages[106] = {bayld=7335, ease=7327, fail=7252, full=7250, notes=7334, points=7332, standing=7333, success=6570} -messages[107] = {bayld=7335, ease=7327, fail=7252, full=7250, notes=7334, points=7332, standing=7333, success=6411} -messages[108] = {bayld=7317, ease=7309, fail=7234, full=7232, notes=7316, points=7314, standing=7315, success=6389} -messages[109] = {bayld=7335, ease=7327, fail=7252, full=7250, notes=7334, points=7332, standing=7333, success=6411} -messages[110] = {bayld=7335, ease=7327, fail=7252, full=7250, notes=7334, points=7332, standing=7333, success=6411} -messages[111] = {bayld=7335, ease=7327, fail=7252, full=7250, notes=7334, points=7332, standing=7333, success=6570} -messages[112] = {bayld=7352, ease=7344, fail=7269, full=7267, notes=7351, points=7349, standing=7350, success=6402} -messages[113] = {bayld=7655, ease=7647, fail=7572, full=7570, notes=7654, points=7652, standing=7653, success=6389} -messages[114] = {bayld=7655, ease=7647, fail=7572, full=7570, notes=7654, points=7652, standing=7653, success=6389} -messages[115] = {bayld=7154, ease=7146, fail=7071, full=7069, notes=7153, points=7151, standing=7152, success=6389} -messages[116] = {bayld=7313, ease=7305, fail=7230, full=7228, notes=7312, points=7310, standing=7311, success=6389} -messages[117] = {bayld=7335, ease=7327, fail=7252, full=7250, notes=7334, points=7332, standing=7333, success=6570} -messages[118] = {bayld=7354, ease=7346, fail=7271, full=7269, notes=7353, points=7351, standing=7352, success=6424} -messages[119] = {bayld=7335, ease=7327, fail=7252, full=7250, notes=7334, points=7332, standing=7333, success=6411} -messages[120] = {bayld=7343, ease=7335, fail=7260, full=7258, notes=7342, points=7340, standing=7341, success=6411} -messages[121] = {bayld=7655, ease=7647, fail=7572, full=7570, notes=7654, points=7652, standing=7653, success=6389} -messages[122] = {bayld=7313, ease=7305, fail=7230, full=7228, notes=7312, points=7310, standing=7311, success=6389} -messages[123] = {bayld=7655, ease=7647, fail=7572, full=7570, notes=7654, points=7652, standing=7653, success=6389} -messages[124] = {bayld=7655, ease=7647, fail=7572, full=7570, notes=7654, points=7652, standing=7653, success=6389} -messages[125] = {bayld=7313, ease=7305, fail=7230, full=7228, notes=7312, points=7310, standing=7311, success=6389} -messages[126] = {bayld=7313, ease=7305, fail=7230, full=7228, notes=7312, points=7310, standing=7311, success=6389} -messages[127] = {bayld=7313, ease=7305, fail=7230, full=7228, notes=7312, points=7310, standing=7311, success=6389} -messages[128] = {bayld=7313, ease=7305, fail=7230, full=7228, notes=7312, points=7310, standing=7311, success=6389} -messages[136] = {bayld=7154, ease=7146, fail=7071, full=7069, notes=7153, points=7151, standing=7152, success=6389} -messages[137] = {bayld=7676, ease=7668, fail=7593, full=7591, notes=7675, points=7673, standing=7674, success=6389} -messages[260] = {bayld=7154, ease=7146, fail=7071, full=7069, notes=7153, points=7151, standing=7152, success=6389} -messages[261] = {bayld=7154, ease=7146, fail=7071, full=7069, notes=7153, points=7151, standing=7152, success=6389} -messages[262] = {bayld=7154, ease=7146, fail=7071, full=7069, notes=7153, points=7151, standing=7152, success=6389} -messages[263] = {bayld=7154, ease=7146, fail=7071, full=7069, notes=7153, points=7151, standing=7152, success=6389} -messages[265] = {bayld=7154, ease=7146, fail=7071, full=7069, notes=7153, points=7151, standing=7152, success=6389} -messages[266] = {bayld=7154, ease=7146, fail=7071, full=7069, notes=7153, points=7151, standing=7152, success=6389} -messages[267] = {bayld=7154, ease=7146, fail=7071, full=7069, notes=7153, points=7151, standing=7152, success=6389} +messages[2] = {bayld=7376, ease=7368, fail=7293, full=7291, notes=7375, points=7373, standing=7374, success=6390} +messages[4] = {bayld=7370, ease=7362, fail=7287, full=7285, notes=7369, points=7367, standing=7368, success=6390} +messages[5] = {bayld=7327, ease=7319, fail=7244, full=7242, notes=7326, points=7324, standing=7325, success=6403} +messages[7] = {bayld=7321, ease=7313, fail=7238, full=7236, notes=7320, points=7318, standing=7319, success=6390} +messages[24] = {bayld=7657, ease=7649, fail=7574, full=7572, notes=7656, points=7654, standing=7655, success=6390} +messages[25] = {bayld=7177, ease=7169, fail=7094, full=7092, notes=7176, points=7174, standing=7175, success=6390} +messages[51] = {bayld=7152, ease=7144, fail=7069, full=7067, notes=7151, points=7149, standing=7150, success=6390} +messages[52] = {bayld=7152, ease=7144, fail=7069, full=7067, notes=7151, points=7149, standing=7150, success=6390} +messages[61] = {bayld=7152, ease=7144, fail=7069, full=7067, notes=7151, points=7149, standing=7150, success=6390} +messages[79] = {bayld=7152, ease=7144, fail=7069, full=7067, notes=7151, points=7149, standing=7150, success=6390} +messages[81] = {bayld=7836, ease=7828, fail=7753, full=7751, notes=7835, points=7833, standing=7834, success=6390} +messages[82] = {bayld=7468, ease=7460, fail=7385, full=7383, notes=7467, points=7465, standing=7466, success=6390} +messages[83] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} +messages[84] = {bayld=7175, ease=7167, fail=7092, full=7090, notes=7174, points=7172, standing=7173, success=6390} +messages[88] = {bayld=7461, ease=7453, fail=7378, full=7376, notes=7460, points=7458, standing=7459, success=6390} +messages[89] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} +messages[90] = {bayld=7252, ease=7244, fail=7169, full=7167, notes=7251, points=7249, standing=7250, success=6390} +messages[91] = {bayld=7175, ease=7167, fail=7092, full=7090, notes=7174, points=7172, standing=7173, success=6390} +messages[95] = {bayld=7182, ease=7174, fail=7099, full=7097, notes=7181, points=7179, standing=7180, success=6390} +messages[96] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} +messages[97] = {bayld=7713, ease=7705, fail=7630, full=7628, notes=7712, points=7710, standing=7711, success=6390} +messages[98] = {bayld=7713, ease=7705, fail=7630, full=7628, notes=7712, points=7710, standing=7711, success=6390} +messages[100] = {bayld=7336, ease=7328, fail=7253, full=7251, notes=7335, points=7333, standing=7334, success=6412} +messages[101] = {bayld=7336, ease=7328, fail=7253, full=7251, notes=7335, points=7333, standing=7334, success=6412} +messages[102] = {bayld=7318, ease=7310, fail=7235, full=7233, notes=7317, points=7315, standing=7316, success=6390} +messages[103] = {bayld=7336, ease=7328, fail=7253, full=7251, notes=7335, points=7333, standing=7334, success=6412} +messages[104] = {bayld=7810, ease=7802, fail=7727, full=7725, notes=7809, points=7807, standing=7808, success=6412} +messages[105] = {bayld=7336, ease=7328, fail=7253, full=7251, notes=7335, points=7333, standing=7334, success=6412} +messages[106] = {bayld=7336, ease=7328, fail=7253, full=7251, notes=7335, points=7333, standing=7334, success=6571} +messages[107] = {bayld=7336, ease=7328, fail=7253, full=7251, notes=7335, points=7333, standing=7334, success=6412} +messages[108] = {bayld=7318, ease=7310, fail=7235, full=7233, notes=7317, points=7315, standing=7316, success=6390} +messages[109] = {bayld=7336, ease=7328, fail=7253, full=7251, notes=7335, points=7333, standing=7334, success=6412} +messages[110] = {bayld=7336, ease=7328, fail=7253, full=7251, notes=7335, points=7333, standing=7334, success=6412} +messages[111] = {bayld=7336, ease=7328, fail=7253, full=7251, notes=7335, points=7333, standing=7334, success=6571} +messages[112] = {bayld=7353, ease=7345, fail=7270, full=7268, notes=7352, points=7350, standing=7351, success=6403} +messages[113] = {bayld=7656, ease=7648, fail=7573, full=7571, notes=7655, points=7653, standing=7654, success=6390} +messages[114] = {bayld=7656, ease=7648, fail=7573, full=7571, notes=7655, points=7653, standing=7654, success=6390} +messages[115] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} +messages[116] = {bayld=7314, ease=7306, fail=7231, full=7229, notes=7313, points=7311, standing=7312, success=6390} +messages[117] = {bayld=7336, ease=7328, fail=7253, full=7251, notes=7335, points=7333, standing=7334, success=6571} +messages[118] = {bayld=7355, ease=7347, fail=7272, full=7270, notes=7354, points=7352, standing=7353, success=6425} +messages[119] = {bayld=7336, ease=7328, fail=7253, full=7251, notes=7335, points=7333, standing=7334, success=6412} +messages[120] = {bayld=7344, ease=7336, fail=7261, full=7259, notes=7343, points=7341, standing=7342, success=6412} +messages[121] = {bayld=7656, ease=7648, fail=7573, full=7571, notes=7655, points=7653, standing=7654, success=6390} +messages[122] = {bayld=7314, ease=7306, fail=7231, full=7229, notes=7313, points=7311, standing=7312, success=6390} +messages[123] = {bayld=7656, ease=7648, fail=7573, full=7571, notes=7655, points=7653, standing=7654, success=6390} +messages[124] = {bayld=7656, ease=7648, fail=7573, full=7571, notes=7655, points=7653, standing=7654, success=6390} +messages[125] = {bayld=7314, ease=7306, fail=7231, full=7229, notes=7313, points=7311, standing=7312, success=6390} +messages[126] = {bayld=7314, ease=7306, fail=7231, full=7229, notes=7313, points=7311, standing=7312, success=6390} +messages[127] = {bayld=7314, ease=7306, fail=7231, full=7229, notes=7313, points=7311, standing=7312, success=6390} +messages[128] = {bayld=7314, ease=7306, fail=7231, full=7229, notes=7313, points=7311, standing=7312, success=6390} +messages[136] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} +messages[137] = {bayld=7677, ease=7669, fail=7594, full=7592, notes=7676, points=7674, standing=7675, success=6390} +messages[260] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} +messages[261] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} +messages[262] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} +messages[263] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} +messages[265] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} +messages[266] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} +messages[267] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} From 1841b885b310a776cb2c86aefa0d6da5c7dac0ee Mon Sep 17 00:00:00 2001 From: Byrth Date: Mon, 4 Apr 2022 07:25:01 -0400 Subject: [PATCH 0822/1002] Update boxdestroyer for the 2022-04 version --- addons/boxdestroyer/messages.lua | 120 +++++++++++++++---------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/addons/boxdestroyer/messages.lua b/addons/boxdestroyer/messages.lua index f9667ce353..7ae3377a40 100644 --- a/addons/boxdestroyer/messages.lua +++ b/addons/boxdestroyer/messages.lua @@ -1,63 +1,63 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination" for the associated zone IDs - [100] = 8074, - [101] = 7512, - [102] = 7925, - [103] = 8100, - [104] = 8665, - [105] = 7716, - [106] = 8090, - [107] = 7551, - [108] = 7620, - [109] = 8483, - [110] = 7607, - [111] = 8584, - [112] = 8186, - [113] = 7935, - [114] = 7785, - [115] = 7881, - [116] = 7577, - [117] = 7584, - [118] = 8126, - [119] = 8363, - [120] = 7523, - [121] = 8103, - [122] = 7441, - [123] = 7886, - [124] = 7837, - [125] = 7654, - [126] = 8070, - [127] = 7358, - [128] = 7513, - [130] = 7577, - [153] = 11403, - [157] = 7383, - [158] = 7389, - [159] = 8452, - [160] = 7416, - [166] = 10585, - [167] = 10599, - [169] = 7546, - [172] = 7419, - [173] = 10524, - [174] = 11402, - [176] = 7611, - [177] = 11226, - [178] = 11406, - [184] = 8636, - [190] = 8260, - [191] = 8380, - [192] = 7416, - [193] = 8392, - [194] = 8272, - [195] = 7603, - [196] = 8312, - [197] = 7357, - [198] = 8278, - [200] = 7534, - [204] = 7522, - [205] = 11489, - [208] = 8291, - [212] = 10645, - [213] = 10455, + [100] = 8075, + [101] = 7513, + [102] = 7926, + [103] = 8101, + [104] = 8666, + [105] = 7717, + [106] = 8091, + [107] = 7552, + [108] = 7621, + [109] = 8484, + [110] = 7608, + [111] = 8585, + [112] = 8187, + [113] = 7936, + [114] = 7786, + [115] = 7882, + [116] = 7578, + [117] = 7585, + [118] = 8127, + [119] = 8364, + [120] = 7524, + [121] = 8104, + [122] = 7442, + [123] = 7887, + [124] = 7838, + [125] = 7655, + [126] = 8071, + [127] = 7359, + [128] = 7514, + [130] = 7578, + [153] = 11404, + [157] = 7384, + [158] = 7390, + [159] = 8453, + [160] = 7417, + [166] = 10586, + [167] = 10600, + [169] = 7547, + [172] = 7420, + [173] = 10525, + [174] = 11403, + [176] = 7612, + [177] = 11227, + [178] = 11407, + [184] = 8637, + [190] = 8261, + [191] = 8381, + [192] = 7417, + [193] = 8393, + [194] = 8273, + [195] = 7604, + [196] = 8313, + [197] = 7358, + [198] = 8279, + [200] = 7535, + [204] = 7523, + [205] = 11490, + [208] = 8292, + [212] = 10646, + [213] = 10456, } offsets = {greater_less=1, failure=2, success=4, second_even_odd=5, first_even_odd=6, range=7, less=8, greater=9, equal=10, second_multiple=11, first_multiple=12, tool_failure=13} From 4be435f10210ed1ee95b1360f0c0118442e9994d Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Tue, 5 Apr 2022 02:36:35 +0200 Subject: [PATCH 0823/1002] [Slips lib] April 2022 Update Adding the items from the April 2022 FFXI Update. --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index c7d7b74208..d3af947a71 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -15,7 +15,7 @@ slips.storages = L{29312, 29313, 29314, 29315, 29316, 29317, 29318, 2931 slips.items = { [slips.storages[1]] = L{16084, 14546, 14961, 15625, 15711, 16085, 14547, 14962, 15626, 15712, 16086, 14548, 14963, 15627, 15713, 16087, 14549, 14964, 15628, 15714, 16088, 14550, 14965, 15629, 15715, 16089, 14551, 14966, 15630, 15716, 16090, 14552, 14967, 15631, 15717, 16091, 14553, 14968, 15632, 15718, 16092, 14554, 14969, 15633, 15719, 16093, 14555, 14970, 15634, 15720, 16094, 14556, 14971, 15635, 15721, 16095, 14557, 14972, 15636, 15722, 16096, 14558, 14973, 15637, 15723, 16097, 14559, 14974, 15638, 15724, 16098, 14560, 14975, 15639, 15725, 16099, 14561, 14976, 15640, 15726, 16100, 14562, 14977, 15641, 15727, 16101, 14563, 14978, 15642, 15728, 16102, 14564, 14979, 15643, 15729, 16103, 14565, 14980, 15644, 15730, 16106, 14568, 14983, 15647, 15733, 16107, 14569, 14984, 15648, 15734, 16108, 14570, 14985, 15649, 15735, 16602, 17741, 18425, 18491, 18588, 18717, 18718, 18850, 18943, 16069, 14530, 14940, 15609, 15695, 16062, 14525, 14933, 15604, 15688, 16064, 14527, 14935, 15606, 15690, 18685, 18065, 17851, 18686, 18025, 18435, 18113, 17951, 17715, 18485, 18408, 18365, 18583, 18417, 18388, 16267, 16268, 16269, 16228, 16229, 15911, 15799, 15800, 15990, 17745, 18121, 16117, 14577, 17857}, -- 168 [slips.storages[2]] = L{12421, 12549, 12677, 12805, 12933, 13911, 14370, 14061, 14283, 14163, 12429, 12557, 12685, 12813, 12941, 13924, 14371, 14816, 14296, 14175, 13934, 14387, 14821, 14303, 14184, 13935, 14388, 14822, 14304, 14185, 13876, 13787, 14006, 14247, 14123, 13877, 13788, 14007, 14248, 14124, 13908, 14367, 14058, 14280, 14160, 13909, 14368, 14059, 14281, 14161, 16113, 14573, 14995, 15655, 15740, 16115, 14575, 14997, 15657, 15742, 16114, 14574, 14996, 15656, 15741, 16116, 14576, 14998, 15658, 15743, 12818, 18198, 12946, 18043, 12690, 17659, 12296, 12434, 15471, 15472, 15473, 15508, 15509, 15510, 15511, 15512, 15513, 15514, 17710, 17595, 18397, 18360, 18222, 17948, 18100, 15475, 15476, 15477, 15488, 15961, 14815, 14812, 14813, 15244, 15240, 14488, 14905, 15576, 15661, 15241, 14489, 14906, 15577, 15662, 13927, 14378, 14076, 14308, 14180, 13928, 14379, 14077, 14309, 14181, 10438, 10276, 10320, 10326, 10367, 10439, 10277, 10321, 10327, 10368, 10440, 10278, 10322, 10328, 10369, 10441, 10279, 10323, 10329, 10370, 25734, 25735, 25736, 25737, 25738, 25739, 25740, 25741, 25742, 25743, 25744}, -- 155 - [slips.storages[3]] = L{16155, 11282, 15021, 16341, 11376, 16156, 11283, 15022, 16342, 11377, 16157, 11284, 15023, 16343, 11378, 16148, 14590, 15011, 16317, 15757, 16143, 14591, 15012, 16318, 15758, 16146, 14588, 15009, 16315, 15755, 16147, 14589, 15010, 16316, 15756, 15966, 15967, 19041, 17684, 17685, 11636, 15844, 15934, 16258, 18735, 18734, 16291, 16292, 19042, 15935, 16293, 16294, 15936, 18618, 11588, 11545, 16158, 16159, 16160, 16149, 14583, 15007, 16314, 15751, 16141, 14581, 15005, 16312, 15749, 16142, 14582, 15006, 16313, 15750, 10876, 10450, 10500, 11969, 10600, 10877, 10451, 10501, 11970, 10601, 10878, 10452, 10502, 11971, 10602, 19132, 18551, 11798, 11362, 11363, 11625, 15959, 16259, 22299, 26414, 21623, 26219, 21886, 23792, 23793, 23794, 23795, 23796, 22032, 22043, 21530, 22044, 26273, 25415}, -- 113 + [slips.storages[3]] = L{16155, 11282, 15021, 16341, 11376, 16156, 11283, 15022, 16342, 11377, 16157, 11284, 15023, 16343, 11378, 16148, 14590, 15011, 16317, 15757, 16143, 14591, 15012, 16318, 15758, 16146, 14588, 15009, 16315, 15755, 16147, 14589, 15010, 16316, 15756, 15966, 15967, 19041, 17684, 17685, 11636, 15844, 15934, 16258, 18735, 18734, 16291, 16292, 19042, 15935, 16293, 16294, 15936, 18618, 11588, 11545, 16158, 16159, 16160, 16149, 14583, 15007, 16314, 15751, 16141, 14581, 15005, 16312, 15749, 16142, 14582, 15006, 16313, 15750, 10876, 10450, 10500, 11969, 10600, 10877, 10451, 10501, 11970, 10601, 10878, 10452, 10502, 11971, 10602, 19132, 18551, 11798, 11362, 11363, 11625, 15959, 16259, 22299, 26414, 21623, 26219, 21886, 23792, 23793, 23794, 23795, 23796, 22032, 22043, 21530, 22044, 26273, 25415, 25416, 25414}, -- 115 [slips.storages[4]] = L{12511, 12638, 13961, 14214, 14089, 12512, 12639, 13962, 14215, 14090, 13855, 12640, 13963, 14216, 14091, 13856, 12641, 13964, 14217, 14092, 12513, 12642, 13965, 14218, 14093, 12514, 12643, 13966, 14219, 14094, 12515, 12644, 13967, 14220, 14095, 12516, 12645, 13968, 14221, 14096, 12517, 12646, 13969, 14222, 14097, 13857, 12647, 13970, 14223, 14098, 12518, 12648, 13971, 14099, 14224, 13868, 13781, 13972, 14225, 14100, 13869, 13782, 13973, 14226, 14101, 12519, 12649, 13974, 14227, 14102, 12520, 12650, 13975, 14228, 14103, 15265, 14521, 14928, 15600, 15684, 15266, 14522, 14929, 15601, 15685, 15267, 14523, 14930, 15602, 15686, 16138, 14578, 15002, 15659, 15746, 16139, 14579, 15003, 15660, 15747, 16140, 14580, 15004, 16311, 15748, 16678, 17478, 17422, 17423, 16829, 16764, 17643, 16798, 16680, 16766, 17188, 17812, 17771, 17772, 16887, 17532, 17717, 18702, 17858, 19203, 21461, 21124, 20776, 27786, 27926, 28066, 28206, 28346, 27787, 27927, 28067, 28207, 28347}, -- 138 [slips.storages[5]] = L{15225, 14473, 14890, 15561, 15352, 15226, 14474, 14891, 15562, 15353, 15227, 14475, 14892, 15563, 15354, 15228, 14476, 14893, 15564, 15355, 15229, 14477, 14894, 15565, 15356, 15230, 14478, 14895, 15566, 15357, 15231, 14479, 14896, 15567, 15358, 15232, 14480, 14897, 15568, 15359, 15233, 14481, 14898, 15569, 15360, 15234, 14482, 14899, 15570, 15361, 15235, 14483, 14900, 15362, 15571, 15236, 14484, 14901, 15572, 15363, 15237, 14485, 14902, 15573, 15364, 15238, 14486, 14903, 15574, 15365, 15239, 14487, 14904, 15575, 15366, 11464, 11291, 15024, 16345, 11381, 11467, 11294, 15027, 16348, 11384, 11470, 11297, 15030, 16351, 11387, 11475, 11302, 15035, 16357, 11393, 11476, 11303, 15036, 16358, 11394, 11477, 11304, 15037, 16359, 11395}, -- 105 [slips.storages[6]] = L{15072, 15087, 15102, 15117, 15132, 15871, 15073, 15088, 15103, 15118, 15133, 15478, 15074, 15089, 15104, 15119, 15134, 15872, 15075, 15090, 15105, 15120, 15135, 15874, 15076, 15091, 15106, 15121, 15136, 15873, 15077, 15092, 15107, 15122, 15137, 15480, 15078, 15093, 15108, 15123, 15138, 15481, 15079, 15094, 15109, 15124, 15139, 15479, 15080, 15095, 15110, 15125, 15140, 15875, 15081, 15096, 15111, 15126, 15141, 15482, 15082, 15097, 15112, 15127, 15142, 15876, 15083, 15098, 15113, 15128, 15143, 15879, 15084, 15099, 15114, 15129, 15144, 15877, 15085, 15100, 15115, 15130, 15145, 15878, 15086, 15101, 15116, 15131, 15146, 15484, 11465, 11292, 15025, 16346, 11382, 16244, 11468, 11295, 15028, 16349, 11385, 15920, 11471, 11298, 15031, 16352, 11388, 16245, 11478, 11305, 15038, 16360, 11396, 16248, 11480, 11307, 15040, 16362, 11398, 15925}, -- 120 From 8802c822f22a94905130da2fc1747b8bbbdb69e3 Mon Sep 17 00:00:00 2001 From: Mike <53079961+Atsuke@users.noreply.github.com> Date: Sat, 9 Apr 2022 13:17:10 -0400 Subject: [PATCH 0824/1002] Support bug fix Occasionally addon will try to resume crafting too quickly after interacting with support npc causing entire queue to be dumped with "you cannot craft at this time" errors. Added a short delay in the check_queue function after poke_npc() call. --- addons/craft/craft.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/craft/craft.lua b/addons/craft/craft.lua index 9751dd7587..f8b89b74d5 100644 --- a/addons/craft/craft.lua +++ b/addons/craft/craft.lua @@ -532,6 +532,7 @@ local function check_queue() end if support then poke_npc() + coroutine.sleep(2) end if food then consume_food() From 84842de8793fa99ee68dd3045ea4b016fddc085d Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Sat, 9 Apr 2022 12:19:57 -0600 Subject: [PATCH 0825/1002] Allow for start/end pattern matching --- addons/findAll/findAll.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/addons/findAll/findAll.lua b/addons/findAll/findAll.lua index 6f96455dac..5a9408f90f 100644 --- a/addons/findAll/findAll.lua +++ b/addons/findAll/findAll.lua @@ -162,6 +162,9 @@ do end) end end +string.query_escape = function(str) + return (str:gsub('[()%.%+?-]', '%%%1')) +end zone_search = windower.ffxi.get_info().logged_in first_pass = true @@ -272,9 +275,11 @@ function search(query, export) local terms_pattern = '' if terms ~= '' then - terms_pattern = terms:escape():gsub('%a', function(char) return string.format("[%s%s]", char:lower(), char:upper()) end) + terms_pattern = terms:query_escape():gsub('%a', function(char) return string.format("[%s%s]", char:lower(), char:upper()) end) end + print(terms_pattern) + for id, names in pairs(item_names) do if terms_pattern == '' or item_names[id].name:find(terms_pattern) or item_names[id].long_name:find(terms_pattern) From 8cec1c7ca7e94e4c665ca1d145e2a56a3dd5b07f Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Sat, 9 Apr 2022 12:20:32 -0600 Subject: [PATCH 0826/1002] fix print/whitespace --- addons/findAll/findAll.lua | 2 -- 1 file changed, 2 deletions(-) diff --git a/addons/findAll/findAll.lua b/addons/findAll/findAll.lua index 5a9408f90f..192f6f96f5 100644 --- a/addons/findAll/findAll.lua +++ b/addons/findAll/findAll.lua @@ -278,8 +278,6 @@ function search(query, export) terms_pattern = terms:query_escape():gsub('%a', function(char) return string.format("[%s%s]", char:lower(), char:upper()) end) end - print(terms_pattern) - for id, names in pairs(item_names) do if terms_pattern == '' or item_names[id].name:find(terms_pattern) or item_names[id].long_name:find(terms_pattern) From 690fe5baf118f9e8bef982f7c20bdc22fafc5fea Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Mon, 25 Apr 2022 19:36:37 -0600 Subject: [PATCH 0827/1002] Pointwatch Fix broken Time Remaining --- addons/pointwatch/statics.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/pointwatch/statics.lua b/addons/pointwatch/statics.lua index 99a199baab..bf87bc2ea7 100644 --- a/addons/pointwatch/statics.lua +++ b/addons/pointwatch/statics.lua @@ -30,7 +30,7 @@ default_settings = { strings = { default = "string.format('%d/%dXP %sMerits XP/hr:%.1fk %sJP CP/hr:%.1fk %d/%dEP EP/hr:%.1fk',xp.current,xp.tnl,max_color('%5.2f':format(math.floor(lp.current/lp.tnm*100)/100+lp.number_of_merits),lp.current/lp.tnm+lp.number_of_merits,lp.maximum_merits,58,147,191),math.floor(xp.rate/100)/10,max_color('%6.2f':format(math.floor(cp.current/cp.tnjp*100)/100+cp.number_of_job_points),cp.current/cp.tnjp+cp.number_of_job_points,500,58,147,191),math.floor(cp.rate/100)/10,ep.current,ep.tnml,math.floor(ep.rate/100)/10)", dynamis = "string.format('%d/%dXP %sMerits XP/hr:%.1fk %sJP CP/hr:%.1fk %d/%dEP %s %s',xp.current,xp.tnl,max_color('%5.2f':format(math.floor(lp.current/lp.tnm*100)/100+lp.number_of_merits),lp.current/lp.tnm+lp.number_of_merits,lp.maximum_merits,58,147,191),math.floor(xp.rate/100)/10,max_color('%6.2f':format(math.floor(cp.current/cp.tnjp*100)/100+cp.number_of_job_points),cp.current/cp.tnjp+cp.number_of_job_points,500,58,147,191),math.floor(cp.rate/100)/10,ep.current,ep.tnml,dynamis.KIs,dynamis.time_remaining or 0)", - abyssea = "string.format('%d/%dXP %sMerits XP/hr:%.1fk %sJP CP/hr:%.1fk %d/%dEP Amber:%d Azure:%d Ruby:%d Pearl:%d Ebon:%d Silver: Gold:%d Time-Remaining:%d',xp.current,xp.tnl,max_color('%5.2f':format(math.floor(lp.current/lp.tnm*100)/100+lp.number_of_merits),lp.current/lp.tnm+lp.number_of_merits,lp.maximum_merits,58,147,191),math.floor(xp.rate/100)/10,max_color('%6.2f':format(math.floor(cp.current/cp.tnjp*100)/100+cp.number_of_job_points),cp.current/cp.tnjp+cp.number_of_job_points,500,58,147,191),math.floor(cp.rate/100)/10,ep.current,ep.tnml,abyssea.amber or 0,abyssea.azure or 0,abyssea.ruby or 0,abyssea.pearlescent or 0,abyssea.ebon or 0,abyssea.silvery or 0,abyssea.golden or 0,abyssea.time_remaining or 0)", + abyssea = "string.format('%d/%dXP %sMerits XP/hr:%.1fk %sJP CP/hr:%.1fk %d/%dEP Amber:%d Azure:%d Ruby:%d Pearl:%d Ebon:%d Silver:%d Gold:%d Time-Remaining:%d',xp.current,xp.tnl,max_color('%5.2f':format(math.floor(lp.current/lp.tnm*100)/100+lp.number_of_merits),lp.current/lp.tnm+lp.number_of_merits,lp.maximum_merits,58,147,191),math.floor(xp.rate/100)/10,max_color('%6.2f':format(math.floor(cp.current/cp.tnjp*100)/100+cp.number_of_job_points),cp.current/cp.tnjp+cp.number_of_job_points,500,58,147,191),math.floor(cp.rate/100)/10,ep.current,ep.tnml,abyssea.amber or 0,abyssea.azure or 0,abyssea.ruby or 0,abyssea.pearlescent or 0,abyssea.ebon or 0,abyssea.silvery or 0,abyssea.golden or 0,abyssea.time_remaining or 0)", }, text_box_settings = { pos = { From c59629c5826356721b2e80a52bb6199cbe4f0cdc Mon Sep 17 00:00:00 2001 From: Byrth Date: Mon, 2 May 2022 08:42:43 -0400 Subject: [PATCH 0828/1002] Make 0xDF and 0xE2 also update the alliance structure --- addons/GearSwap/packet_parsing.lua | 75 ++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 25 deletions(-) diff --git a/addons/GearSwap/packet_parsing.lua b/addons/GearSwap/packet_parsing.lua index f8cabf325f..869b73579c 100644 --- a/addons/GearSwap/packet_parsing.lua +++ b/addons/GearSwap/packet_parsing.lua @@ -639,36 +639,61 @@ parse.i[0x076] = function (data) end end -parse.i[0x0DF] = function (data) - if data:unpack('I',5) == player.id then - player.vitals.hp = data:unpack('I',9) - player.vitals.mp = data:unpack('I',13) - player.vitals.tp = data:unpack('I',0x11) - player.vitals.hpp = data:byte(0x17) - player.vitals.mpp = data:byte(0x18) +function update_vitals(id, hp, mp, tp, hpp, mpp) + if id==player.id then + player.vitals.hp = hp + player.vitals.mp = mp + player.vitals.tp = tp + player.vitals.hpp = hpp + player.vitals.mpp = mpp - player.hp = data:unpack('I',9) - player.mp = data:unpack('I',13) - player.tp = data:unpack('I',0x11) - player.hpp = data:byte(0x17) - player.mpp = data:byte(0x18) + player.hp = hp + player.mp = mp + player.tp = tp + player.hpp = hpp + player.mpp = mpp + end + -- Update alliance + local found_person = false + for i,v in pairs(alliance) do + if type(v) == 'table' then + for k,j in pairs(v) do + if type(j) == 'table' and j.id == id then + j.hp = hp + j.mp = mp + j.tp = tp + j.hpp = hpp + j.mpp = mpp + found_person = true + end + end + if found_person then + break + end + end end end +parse.i[0x0DF] = function (data) + update_vitals( + data:unpack('I',5), + data:unpack('I',9), + data:unpack('I',13), + data:unpack('I',0x11), + data:byte(0x17), + data:byte(0x18) + ) +end + parse.i[0x0E2] = function (data) - if data:unpack('I',5)==player.id then - player.vitals.hp = data:unpack('I',9) - player.vitals.mp = data:unpack('I',0xB) - player.vitals.tp = data:unpack('I',0x11) - player.vitals.hpp = data:byte(0x1E) - player.vitals.mpp = data:byte(0x1F) - - player.hp = data:unpack('I',9) - player.mp = data:unpack('I',0xB) - player.tp = data:unpack('I',0x11) - player.hpp = data:byte(0x1E) - player.mpp = data:byte(0x1F) - end + update_vitals( + data:unpack('I',5), + data:unpack('I',9), + data:unpack('I',0xB), + data:unpack('I',0x11), + data:byte(0x1E), + data:byte(0x1F) + ) end parse.o[0x100] = function(data) From ccd2183f52eb9293f95232c32dd5a968c98a0e23 Mon Sep 17 00:00:00 2001 From: funkworkz Date: Tue, 10 May 2022 02:02:41 -0500 Subject: [PATCH 0829/1002] Update setbgm.lua --- addons/setbgm/setbgm.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/setbgm/setbgm.lua b/addons/setbgm/setbgm.lua index 88e99c45d7..c0b49f0d5c 100644 --- a/addons/setbgm/setbgm.lua +++ b/addons/setbgm/setbgm.lua @@ -50,7 +50,7 @@ music_types = { } songs = { - [25]='Voracious Resurgence Unknown 1', [26]='Voracious Resurgence Unknown 2', [27]='Voracious Resurgence Unknown 3', [28]='Voracious Resurgence Unknown 4', [29]="Devils' Delight", [30]="Odyssey - Bumba", [31]='Voracious Resurgence Unknown 5', [32]='Voracious Resurgence Unknown 6', [33]='Voracious Resurgence Unknown 7', + [25]='Voracious Resurgence Unknown 1', [26]='Voracious Resurgence Unknown 2', [27]='Voracious Resurgence Unknown 3', [28]='Voracious Resurgence Unknown 4', [29]="Devils' Delight", [30]="Odyssey - Bumba", [31]='Voracious Resurgence Unknown 5', [32]='Voracious Resurgence Unknown 6', [33]='Voracious Resurgence Unknown 7', [34]="We Are Vana'diel", [40]='Cloister of Time and Souls', [41]='Royal Wanderlust', [42]='Snowdrift Waltz', [43]='Troubled Shadows', [44]='Where Lords Rule Not', [45]='Summers Lost', [46]='Goddess Divine', [47]='Echoes of Creation', [48]='Main Theme', [49]='Luck of the Mog', [50]='Feast of the Ladies', [51]='Abyssea - Scarlet Skies, Shadowed Plains', [52]='Melodies Errant', [53]='Shinryu', [54]='Everlasting Bonds', [55]='Provenance Watcher', [56]='Where it All Begins', [57]='Steel Sings, Blades Dance', [58]='A New Direction', [59]='The Pioneers', [60]='Into Lands Primeval - Ulbuka', [61]="Water's Umbral Knell", [62]='Keepers of the Wild', [63]='The Sacred City of Adoulin', [64]='Breaking Ground', [65]='Hades', [66]='Arciela', [67]='Mog Resort', [68]='Worlds Away', [69]="Distant Worlds (Nanaa Mihgo's version)", From 072926991196b180bcff388c5b3233b052e14eed Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Tue, 10 May 2022 14:53:27 -0600 Subject: [PATCH 0830/1002] Trusts - Re-Add Cornelia Don't know why she was commented out in the first place --- addons/Trusts/Trusts.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/Trusts/Trusts.lua b/addons/Trusts/Trusts.lua index 11e9c6de7f..36d03527de 100644 --- a/addons/Trusts/Trusts.lua +++ b/addons/Trusts/Trusts.lua @@ -367,7 +367,7 @@ trusts = T{ [117]={id=1017,japanese="アシェラII",english="Arciela II",name="Arciela",models=3085}, [118]={id=1018,japanese="イロハII",english="Iroha II",name="Iroha",models=3112}, [119]={id=1019,japanese="シャントットII",english="Shantotto II",name="Shantotto",models=3110}, --- [120]={id=1003,japanese="コーネリア",english="Cornelia",name="Cornelia",models=3119}, --goodbye, my love + [120]={id=1003,japanese="コーネリア",english="Cornelia",name="Cornelia",models=3119}, --goodbye, my love [121]={id=999,japanese="モンブロー",english="Monberaux",name="Monberaux",models=3120}, [122]={id=1003,japanese="マツイP",english="Matsui-P",name="Matsui-P",models=3121}, } From dc6ae40df64d513dbc60f69c1cb60a2afe957acd Mon Sep 17 00:00:00 2001 From: Byrth Date: Fri, 13 May 2022 06:25:47 -0400 Subject: [PATCH 0831/1002] Add vana time offset --- addons/GearSwap/packet_parsing.lua | 7 ++++--- addons/GearSwap/statics.lua | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/addons/GearSwap/packet_parsing.lua b/addons/GearSwap/packet_parsing.lua index 869b73579c..0dba6a1b64 100644 --- a/addons/GearSwap/packet_parsing.lua +++ b/addons/GearSwap/packet_parsing.lua @@ -185,6 +185,8 @@ parse.i[0x037] = function (data) end end end]] + -- Info provided by Akaden + vana_offset = os.time() - (((data:unpack("I",0x41)*60 + data:unpack("I",0x37)) % 0x100000000) / 60) local indi_byte = data:byte(0x59) if indi_byte%128/64 >= 1 then @@ -457,7 +459,7 @@ parse.i[0x063] = function (data) for i=1,32 do local buff_id = data:unpack('H',i*2+7) if buff_id ~= 255 and buff_id ~= 0 then -- 255 is used for "no buff" - local t = data:unpack('I',i*4+0x45)/60+572662306+1009810800 + local t = data:unpack('I',i*4+0x45)/60 + vana_offset newbuffs[i] = setmetatable({ name=res.buffs[buff_id].name, buff=copy_entry(res.buffs[buff_id]), @@ -475,7 +477,6 @@ parse.i[0x063] = function (data) end end if seen_0x063_type9 then - -- Look for exact matches for n,new in pairs(newbuffs) do newbuffs[n].matched_exactly = nil @@ -556,7 +557,7 @@ parse.i[0x063] = function (data) end end end - + table.reassign(_ExtraData.player.buff_details,newbuffs) for i=1,32 do player.buffs[i] = (newbuffs[i] and newbuffs[i].id) or nil diff --git a/addons/GearSwap/statics.lua b/addons/GearSwap/statics.lua index 49863a1d49..a81f428bee 100644 --- a/addons/GearSwap/statics.lua +++ b/addons/GearSwap/statics.lua @@ -190,6 +190,7 @@ slot_map.back = 15 gearswap_disabled = false seen_0x063_type9 = false delay_0x063_v9 = false +vana_offset = 572662306+1009810800 not_sent_out_equip = {} command_registry = Command_Registry.new() equip_list = {} From 0d564b4b09d2310e52f107f279948e7a81042da6 Mon Sep 17 00:00:00 2001 From: WinterSolstice8 <60417494+WinterSolstice8@users.noreply.github.com> Date: Fri, 13 May 2022 15:58:44 -0700 Subject: [PATCH 0832/1002] [gearswap] Fix duration calculation in packet_parsing.lua Co-authored-by: RubenatorX --- addons/GearSwap/packet_parsing.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/GearSwap/packet_parsing.lua b/addons/GearSwap/packet_parsing.lua index 0dba6a1b64..410ea7613c 100644 --- a/addons/GearSwap/packet_parsing.lua +++ b/addons/GearSwap/packet_parsing.lua @@ -186,8 +186,8 @@ parse.i[0x037] = function (data) end end]] -- Info provided by Akaden - vana_offset = os.time() - (((data:unpack("I",0x41)*60 + data:unpack("I",0x37)) % 0x100000000) / 60) - + vana_offset = os.time() - (((data:unpack("I",0x41)*60 - data:unpack("I",0x3D)) % 0x100000000) / 60) + local indi_byte = data:byte(0x59) if indi_byte%128/64 >= 1 then local temp_indi = _ExtraData.player.indi @@ -459,7 +459,7 @@ parse.i[0x063] = function (data) for i=1,32 do local buff_id = data:unpack('H',i*2+7) if buff_id ~= 255 and buff_id ~= 0 then -- 255 is used for "no buff" - local t = data:unpack('I',i*4+0x45)/60 + vana_offset + local t = data:unpack('I',i*4+0x45)/60 newbuffs[i] = setmetatable({ name=res.buffs[buff_id].name, buff=copy_entry(res.buffs[buff_id]), @@ -469,7 +469,7 @@ parse.i[0x063] = function (data) }, {__index=function(t,k) if k and k=='duration' then - return rawget(t,'time')-os.time() + return rawget(t,'time')-os.time()+(vana_offset or 0) else return rawget(t,k) end From 2989eaebf9c71870e446dbc7a2ebfa5b6ebd9157 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Tue, 17 May 2022 01:51:09 +0200 Subject: [PATCH 0833/1002] [Slips lib] Update for May 2022 Added items to slips libs for the 10 May, 2022 FFXI Update. --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index d3af947a71..860e12930d 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757, 25909}, -- 192 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751}, -- 146 SE Skipped an index hence the 0 as one of the items + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049}, -- 151 SE Skipped an index hence the 0 as one of the items [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067, 21680, 22071}, --177 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, --115 From c902c7658bde23e9a10f6d8754bc7fea7a4d9ea8 Mon Sep 17 00:00:00 2001 From: Byrth Date: Sun, 22 May 2022 20:44:22 -0400 Subject: [PATCH 0834/1002] get_player() sometimes returns nil when logging out --- addons/pointwatch/pointwatch.lua | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/addons/pointwatch/pointwatch.lua b/addons/pointwatch/pointwatch.lua index 386869e397..dea5cf61aa 100644 --- a/addons/pointwatch/pointwatch.lua +++ b/addons/pointwatch/pointwatch.lua @@ -132,9 +132,12 @@ packet_handlers = { lp.number_of_merits = p['Merit Points'] lp.maximum_merits = p['Max Merit Points'] elseif p['Order'] == 5 then - local job = windower.ffxi.get_player().main_job_full - cp.current = p[job..' Capacity Points'] - cp.number_of_job_points = p[job..' Job Points'] + local player = windower.ffxi.get_player() + if player then + local job = player.main_job_full + cp.current = p[job..' Capacity Points'] + cp.number_of_job_points = p[job..' Job Points'] + end end end, [0x110] = function(org) From c776dbfaabf93e9ce6dd28722639a799dcc8d910 Mon Sep 17 00:00:00 2001 From: Byrth Date: Sun, 22 May 2022 21:22:11 -0400 Subject: [PATCH 0835/1002] remove message printing from pointwatch --- addons/pointwatch/FIXING POINTWATCH.txt | 35 ------------------------- addons/pointwatch/ReadMe.txt | 4 --- addons/pointwatch/pointwatch.lua | 8 +----- addons/pointwatch/statics.lua | 5 +--- 4 files changed, 2 insertions(+), 50 deletions(-) delete mode 100644 addons/pointwatch/FIXING POINTWATCH.txt diff --git a/addons/pointwatch/FIXING POINTWATCH.txt b/addons/pointwatch/FIXING POINTWATCH.txt deleted file mode 100644 index 61bb39cdaf..0000000000 --- a/addons/pointwatch/FIXING POINTWATCH.txt +++ /dev/null @@ -1,35 +0,0 @@ -Updating Message IDs: A guide - - Pointwatch relies on zone-based message IDs for some of its features. -These IDs change on a regular basis. Fortunately, their positions relative -to one another rarely change, which means that most of the time you only -have to change one number and the entire zone will work again. - -I have written this guide to explain how to change those numbers in the -hopes that members of the community will maintain pointwatch's message- -dependent features. - -Method 1 - POLUtils -1) Download POLUtils (if you don't already have it) from the google code site -2) Install it and run it -3) Click "FFXI Data Browser" -4) Go to the "Dialog Tables" menu and select the zone you are interested in -5) Wait for it to load, then export the entire table as xml -6) Open the xml file up in a text editor, like Notepad or Notepad++. -7) Control-F for the key phrase. -8) The associated message ID is the offset value for that zone. - -Method 2 - message_printing -1) Load Pointwatch (//lua l pointwatch) -2) Enable message printing (//pw message_printing) -3) Generate the key message (for instance, by resting in Abyssea) -4) This will print message IDs to your windower console. They appear in the - order they were generated. Select the one that you want (for instance, - the second one when you rest in Abyssea). -5) That value is your offset. -6) Disable message printing (//pw message_printing) - -Both methods: -* Open message_ids.lua -* Find the zone and replace the zone.offset value with the correct value. -* Submit your file to Github, so that everyone can have a working copy! diff --git a/addons/pointwatch/ReadMe.txt b/addons/pointwatch/ReadMe.txt index 4616a8c477..2143b47d8f 100644 --- a/addons/pointwatch/ReadMe.txt +++ b/addons/pointwatch/ReadMe.txt @@ -14,10 +14,6 @@ Text Box Commands: * bg_transparency - Changes the background transparency. Number should be between 0 and 1 ** pos_x, pos_y, pad, transparency, alpha, and bg_alpha are also valid commands and are documented in the texts library. -Other Commands: -* message_printing - See FIXING POINTWATCH.txt in this directory for a full explanation. - - Strings Options: The two strings options in settings.xml are loaded as Lua code and run accordingly, diff --git a/addons/pointwatch/pointwatch.lua b/addons/pointwatch/pointwatch.lua index dea5cf61aa..4fc0ac0dda 100644 --- a/addons/pointwatch/pointwatch.lua +++ b/addons/pointwatch/pointwatch.lua @@ -64,10 +64,7 @@ packet_handlers = { [0x02A] = function(org) -- Resting message local p = packets.parse('incoming',org) local zone = 'z'..windower.ffxi.get_info().zone - if settings.options.message_printing then - print('Message ID: '..bit.band(p['Message ID'], 16383)) - end - + if messages[zone] then local msg = bit.band(p['Message ID'], 16383) for i,v in pairs(messages[zone]) do @@ -214,9 +211,6 @@ windower.register_event('addon command',function(...) windower.send_command('lua u pointwatch') elseif first_cmd == 'reset' then initialize() - elseif first_cmd == 'message_printing' then - settings.options.message_printing = not settings.options.message_printing - print('Pointwatch: Message printing is '..tostring(settings.options.message_printing)..'.') elseif first_cmd == 'eval' then assert(loadstring(table.concat(commands, ' ')))() end diff --git a/addons/pointwatch/statics.lua b/addons/pointwatch/statics.lua index bf87bc2ea7..5afd4af9e0 100644 --- a/addons/pointwatch/statics.lua +++ b/addons/pointwatch/statics.lua @@ -60,10 +60,7 @@ default_settings = { green = 255, blue = 255 } - }, - options = { - message_printing = false, - }, + } } -- Approved textbox commands: From 5130c96c194a04e4ffa2eed285f0070e4d62d086 Mon Sep 17 00:00:00 2001 From: StarlitGhost <679547+StarlitGhost@users.noreply.github.com> Date: Tue, 24 May 2022 18:22:48 +0100 Subject: [PATCH 0836/1002] [gametime] fix //gt route I checked in Selbina and the arrival times are correct. https://cdn.discordapp.com/attachments/484050756169760788/978709336333361222/unknown.png --- addons/gametime/gametime.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/gametime/gametime.lua b/addons/gametime/gametime.lua index 9ea880138a..a62beee803 100644 --- a/addons/gametime/gametime.lua +++ b/addons/gametime/gametime.lua @@ -287,6 +287,7 @@ end windower.register_event('time change', function(new, old) gt.hours = (new / 60):floor() gt.minutes = new % 60 + gt.dectime = timeconvert(gt.hours..':'..gt.minutes) gt.gtt:update(gt) end) From 10e095689295afde806eeab984bcef91ff19a33a Mon Sep 17 00:00:00 2001 From: StarlitGhost <679547+StarlitGhost@users.noreply.github.com> Date: Tue, 24 May 2022 18:38:00 +0100 Subject: [PATCH 0837/1002] [gametime] bump version, add copyright date 2022 --- addons/gametime/gametime.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/gametime/gametime.lua b/addons/gametime/gametime.lua index a62beee803..6b9d4c2a03 100644 --- a/addons/gametime/gametime.lua +++ b/addons/gametime/gametime.lua @@ -1,4 +1,4 @@ --- Copyright © 2013-2016, Omnys of Valefor +-- Copyright © 2013-2016, 2022, Omnys of Valefor -- All rights reserved. -- Redistribution and use in source and binary forms, with or without @@ -26,7 +26,7 @@ _addon.name = 'gametime' _addon.author = 'Omnys' -_addon.version = '0.6' +_addon.version = '0.7' _addon.commands = {'gametime','gt'} require('chat') From a54a5c514c5a774d3d92106b9ea5267a8040eb3d Mon Sep 17 00:00:00 2001 From: vessellaj Date: Sat, 28 May 2022 21:11:42 -0400 Subject: [PATCH 0838/1002] Fix for player party member out-of-zone --- addons/Trusts/Trusts.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/Trusts/Trusts.lua b/addons/Trusts/Trusts.lua index 36d03527de..c35f66c36e 100644 --- a/addons/Trusts/Trusts.lua +++ b/addons/Trusts/Trusts.lua @@ -139,7 +139,7 @@ function check_exist() local get_party = windower.ffxi.get_party() for i=1,5 do local member = get_party['p'..i] - if member then + if member and member.mob then if member.mob.spawn_type == 14 then party[member.name] = member.mob.models[1] table.insert(party_ind,member.name) From 2de084daa3258d096cd1e496828fd85b927265ce Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Wed, 1 Jun 2022 19:23:12 -0600 Subject: [PATCH 0839/1002] DST time offset fix --- addons/Clock/Clock.lua | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/addons/Clock/Clock.lua b/addons/Clock/Clock.lua index 9a66f68374..b3ae51540a 100644 --- a/addons/Clock/Clock.lua +++ b/addons/Clock/Clock.lua @@ -62,7 +62,15 @@ config.register(settings, redraw) clock:show() -utc_diff = os.difftime(os.time(), os.time(os.date('!*t', os.time()))) +local function get_timezone_offset(ts) + ts = ts or os.time() + local utcdate = os.date("!*t", ts) + local localdate = os.date("*t", ts) + localdate.isdst = false -- this is the trick + return os.difftime(os.time(localdate), os.time(utcdate)) +end + +utc_diff = get_timezone_offset() windower.register_event('prerender', function() local utc_now = os.time() - utc_diff From 7e39d8e187f331c3a4a7cc0e794fcbe9cedf11de Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Thu, 2 Jun 2022 17:47:30 +0200 Subject: [PATCH 0840/1002] Fields: Refactored buff time calculation --- addons/libs/packets/fields.lua | 116 ++++++++++++++++----------------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 98525c1fe7..e89e7ccb8d 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -106,7 +106,7 @@ do end bufftime = function(ts) - return fn((ts / 60) + 572662306 + 1009810800) + return fn(1009810800 + (ts / 60) + 0x100000000 / 60 * 8) -- increment last number every 2.27 years end end @@ -398,7 +398,7 @@ fields.outgoing[0x029] = L{ fields.outgoing[0x02B] = L{ {ctype='unsigned char', label='Starting Language'}, -- 04 0 == JP, 1 == EN {ctype='unsigned char', label='Ending Language'}, -- 05 0 == JP, 1 == EN - {ctype='unsigned short', label='_unknown1', const=0x0000}, -- 06 + {ctype='unsigned short', label='_unknown1', const=0x0000}, -- 06 {ctype='char[64]', label='Phrase'}, -- 08 Quotation marks are removed. Phrase is truncated at 64 characters. } @@ -696,7 +696,7 @@ fields.outgoing[0x05C] = L{ -- Outgoing emote fields.outgoing[0x05D] = L{ {ctype='unsigned int', label='Target ID', fn=id}, -- 04 - {ctype='unsigned short', label='Target Index', fn=index}, -- 08 + {ctype='unsigned short', label='Target Index', fn=index}, -- 08 {ctype='unsigned char', label='Emote', fn=emote}, -- 0A {ctype='unsigned char', label='Type'}, -- 0B 2 for motion, 0 otherwise {ctype='unsigned int', label='_unknown1', const=0}, -- 0C @@ -760,7 +760,7 @@ fields.outgoing[0x070] = L{ -- Kick fields.outgoing[0x071] = L{ - {ctype='data[6]', label='_unknown1'}, -- 04 + {ctype='data[6]', label='_unknown1'}, -- 04 {ctype='unsigned char', label='Kick Type'}, -- 0A 0 for party, 1 for linkshell, 2 for alliance (maybe) {ctype='unsigned char', label='_unknown2'}, -- 0B {ctype='data[16]', label='Member Name'} -- 0C Null terminated string @@ -794,8 +794,8 @@ fields.outgoing[0x078] = L{ -- Guild NPC Buy -- Sent when buying an item from a guild NPC fields.outgoing[0x082] = L{ - {ctype='unsigned short', label='Item', fn=item}, -- 08 - {ctype='unsigned char', label='_unknown1', const=0x00}, -- 0A + {ctype='unsigned short', label='Item', fn=item}, -- 08 + {ctype='unsigned char', label='_unknown1', const=0x00}, -- 0A {ctype='unsigned char', label='Count'}, -- 0B Number you are buying } @@ -859,8 +859,8 @@ fields.outgoing[0x0A2] = L{ -- Guild Buy Item -- Sent when buying an item from a guild NPC fields.outgoing[0x0AA] = L{ - {ctype='unsigned short', label='Item', fn=item}, -- 04 - {ctype='unsigned char', label='_unknown1', const=0x00}, -- 06 + {ctype='unsigned short', label='Item', fn=item}, -- 04 + {ctype='unsigned char', label='_unknown1', const=0x00}, -- 06 {ctype='unsigned char', label='Count'}, -- 07 Number you are buying } @@ -872,8 +872,8 @@ fields.outgoing[0x0AB] = L{ -- Guild Sell Item -- Sent when selling an item to a guild NPC fields.outgoing[0x0AC] = L{ - {ctype='unsigned short', label='Item', fn=item}, -- 04 - {ctype='unsigned char', label='_unknown1'}, -- 06 + {ctype='unsigned short', label='Item', fn=item}, -- 04 + {ctype='unsigned char', label='_unknown1'}, -- 06 {ctype='unsigned char', label='Count'}, -- 07 Number you are selling } @@ -918,8 +918,8 @@ fields.outgoing[0x0C0] = L{ -- /makelinkshell fields.outgoing[0x0C3] = L{ - {ctype='unsigned char', label='_unknown1'}, -- 04 - {ctype='unsigned char', label='Linkshell Number'}, -- 05 + {ctype='unsigned char', label='_unknown1'}, -- 04 + {ctype='unsigned char', label='Linkshell Number'}, -- 05 {ctype='data[2]', label='_junk1'} -- 05 } @@ -1147,7 +1147,7 @@ fields.outgoing[0x10D] = L{ fields.outgoing[0x10E] = L{ {ctype='unsigned short', label='RoE Quest'}, -- 04 This field is likely actually 12 bits } - + -- Currency Menu fields.outgoing[0x10F] = L{ } @@ -1190,7 +1190,7 @@ fields.outgoing[0x115] = L{ -- Open Unity Menu :: Two of these are sent whenever I open my unity menu. The first one has a bool of 0 and the second of 1. fields.outgoing[0x116] = L{ {ctype='bool', label='_unknown1'}, -- 04 - {ctype='char[3]', label='_unknown2'}, -- 05 + {ctype='char[3]', label='_unknown2'}, -- 05 } -- Unity Ranking Results :: Sent when I open my Unity Ranking Results menu. Triggers a Sparks Update packet and may trigger ranking packets that I could not record. @@ -1201,7 +1201,7 @@ fields.outgoing[0x117] = L{ -- Open Chat status fields.outgoing[0x118] = L{ {ctype='bool', label='Chat Status'}, -- 04 0 for Inactive and 1 for Active - {ctype='char[3]', label='_unknown2'}, -- 05 + {ctype='char[3]', label='_unknown2'}, -- 05 } types.job_level = L{ @@ -1212,8 +1212,8 @@ types.job_level = L{ fields.incoming[0x00A] = L{ {ctype='unsigned int', label='Player', fn=id}, -- 04 {ctype='unsigned short', label='Player Index', fn=index}, -- 08 - {ctype='unsigned char', label='_padding'}, -- 0A - {ctype='unsigned char', label='Heading', fn=dir}, -- 0B -- 0B to + {ctype='unsigned char', label='_padding'}, -- 0A + {ctype='unsigned char', label='Heading', fn=dir}, -- 0B -- 0B to {ctype='float', label='X'}, -- 0C {ctype='float', label='Z'}, -- 10 {ctype='float', label='Y'}, -- 14 @@ -1344,7 +1344,7 @@ fields.incoming[0x00D] = L{ {ctype='unsigned int', label='Player', fn=id}, -- 04 {ctype='unsigned short', label='Index', fn=index}, -- 08 - {ctype='boolbit', label='Update Position'}, -- 0A:0 Position, Rotation, Target, Speed + {ctype='boolbit', label='Update Position'}, -- 0A:0 Position, Rotation, Target, Speed {ctype='boolbit', label='Update Status'}, -- 1A:1 Not used for 0x00D {ctype='boolbit', label='Update Vitals'}, -- 0A:2 HP%, Status, Flags, LS color, "Face Flags" {ctype='boolbit', label='Update Name'}, -- 0A:3 Name @@ -1369,7 +1369,7 @@ fields.incoming[0x00D] = L{ {ctype='unsigned char', label='Linkshell Green'}, -- 25 {ctype='unsigned char', label='Linkshell Blue'}, -- 26 {ctype='unsigned char', label='_flags1'}, -- 27 0x80 Autogroup flag - {ctype='unsigned char', label='_flags2'}, -- 28 0x01 puts your weapon on hand, 0x02 Request flag, + {ctype='unsigned char', label='_flags2'}, -- 28 0x01 puts your weapon on hand, 0x02 Request flag, {ctype='unsigned char', label='PvP Stuff'}, -- 29 Same pattern than incoming 0x037 packet {ctype='unsigned char', label='_flags3'}, -- 2A 0x20 Sneak Effect flag, 0x80 New Adventurer flag {ctype='unsigned char', label='_flags4'}, -- 2B 0x01 Mentor flag @@ -1890,8 +1890,8 @@ fields.incoming[0x029] = L{ --[[ 0x2A can also be triggered by spending cruor by buying non-vwnm related items, or even activating/using Flux Field1 will be the amount of cruor spent ]] - - + + --[[ 0x2A can also be triggered by zoning into Abyssea: Field1 will be set to your remaining time. 5 at first, then whatever new value when acquiring visiting status. 0x2A will likely be triggered as well when extending your time limit. Needs verification. @@ -1951,7 +1951,7 @@ fields.incoming[0x030] = L{ -- Synth List / Synth Recipe --[[ This packet is used for list of recipes, but also for details of a specific recipe. - If you ask the guild NPC that provides regular Image Suppor for recipes, + If you ask the guild NPC that provides regular Image Suppor for recipes, s/he will give you a list of recipes, fields are as follows: Field1-2: NPC ID Field3: NPC Index @@ -1961,13 +1961,13 @@ fields.incoming[0x030] = L{ Field24: Usually Item ID of the recipe on next page - If you ask a guild NPC for a specific recipe, fields are as follows: + If you ask a guild NPC for a specific recipe, fields are as follows: field1: item to make (item id) field2,3,4: sub-crafts needed. Note that main craft will not be listed. 1 = woodworking 2 = smithing 3 = goldsmithing - 4 = clothcraft + 4 = clothcraft 5 = leatherworking 6 = bonecraft 7 = Alchemy @@ -1976,10 +1976,10 @@ fields.incoming[0x030] = L{ field6: KeyItem needed, if any (in Big Endian) field7-14: material required (item id) field15-22: qty for each material above. - field23-24: Unknown + field23-24: Unknown ]] fields.incoming[0x031] = L{ - {ctype='unsigned short[24]', label='Field'}, -- 04 + {ctype='unsigned short[24]', label='Field'}, -- 04 } -- NPC Interaction Type 1 @@ -2010,7 +2010,7 @@ fields.incoming[0x033] = L{ -- NPC Interaction Type 2 fields.incoming[0x034] = L{ {ctype='unsigned int', label='NPC', fn=id}, -- 04 - {ctype='data[32]', label='Menu Parameters'}, -- 08 + {ctype='data[32]', label='Menu Parameters'}, -- 08 {ctype='unsigned short', label='NPC Index', fn=index}, -- 28 {ctype='unsigned short', label='Zone', fn=zone}, -- 2A {ctype='unsigned short', label='Menu ID'}, -- 2C Seems to select between menus within a zone @@ -2072,14 +2072,14 @@ enums.indi = { -- 0x2000 -- No obvious effect -- 0x4000 -- No obvious effect -- 0x8000 -- No obvious effect - + _flags2: -- 0x01 -- POL Icon :: Actually a flag, overrides everything else but does not affect name color -- 0x02 -- No obvious effect -- 0x04 -- Disconnection icon :: Actually a flag, overrides everything but POL Icon -- 0x08 -- No linkshell -- 0x0A -- No obvious effect - + -- 0x10 -- No linkshell -- 0x20 -- Trial account icon -- 0x40 -- Trial account icon @@ -2093,13 +2093,13 @@ enums.indi = { -- Bit 0x80 overpowers those bits -- Bit 0x80 combines with 0x04 and 0x02 to make SGM. -- These are basically flags, but they can be combined to mean different things sometimes. - + _flags3: -- 0x10 -- No obvious effect -- 0x20 -- Event mode? Can't activate the targeting cursor but can still spin the camera -- 0x40 -- No obvious effect -- 0x80 -- Invisible model - + _flags4: -- 0x02 -- No obvious effect -- 0x04 -- No obvious effect @@ -2108,16 +2108,16 @@ enums.indi = { -- 0x20 -- Bazaar icon -- 0x40 -- Event status again? Can't activate the targeting cursor but can move the camera. -- 0x80 -- No obvious effects - + _flags5: -- 0x01 -- No obvious effect -- 0x02 -- No obvious effect -- 0x04 -- Autoinvite icon - + _flags6: -- 0x08 -- Terror flag -- 0x10 -- No obvious effect - + PvP stuff: -- 0x0020 -- No obvious effect -- 0x0040 -- San d'Oria ballista flag @@ -2131,7 +2131,7 @@ enums.indi = { -- 0x0420 -- Pankration blue icon -- 0x0800 -- and I still don't D:< -- 0x1000 -- and I still don't D:< - + _flags7: -- 0x0020 -- No obvious effect -- 0x0040 -- Individually, this bit has no effect. When combined with 0x20, it prevents you from returning to a walking animation after you stop (sliding along the ground while bound) @@ -2146,8 +2146,8 @@ fields.incoming[0x037] = L{ {ctype='unsigned char[32]', label='Buff', fn=buff}, -- 04 {ctype='unsigned int', label='Player', fn=id}, -- 24 {ctype='unsigned short', label='_flags1'}, -- 28 Called "Flags" on the old dev wiki. Second byte might not be part of the flags, actually. - {ctype='unsigned char', label='HP %', fn=percent}, -- 2A - {ctype='bit[8]', label='_flags2'}, -- 2B + {ctype='unsigned char', label='HP %', fn=percent}, -- 2A + {ctype='bit[8]', label='_flags2'}, -- 2B {ctype='bit[12]', label='Movement Speed/2'}, -- 2C Player movement speed {ctype='bit[4]', label='_flags3'}, -- 2D {ctype='bit[9]', label='Yalms per step'}, -- 2E Determines how quickly your animation walks @@ -2156,7 +2156,7 @@ fields.incoming[0x037] = L{ {ctype='unsigned char', label='LS Color Red'}, -- 31 {ctype='unsigned char', label='LS Color Green'}, -- 32 {ctype='unsigned char', label='LS Color Blue'}, -- 33 - {ctype='bit[3]', label='_flags5'}, -- 34 + {ctype='bit[3]', label='_flags5'}, -- 34 {ctype='bit[16]', label='Pet Index', fn=index}, -- 34 From 0x08 of byte 0x34 to 0x04 of byte 0x36 {ctype='bit[2]', label='_flags6'}, -- 36 {ctype='bit[9]', label='PvP Stuff'}, -- 36 Ballista flags here also makes appear the score, but it is probably modified in a ballista specific packet. @@ -2176,7 +2176,7 @@ fields.incoming[0x037] = L{ {ctype='bit[7]', label='Indi Buff', fn=e+{'indi'}}, -- 58 {ctype='boolbit', label='Job Master Flag'}, -- 58 {ctype='unsigned char', label='Face Flags'}, -- 59 - {ctype='unsigned char', label='_unknown5'}, -- 5A + {ctype='unsigned char', label='_unknown5'}, -- 5A {ctype='unsigned char', label='Mount'}, -- 5B Related to Mounts, seems to be mount id + 1, except for chocobo. The value doesn't get zeroed after dismount {ctype='boolbit', label='Wardrobe 3'}, -- 5C {ctype='boolbit', label='Wardrobe 4'}, -- 5C @@ -2229,7 +2229,7 @@ types.shop_item = L{ {ctype='unsigned short', label='Item', fn=item}, -- 04 {ctype='unsigned short', label='Shop Slot'}, -- 08 {ctype='unsigned short', label='Craft Skill'}, -- 0A Zero on normal shops, has values that correlate to res\skills. - {ctype='unsigned short', label='Craft Rank'}, -- 0C Correlates to Rank able to purchase product from GuildNPC + {ctype='unsigned short', label='Craft Rank'}, -- 0C Correlates to Rank able to purchase product from GuildNPC } -- Shop @@ -2440,7 +2440,7 @@ func.incoming[0x04B].base = L{ {ctype='signed char', label='Delivery Slot'}, -- 06 This goes left to right and then drops down a row and left to right again. Value is 00 through 07 -- 01 if Type is 06, otherwise FF -- 06 Type always seems to come in a pair, this field is only 01 for the first packet - {ctype='signed char', label='_unknown2'}, -- 07 Always FF FF FF FF? + {ctype='signed char', label='_unknown2'}, -- 07 Always FF FF FF FF? {ctype='signed int', label='_unknown3', const=-1}, -- 0C When in a 0x0D/0x0E type, 01 grants request to open inbox/outbox. With FA you get "Please try again later" {ctype='signed char', label='_unknown4'}, -- 0D 02 and 03 observed {ctype='signed char', label='Packet Number'}, -- 0E FF FF observed @@ -2592,8 +2592,8 @@ func.incoming[0x04C][0x0D] = L{ func.incoming[0x04C][0x0E] = L{ {ctype='unsigned char', label='_unknown1'}, -- 05 {ctype='unsigned char', label='Buy Status', fn=e+{'buy stat'}}, -- 06 - {ctype='unsigned char', label='_unknown2'}, -- 07 - {ctype='unsigned int', label='Price', fn=gil}, -- 08 + {ctype='unsigned char', label='_unknown2'}, -- 07 + {ctype='unsigned int', label='Price', fn=gil}, -- 08 {ctype='unsigned short', label='Item ID', fn=item}, -- 0C {ctype='unsigned short', label='_unknown3'}, -- 0E {ctype='unsigned short', label='Count'}, -- 10 @@ -2758,7 +2758,7 @@ fields.incoming[0x056] = function (data, type) return (func.incoming[0x056][type or data and data:unpack('H',0x25)] or L{{ctype='data[32]', label='Quest Flags'}}) + func.incoming[0x056].type end -func.incoming[0x056].type = L{ +func.incoming[0x056].type = L{ {ctype='unsigned short',label='Type', fn=e+{'quest_mission_log'}} -- 24 } @@ -2827,7 +2827,7 @@ fields.incoming[0x058] = L{ -- Emote fields.incoming[0x05A] = L{ - {ctype='unsigned int', label='Player ID', fn=id}, -- 04 + {ctype='unsigned int', label='Player ID', fn=id}, -- 04 {ctype='unsigned int', label='Target ID', fn=id}, -- 08 {ctype='unsigned short', label='Player Index', fn=index}, -- 0C {ctype='unsigned short', label='Target Index', fn=index}, -- 0E @@ -2942,7 +2942,7 @@ fields.incoming[0x05E] = L{ {ctype='unsigned char', label="Days to tally"}, -- 8C Number of days to the next conquest tally {ctype='data[3]', label="_unknown4"}, -- 8D All Zeros, and changed nothing when 0xFF'd. {ctype='int', label='Conquest Points'}, -- 90 - {ctype='unsigned char', label="Beastmen region bar"}, -- 94 + {ctype='unsigned char', label="Beastmen region bar"}, -- 94 {ctype='data[12]', label="_unknown5"}, -- 95 Mostly zeros and noticed no change when 0xFF'd. -- These bytes are for the overview summary on the map. @@ -3013,15 +3013,15 @@ fields.incoming[0x061] = L{ {ctype='unsigned short', label='_unknown2'}, -- 4E {ctype='unsigned char', label='Nation'}, -- 50 0 = sandy, 1 = bastok, 2 = windy {ctype='unsigned char', label='_unknown3'}, -- 51 Possibly Unity ID (always 7 for me, I'm in Aldo's unity) - {ctype='unsigned char', label='Su Level'}, -- 52 + {ctype='unsigned char', label='Su Level'}, -- 52 {ctype='unsigned char', label='_unknown4'}, -- 53 Always 00 for me - {ctype='unsigned char', label='Maximum iLevel'}, -- 54 + {ctype='unsigned char', label='Maximum iLevel'}, -- 54 {ctype='unsigned char', label='iLevel over 99'}, -- 55 0x10 would be an iLevel of 115 - {ctype='unsigned char', label='Main Hand iLevel'}, -- 56 + {ctype='unsigned char', label='Main Hand iLevel'}, -- 56 {ctype='unsigned char', label='_unknown5'}, -- 57 Always 00 for me {ctype='bit[5]', label='Unity ID'}, -- 58 0=None, 1=Pieuje, 2=Ayame, 3=Invincible Shield, 4=Apururu, 5=Maat, 6=Aldo, 7=Jakoh Wahcondalo, 8=Naja Salaheem, 9=Flavira {ctype='bit[5]', label='Unity Rank'}, -- 58 Danger, 00ing caused my client to crash - {ctype='bit[17]', label='Unity Points'}, -- 59 + {ctype='bit[17]', label='Unity Points'}, -- 59 {ctype='bit[5]', label='_unknown6'}, -- 5A No obvious function {ctype='unsigned int', label='_junk1'}, -- 5C {ctype='unsigned int', label='_junk2'}, -- 60 @@ -3289,7 +3289,7 @@ fields.incoming[0x079] = L{ -- Guild Buy Response -- Sent when buying an item from a guild NPC fields.incoming[0x082] = L{ - {ctype='unsigned short', label='Item', fn=item}, -- 08 + {ctype='unsigned short', label='Item', fn=item}, -- 08 {ctype='unsigned char', label='_junk1'}, -- 0A No obvious purpose {ctype='unsigned char', label='Count'}, -- 0B Number you bought } @@ -3305,14 +3305,14 @@ fields.incoming[0x083] = L{ {ref=types.guild_entry, label='Item', count='30'}, -- 04 {ctype='unsigned char', label='Item Count'}, -- F4 {ctype='bit[4]', label='Order'}, -- F5 - {ctype='bit[4]', label='_unknown'}, + {ctype='bit[4]', label='_unknown'}, {ctype='unsigned short', label='_padding'} -- F6 } -- Guild Sell Response -- Sent when selling an item to a guild NPC fields.incoming[0x084] = L{ - {ctype='unsigned short', label='Item', fn=item}, -- 08 + {ctype='unsigned short', label='Item', fn=item}, -- 08 {ctype='unsigned char', label='_junk1'}, -- 0A No obvious purpose {ctype='unsigned char', label='Count'}, -- 0B Number you bought. If 0, the transaction failed. } @@ -3322,7 +3322,7 @@ fields.incoming[0x085] = L{ {ref=types.guild_entry, label='Item', count='30'}, -- 04 {ctype='unsigned char', label='Item Count'}, -- F4 {ctype='bit[4]', label='Order'}, -- F5 - {ctype='bit[4]', label='_unknown'}, + {ctype='bit[4]', label='_unknown'}, {ctype='unsigned short', label='_padding'} -- F6 } -- Guild Open @@ -3457,10 +3457,10 @@ func.incoming[0x0C9][0x01] = L{ {ctype='unsigned char', label='Icon Set Subtype'}, -- 0E 0 = Unopened Linkshell?, 1 = Linkshell, 2 = Pearlsack, 3 = Linkpearl, 4 = Ripped Pearlsack (I think), 5 = Broken Linkpearl? {ctype='unsigned char', label='Icon Set ID'}, -- 0F This identifies the icon set, always 2 for linkshells. {ctype='data[16]', label='Linkshell', enc=ls_enc}, -- 10 6-bit packed - {ctype='bit[4]', label='_junk1'}, -- 20 + {ctype='bit[4]', label='_junk1'}, -- 20 {ctype='bit[4]', label='Linkshell Red'}, -- 20 0xGR, 0x-B - {ctype='bit[4]', label='Linkshell Green'}, -- 21 - {ctype='bit[4]', label='Linkshell Blue'}, -- 21 + {ctype='bit[4]', label='Linkshell Green'}, -- 21 + {ctype='bit[4]', label='Linkshell Blue'}, -- 21 {ctype='unsigned char', label='_unknown1'}, -- 22 {ctype='unsigned char', label='Sub Job', fn=job}, -- 23 {ctype='unsigned char', label='Main Job Level'}, -- 24 @@ -3476,7 +3476,7 @@ func.incoming[0x0C9][0x01] = L{ fields.incoming[0x0CA] = L{ {ctype='char[124]', label='Bazaar Message'}, -- 04 Terminated with a vertical tab {ctype='char[16]', label='Player Name'}, -- 80 - {ctype='unsigned short', label='Player Title ID'}, -- 90 + {ctype='unsigned short', label='Player Title ID'}, -- 90 {ctype='unsigned short', label='_unknown4'}, -- 92 00 00 observed. } From a36eadd1c7ab55a06e5d50828940fd29a88a1fde Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Thu, 2 Jun 2022 17:47:52 +0200 Subject: [PATCH 0841/1002] Fields: Incremented year count for buff time calculation --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index e89e7ccb8d..0d14bbe579 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -106,7 +106,7 @@ do end bufftime = function(ts) - return fn(1009810800 + (ts / 60) + 0x100000000 / 60 * 8) -- increment last number every 2.27 years + return fn(1009810800 + (ts / 60) + 0x100000000 / 60 * 9) -- increment last number every 2.27 years end end From 15de26264fa59ca5d9b64559f3342bba1748cc72 Mon Sep 17 00:00:00 2001 From: Byrth Date: Sun, 12 Jun 2022 09:04:37 -0400 Subject: [PATCH 0842/1002] Add items for June 2022 Update --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 860e12930d..d3e427c7ed 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757, 25909}, -- 192 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049}, -- 151 SE Skipped an index hence the 0 as one of the items + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, }, -- 155 SE Skipped an index hence the 0 as one of the items [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067, 21680, 22071}, --177 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, --115 From fe39145d5fd2571ff17127ddd3eec3ef0dd34b5a Mon Sep 17 00:00:00 2001 From: Algelius <62651753+Algelius@users.noreply.github.com> Date: Wed, 15 Jun 2022 03:45:29 +0200 Subject: [PATCH 0843/1002] Update Yush.lua Added DIKs for f13-f15. --- addons/Yush/Yush.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/addons/Yush/Yush.lua b/addons/Yush/Yush.lua index 0bee580f96..2668c4f80f 100644 --- a/addons/Yush/Yush.lua +++ b/addons/Yush/Yush.lua @@ -271,7 +271,11 @@ dikt = { -- Har har [80] = 'num2', [81] = 'num3', [82] = 'num0', - + + [100] = 'f13', + [101] = 'f14', + [102] = 'f15', + [199] = 'home', [200] = 'up', [201] = 'pageup', From 6bc9be28b85b337234c0a74e603b7f16c3cf4f4a Mon Sep 17 00:00:00 2001 From: Algelius <62651753+Algelius@users.noreply.github.com> Date: Wed, 15 Jun 2022 04:02:36 +0200 Subject: [PATCH 0844/1002] Update Yush.lua --- addons/Yush/Yush.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/Yush/Yush.lua b/addons/Yush/Yush.lua index 2668c4f80f..83e777e0d6 100644 --- a/addons/Yush/Yush.lua +++ b/addons/Yush/Yush.lua @@ -272,9 +272,9 @@ dikt = { -- Har har [81] = 'num3', [82] = 'num0', - [100] = 'f13', + [100] = 'f13', [101] = 'f14', - [102] = 'f15', + [102] = 'f15', [199] = 'home', [200] = 'up', From 2762180d3fdc15aa423c33dd470e327e0f57b7cd Mon Sep 17 00:00:00 2001 From: Algelius <62651753+Algelius@users.noreply.github.com> Date: Wed, 15 Jun 2022 04:14:48 +0200 Subject: [PATCH 0845/1002] Update Yush.lua DIKs for f11 & f12 --- addons/Yush/Yush.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addons/Yush/Yush.lua b/addons/Yush/Yush.lua index 83e777e0d6..2797b207d9 100644 --- a/addons/Yush/Yush.lua +++ b/addons/Yush/Yush.lua @@ -272,6 +272,9 @@ dikt = { -- Har har [81] = 'num3', [82] = 'num0', + [87] = 'f11', + [88] = 'f12', + [100] = 'f13', [101] = 'f14', [102] = 'f15', From efe0f62b0f5f1c158d9e1ca0ef38554315dec85d Mon Sep 17 00:00:00 2001 From: Joe Vessella Date: Mon, 20 Jun 2022 16:04:11 -0400 Subject: [PATCH 0846/1002] Added VerboseKeys setting. --- addons/Yush/ReadMe.md | 4 ++++ addons/Yush/Yush.lua | 22 +++++++++++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/addons/Yush/ReadMe.md b/addons/Yush/ReadMe.md index 3a2818ab20..3022167e24 100644 --- a/addons/Yush/ReadMe.md +++ b/addons/Yush/ReadMe.md @@ -29,6 +29,10 @@ The key which resets the current macro set to the previous set. If true, will display the current macro set you are in. The name it displays is the same name it has in the file it loads. +**VerboseKeys** + +If true, will append the list of keybinds for the current macro set. + **VerboseOutput** Determines where the current macro set will be displayed (only effective if the *Verbose* setting is `true`). The following options are available: diff --git a/addons/Yush/Yush.lua b/addons/Yush/Yush.lua index 2797b207d9..9d866d9a80 100644 --- a/addons/Yush/Yush.lua +++ b/addons/Yush/Yush.lua @@ -59,6 +59,7 @@ defaults.ResetKey = '`' defaults.BackKey = 'backspace' defaults.Verbose = false defaults.VerboseOutput = 'Text' +defaults.VerboseKeys = false defaults.Label = {} settings = config.load(defaults) @@ -67,6 +68,7 @@ label = texts.new(settings.Label, settings) binds = {} names = {} +key_combos = {} current = binds stack = L{binds} keys = S{} @@ -75,12 +77,24 @@ output = function() if settings.Verbose then names[current] = names[current] or 'Unnamed ' .. tostring(current):sub(8) + output_text_table = {} + table.insert(output_text_table, names[current]) + if settings.VerboseKeys then + for key, val in pairs(current) do + if type(val) ~= 'string' then + val = names[val] or 'Unnamed' + end + table.insert(output_text_table, key_combos[key] .. ': ' .. val) + end + end + local output_text = table.concat(output_text_table, '\n') + if settings.VerboseOutput == 'Text' then - label:text(names[current]) + label:text(output_text) elseif settings.VerboseOutput == 'Chat' then - log('Changing into macro set %s.':format(names[current])) + log('Changing into macro set %s.':format(output_text)) elseif settings.VerboseOutput == 'Console' then - print('Changing into macro set %s.':format(names[current])) + print('Changing into macro set %s.':format(output_text)) end end end @@ -127,7 +141,9 @@ parse_binds = function(fbinds, top) rawset(names, top, rawget(_innerG._names, fbinds)) for key, val in pairs(fbinds) do + key_combo = key key = S(key:split('+')):map(string.lower) + rawset(key_combos, key, key_combo) if type(val) == 'string' or type(val) == 'function' then rawset(top, key, val) else From b240a1e14bd1c6e57a4296e82797242f9cb92c0d Mon Sep 17 00:00:00 2001 From: Joe Vessella Date: Mon, 20 Jun 2022 16:25:46 -0400 Subject: [PATCH 0847/1002] Wording update. --- addons/Yush/ReadMe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/Yush/ReadMe.md b/addons/Yush/ReadMe.md index 3022167e24..2e0adec1e5 100644 --- a/addons/Yush/ReadMe.md +++ b/addons/Yush/ReadMe.md @@ -31,7 +31,7 @@ If true, will display the current macro set you are in. The name it displays is **VerboseKeys** -If true, will append the list of keybinds for the current macro set. +If true, will append the list of keybinds for the current macro set (only effective if the *Verbose* setting is `true`). **VerboseOutput** From 7bce71c2bcefad82ba93c26120862a89dec778f3 Mon Sep 17 00:00:00 2001 From: Joe Vessella Date: Mon, 20 Jun 2022 18:04:33 -0400 Subject: [PATCH 0848/1002] Removed table identifier. --- addons/Yush/Yush.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/Yush/Yush.lua b/addons/Yush/Yush.lua index 9d866d9a80..544a174cf9 100644 --- a/addons/Yush/Yush.lua +++ b/addons/Yush/Yush.lua @@ -75,7 +75,7 @@ keys = S{} output = function() if settings.Verbose then - names[current] = names[current] or 'Unnamed ' .. tostring(current):sub(8) + names[current] = names[current] or 'Unnamed' output_text_table = {} table.insert(output_text_table, names[current]) From fa2139c02748a9b52a5da05af9f6bbb6deac2991 Mon Sep 17 00:00:00 2001 From: Joe Vessella Date: Mon, 20 Jun 2022 18:07:13 -0400 Subject: [PATCH 0849/1002] parse_binds no longer reassigns key. --- addons/Yush/Yush.lua | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/addons/Yush/Yush.lua b/addons/Yush/Yush.lua index 544a174cf9..15152a315a 100644 --- a/addons/Yush/Yush.lua +++ b/addons/Yush/Yush.lua @@ -141,14 +141,13 @@ parse_binds = function(fbinds, top) rawset(names, top, rawget(_innerG._names, fbinds)) for key, val in pairs(fbinds) do - key_combo = key - key = S(key:split('+')):map(string.lower) - rawset(key_combos, key, key_combo) + local split_key = S(key:split('+')):map(string.lower) + rawset(key_combos, split_key, key) if type(val) == 'string' or type(val) == 'function' then - rawset(top, key, val) + rawset(top, split_key, val) else local sub = {} - rawset(top, key, sub) + rawset(top, split_key, sub) parse_binds(val, sub) end end From 4d657abf7596a601c9386bf5b4cac106144d981d Mon Sep 17 00:00:00 2001 From: Joe Vessella Date: Mon, 20 Jun 2022 18:09:43 -0400 Subject: [PATCH 0850/1002] output_text_table renamed, made list, and output text updated. --- addons/Yush/Yush.lua | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/addons/Yush/Yush.lua b/addons/Yush/Yush.lua index 15152a315a..92853f22be 100644 --- a/addons/Yush/Yush.lua +++ b/addons/Yush/Yush.lua @@ -77,24 +77,23 @@ output = function() if settings.Verbose then names[current] = names[current] or 'Unnamed' - output_text_table = {} - table.insert(output_text_table, names[current]) + local output_text_names = L{} + output_text_names:append(names[current]) if settings.VerboseKeys then for key, val in pairs(current) do if type(val) ~= 'string' then val = names[val] or 'Unnamed' end - table.insert(output_text_table, key_combos[key] .. ': ' .. val) + output_text_names:append(key_combos[key] .. ': ' .. val) end end - local output_text = table.concat(output_text_table, '\n') if settings.VerboseOutput == 'Text' then - label:text(output_text) + label:text(output_text_names:concat('\n')) elseif settings.VerboseOutput == 'Chat' then - log('Changing into macro set %s.':format(output_text)) + log('Changing into macro set %s.':format(output_text_names:concat(' | '))) elseif settings.VerboseOutput == 'Console' then - print('Changing into macro set %s.':format(output_text)) + print('Changing into macro set %s.':format(output_text_names:concat(' | '))) end end end From 18413aab817c853b19952a8ff775540b801a8fa0 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Sun, 26 Jun 2022 12:54:14 -0600 Subject: [PATCH 0851/1002] [tables] add table.pack --- addons/libs/tables.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/addons/libs/tables.lua b/addons/libs/tables.lua index 8a654c2c7e..644b33cb26 100644 --- a/addons/libs/tables.lua +++ b/addons/libs/tables.lua @@ -474,6 +474,10 @@ function table.unpack(t, ...) return unpack(temp) end +function table.pack(...) + return {...} +end + -- Returns the values of the table, extracted into an argument list. Like unpack, but works on dictionaries as well. function table.extract(t) local res = {} From 0491d6dee606d4770b363f751bd5ce65f94d1b5c Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Sun, 26 Jun 2022 17:51:54 -0600 Subject: [PATCH 0852/1002] [Gearswap][Motes-Mappings] Ltng. Threnody There is no spell called "Lightning Threnody" --- addons/GearSwap/libs/Mote-Mappings.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/GearSwap/libs/Mote-Mappings.lua b/addons/GearSwap/libs/Mote-Mappings.lua index 47e8b06b81..d3fc055688 100644 --- a/addons/GearSwap/libs/Mote-Mappings.lua +++ b/addons/GearSwap/libs/Mote-Mappings.lua @@ -179,8 +179,8 @@ spell_maps = { ['Fire Carol']='Carol',['Ice Carol']='Carol',['Wind Carol']='Carol',['Earth Carol']='Carol',['Lightning Carol']='Carol',['Water Carol']='Carol',['Light Carol']='Carol',['Dark Carol']='Carol', ['Fire Carol II']='Carol',['Ice Carol II']='Carol',['Wind Carol II']='Carol',['Earth Carol II']='Carol',['Lightning Carol II']='Carol',['Water Carol II']='Carol',['Light Carol II']='Carol',['Dark Carol II']='Carol', ['Foe Lullaby']='Lullaby',['Foe Lullaby II']='Lullaby',['Horde Lullaby']='Lullaby',['Horde Lullaby II']='Lullaby', - ['Fire Threnody']='Threnody',['Ice Threnody']='Threnody',['Wind Threnody']='Threnody',['Earth Threnody']='Threnody',['Lightning Threnody']='Threnody',['Water Threnody']='Threnody',['Light Threnody']='Threnody',['Dark Threnody']='Threnody', - ['Fire Threnody II']='Threnody',['Ice Threnody II']='Threnody',['Wind Threnody II']='Threnody',['Earth Threnody II']='Threnody',['Lightning Threnody II']='Threnody',['Water Threnody II']='Threnody',['Light Threnody II']='Threnody',['Dark Threnody II']='Threnody', + ['Fire Threnody']='Threnody',['Ice Threnody']='Threnody',['Wind Threnody']='Threnody',['Earth Threnody']='Threnody',['Ltng. Threnody']='Threnody',['Water Threnody']='Threnody',['Light Threnody']='Threnody',['Dark Threnody']='Threnody', + ['Fire Threnody II']='Threnody',['Ice Threnody II']='Threnody',['Wind Threnody II']='Threnody',['Earth Threnody II']='Threnody',['Ltng. Threnody II']='Threnody',['Water Threnody II']='Threnody',['Light Threnody II']='Threnody',['Dark Threnody II']='Threnody', ['Battlefield Elegy']='Elegy',['Carnage Elegy']='Elegy', ['Foe Requiem']='Requiem',['Foe Requiem II']='Requiem',['Foe Requiem III']='Requiem',['Foe Requiem IV']='Requiem',['Foe Requiem V']='Requiem',['Foe Requiem VI']='Requiem',['Foe Requiem VII']='Requiem', ['Utsusemi: Ichi']='Utsusemi',['Utsusemi: Ni']='Utsusemi',['Utsusemi: San']='Utsusemi', From c3d811dc8e5ced3a2edd8916c7cad499d4f926b7 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Tue, 28 Jun 2022 03:38:39 +0200 Subject: [PATCH 0853/1002] [fields lib] fix wrong 0x0E8 packet direction 0x0E8 is an outgoing packet. --- addons/libs/packets/fields.lua | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 0d14bbe579..8e03082b9e 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -986,6 +986,14 @@ fields.outgoing[0x0E7] = L{ {ctype='unsigned char', label='_unknown3'}, -- 07 Observed to be 00 } +-- Toggle Heal +fields.outgoing[0x0E8] = L{ + {ctype='unsigned char', label='Movement'}, -- 04 02 if caused by movement + {ctype='unsigned char', label='_unknown2'}, -- 05 00 observed + {ctype='unsigned char', label='_unknown3'}, -- 06 00 observed + {ctype='unsigned char', label='_unknown4'}, -- 07 00 observed +} + -- Sit fields.outgoing[0x0EA] = L{ {ctype='unsigned char', label='Movement'}, -- 04 @@ -3623,14 +3631,6 @@ fields.incoming[0x0E2] = L{ {ctype='char*', label='Name'}, -- 22 * Maybe a base stat } --- Toggle Heal -fields.incoming[0x0E8] = L{ - {ctype='unsigned char', label='Movement'}, -- 04 02 if caused by movement - {ctype='unsigned char', label='_unknown2'}, -- 05 00 observed - {ctype='unsigned char', label='_unknown3'}, -- 06 00 observed - {ctype='unsigned char', label='_unknown4'}, -- 07 00 observed -} - -- Widescan Mob fields.incoming[0x0F4] = L{ {ctype='unsigned short', label='Index', fn=index}, -- 04 From 6e4caf6d48a742d25492bcd1b9364fe6d38ebc75 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Sun, 3 Jul 2022 15:28:50 +0200 Subject: [PATCH 0854/1002] Packets/Fields: Updated outgoing 0x061 length --- addons/libs/packets/fields.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 8e03082b9e..954b10cda7 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -716,8 +716,9 @@ fields.outgoing[0x05E] = L{ {ctype='unsigned char', label='Type'}, -- 17 03 for leaving the MH, 00 otherwise } --- Equipment Screen (0x02 length) -- Also observed when zoning +-- Equipment Screen, also observed when zoning fields.outgoing[0x061] = L{ + {ctype='data[4]', label='_unknown1'}, -- 04 Always zero? } -- Digging Finished From 3e7fb71f439fd2f59e06dc530c4638e8e6fa1722 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Fri, 8 Jul 2022 02:10:22 +0200 Subject: [PATCH 0855/1002] [Slips lib] Update for June 2022 Added items to slips libs for the 10 June, 2022 FFXI Update. --- addons/libs/slips.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index d3e427c7ed..dce16aa0f8 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -15,7 +15,7 @@ slips.storages = L{29312, 29313, 29314, 29315, 29316, 29317, 29318, 2931 slips.items = { [slips.storages[1]] = L{16084, 14546, 14961, 15625, 15711, 16085, 14547, 14962, 15626, 15712, 16086, 14548, 14963, 15627, 15713, 16087, 14549, 14964, 15628, 15714, 16088, 14550, 14965, 15629, 15715, 16089, 14551, 14966, 15630, 15716, 16090, 14552, 14967, 15631, 15717, 16091, 14553, 14968, 15632, 15718, 16092, 14554, 14969, 15633, 15719, 16093, 14555, 14970, 15634, 15720, 16094, 14556, 14971, 15635, 15721, 16095, 14557, 14972, 15636, 15722, 16096, 14558, 14973, 15637, 15723, 16097, 14559, 14974, 15638, 15724, 16098, 14560, 14975, 15639, 15725, 16099, 14561, 14976, 15640, 15726, 16100, 14562, 14977, 15641, 15727, 16101, 14563, 14978, 15642, 15728, 16102, 14564, 14979, 15643, 15729, 16103, 14565, 14980, 15644, 15730, 16106, 14568, 14983, 15647, 15733, 16107, 14569, 14984, 15648, 15734, 16108, 14570, 14985, 15649, 15735, 16602, 17741, 18425, 18491, 18588, 18717, 18718, 18850, 18943, 16069, 14530, 14940, 15609, 15695, 16062, 14525, 14933, 15604, 15688, 16064, 14527, 14935, 15606, 15690, 18685, 18065, 17851, 18686, 18025, 18435, 18113, 17951, 17715, 18485, 18408, 18365, 18583, 18417, 18388, 16267, 16268, 16269, 16228, 16229, 15911, 15799, 15800, 15990, 17745, 18121, 16117, 14577, 17857}, -- 168 [slips.storages[2]] = L{12421, 12549, 12677, 12805, 12933, 13911, 14370, 14061, 14283, 14163, 12429, 12557, 12685, 12813, 12941, 13924, 14371, 14816, 14296, 14175, 13934, 14387, 14821, 14303, 14184, 13935, 14388, 14822, 14304, 14185, 13876, 13787, 14006, 14247, 14123, 13877, 13788, 14007, 14248, 14124, 13908, 14367, 14058, 14280, 14160, 13909, 14368, 14059, 14281, 14161, 16113, 14573, 14995, 15655, 15740, 16115, 14575, 14997, 15657, 15742, 16114, 14574, 14996, 15656, 15741, 16116, 14576, 14998, 15658, 15743, 12818, 18198, 12946, 18043, 12690, 17659, 12296, 12434, 15471, 15472, 15473, 15508, 15509, 15510, 15511, 15512, 15513, 15514, 17710, 17595, 18397, 18360, 18222, 17948, 18100, 15475, 15476, 15477, 15488, 15961, 14815, 14812, 14813, 15244, 15240, 14488, 14905, 15576, 15661, 15241, 14489, 14906, 15577, 15662, 13927, 14378, 14076, 14308, 14180, 13928, 14379, 14077, 14309, 14181, 10438, 10276, 10320, 10326, 10367, 10439, 10277, 10321, 10327, 10368, 10440, 10278, 10322, 10328, 10369, 10441, 10279, 10323, 10329, 10370, 25734, 25735, 25736, 25737, 25738, 25739, 25740, 25741, 25742, 25743, 25744}, -- 155 - [slips.storages[3]] = L{16155, 11282, 15021, 16341, 11376, 16156, 11283, 15022, 16342, 11377, 16157, 11284, 15023, 16343, 11378, 16148, 14590, 15011, 16317, 15757, 16143, 14591, 15012, 16318, 15758, 16146, 14588, 15009, 16315, 15755, 16147, 14589, 15010, 16316, 15756, 15966, 15967, 19041, 17684, 17685, 11636, 15844, 15934, 16258, 18735, 18734, 16291, 16292, 19042, 15935, 16293, 16294, 15936, 18618, 11588, 11545, 16158, 16159, 16160, 16149, 14583, 15007, 16314, 15751, 16141, 14581, 15005, 16312, 15749, 16142, 14582, 15006, 16313, 15750, 10876, 10450, 10500, 11969, 10600, 10877, 10451, 10501, 11970, 10601, 10878, 10452, 10502, 11971, 10602, 19132, 18551, 11798, 11362, 11363, 11625, 15959, 16259, 22299, 26414, 21623, 26219, 21886, 23792, 23793, 23794, 23795, 23796, 22032, 22043, 21530, 22044, 26273, 25415, 25416, 25414}, -- 115 + [slips.storages[3]] = L{16155, 11282, 15021, 16341, 11376, 16156, 11283, 15022, 16342, 11377, 16157, 11284, 15023, 16343, 11378, 16148, 14590, 15011, 16317, 15757, 16143, 14591, 15012, 16318, 15758, 16146, 14588, 15009, 16315, 15755, 16147, 14589, 15010, 16316, 15756, 15966, 15967, 19041, 17684, 17685, 11636, 15844, 15934, 16258, 18735, 18734, 16291, 16292, 19042, 15935, 16293, 16294, 15936, 18618, 11588, 11545, 16158, 16159, 16160, 16149, 14583, 15007, 16314, 15751, 16141, 14581, 15005, 16312, 15749, 16142, 14582, 15006, 16313, 15750, 10876, 10450, 10500, 11969, 10600, 10877, 10451, 10501, 11970, 10601, 10878, 10452, 10502, 11971, 10602, 19132, 18551, 11798, 11362, 11363, 11625, 15959, 16259, 22299, 26414, 21623, 26219, 21886, 23792, 23793, 23794, 23795, 23796, 22032, 22043, 21530, 22044, 26273, 25415, 25416, 25414, 22050}, -- 116 [slips.storages[4]] = L{12511, 12638, 13961, 14214, 14089, 12512, 12639, 13962, 14215, 14090, 13855, 12640, 13963, 14216, 14091, 13856, 12641, 13964, 14217, 14092, 12513, 12642, 13965, 14218, 14093, 12514, 12643, 13966, 14219, 14094, 12515, 12644, 13967, 14220, 14095, 12516, 12645, 13968, 14221, 14096, 12517, 12646, 13969, 14222, 14097, 13857, 12647, 13970, 14223, 14098, 12518, 12648, 13971, 14099, 14224, 13868, 13781, 13972, 14225, 14100, 13869, 13782, 13973, 14226, 14101, 12519, 12649, 13974, 14227, 14102, 12520, 12650, 13975, 14228, 14103, 15265, 14521, 14928, 15600, 15684, 15266, 14522, 14929, 15601, 15685, 15267, 14523, 14930, 15602, 15686, 16138, 14578, 15002, 15659, 15746, 16139, 14579, 15003, 15660, 15747, 16140, 14580, 15004, 16311, 15748, 16678, 17478, 17422, 17423, 16829, 16764, 17643, 16798, 16680, 16766, 17188, 17812, 17771, 17772, 16887, 17532, 17717, 18702, 17858, 19203, 21461, 21124, 20776, 27786, 27926, 28066, 28206, 28346, 27787, 27927, 28067, 28207, 28347}, -- 138 [slips.storages[5]] = L{15225, 14473, 14890, 15561, 15352, 15226, 14474, 14891, 15562, 15353, 15227, 14475, 14892, 15563, 15354, 15228, 14476, 14893, 15564, 15355, 15229, 14477, 14894, 15565, 15356, 15230, 14478, 14895, 15566, 15357, 15231, 14479, 14896, 15567, 15358, 15232, 14480, 14897, 15568, 15359, 15233, 14481, 14898, 15569, 15360, 15234, 14482, 14899, 15570, 15361, 15235, 14483, 14900, 15362, 15571, 15236, 14484, 14901, 15572, 15363, 15237, 14485, 14902, 15573, 15364, 15238, 14486, 14903, 15574, 15365, 15239, 14487, 14904, 15575, 15366, 11464, 11291, 15024, 16345, 11381, 11467, 11294, 15027, 16348, 11384, 11470, 11297, 15030, 16351, 11387, 11475, 11302, 15035, 16357, 11393, 11476, 11303, 15036, 16358, 11394, 11477, 11304, 15037, 16359, 11395}, -- 105 [slips.storages[6]] = L{15072, 15087, 15102, 15117, 15132, 15871, 15073, 15088, 15103, 15118, 15133, 15478, 15074, 15089, 15104, 15119, 15134, 15872, 15075, 15090, 15105, 15120, 15135, 15874, 15076, 15091, 15106, 15121, 15136, 15873, 15077, 15092, 15107, 15122, 15137, 15480, 15078, 15093, 15108, 15123, 15138, 15481, 15079, 15094, 15109, 15124, 15139, 15479, 15080, 15095, 15110, 15125, 15140, 15875, 15081, 15096, 15111, 15126, 15141, 15482, 15082, 15097, 15112, 15127, 15142, 15876, 15083, 15098, 15113, 15128, 15143, 15879, 15084, 15099, 15114, 15129, 15144, 15877, 15085, 15100, 15115, 15130, 15145, 15878, 15086, 15101, 15116, 15131, 15146, 15484, 11465, 11292, 15025, 16346, 11382, 16244, 11468, 11295, 15028, 16349, 11385, 15920, 11471, 11298, 15031, 16352, 11388, 16245, 11478, 11305, 15038, 16360, 11396, 16248, 11480, 11307, 15040, 16362, 11398, 15925}, -- 120 @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757, 25909}, -- 192 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, }, -- 155 SE Skipped an index hence the 0 as one of the items + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052}, -- 155 SE Skipped an index hence the 0 as one of the items [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067, 21680, 22071}, --177 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, --115 From 4a42b90ca967c8eafdf33795dac15e953256280a Mon Sep 17 00:00:00 2001 From: Roland-J <107378114+Roland-J@users.noreply.github.com> Date: Fri, 8 Jul 2022 12:42:00 -0500 Subject: [PATCH 0856/1002] Adds the texts:draggable() function Allows users to toggle the draggable flag post-creation. Previously, this flag could only be passed in with the config in a images.new(config). --- addons/libs/texts.lua | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/addons/libs/texts.lua b/addons/libs/texts.lua index 2213e06d58..d040b63804 100644 --- a/addons/libs/texts.lua +++ b/addons/libs/texts.lua @@ -573,6 +573,14 @@ function texts.stroke_alpha(t, alpha) meta[t].settings.text.stroke.alpha = alpha end +function texts.draggable(t, draggable) + if draggable == nil then + return meta[t].settings.flags.draggable + end + + meta[t].settings.flags.draggable = draggable +end + -- Returns true if the coordinates are currently over the text object function texts.hover(t, x, y) if not t:visible() then From 019e6087b90fa217e31fd49a4c46c8f71ca46215 Mon Sep 17 00:00:00 2001 From: eLii Date: Sat, 9 Jul 2022 14:08:45 -0500 Subject: [PATCH 0857/1002] Update fields.lua Added Current TVR Mission. --- addons/libs/packets/fields.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 954b10cda7..0d131e94cb 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2752,6 +2752,7 @@ enums.quest_mission_log = { [0x00F8] = 'Completed Adoulin Quests', [0x0100] = 'Current Coalition Quests', [0x0108] = 'Completed Coalition Quests', + [0xFFFE] = 'Current TVR Missions', [0xFFFF] = 'Current Missions', } @@ -2797,6 +2798,11 @@ func.incoming[0x056][0x00D8] = L{ {ctype='data[16]', label='_junk'}, -- 14 } +func.incoming[0x056][0xFFFE] = L{ + {ctype='int', label='Current TVR Mission'}, -- 04 + {ctype='data[8]', label='_junk'}, -- 08 +} + func.incoming[0x056][0xFFFF] = L{ {ctype='int', label='Nation'}, -- 04 {ctype='int', label='Current Nation Mission'}, -- 08 From 1b70a017f9d34421a8d723fe0b73f1d0bedd9ef8 Mon Sep 17 00:00:00 2001 From: eLii Date: Sat, 9 Jul 2022 14:14:53 -0500 Subject: [PATCH 0858/1002] Update fields.lua Correct TVR `_junk` field. --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 0d131e94cb..0dea088c5a 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2800,7 +2800,7 @@ func.incoming[0x056][0x00D8] = L{ func.incoming[0x056][0xFFFE] = L{ {ctype='int', label='Current TVR Mission'}, -- 04 - {ctype='data[8]', label='_junk'}, -- 08 + {ctype='data[28]', label='_junk'}, -- 08 } func.incoming[0x056][0xFFFF] = L{ From 52680ee9e7efa4913791ac1696ea918687b6e1c9 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Mon, 11 Jul 2022 13:38:56 +0200 Subject: [PATCH 0859/1002] [Slips lib] Update for July 2022 Added items to slips libs for the 10 July, 2022 FFXI Update. --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index dce16aa0f8..9bb58a67ac 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757, 25909}, -- 192 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052}, -- 155 SE Skipped an index hence the 0 as one of the items + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752}, -- 156 SE Skipped an index hence the 0 as one of the items [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067, 21680, 22071}, --177 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, --115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, --115 From e2a0ae23a0c002dae59cd036eb33f3edfcb3068b Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Fri, 5 Aug 2022 00:24:36 -0600 Subject: [PATCH 0860/1002] [dialog.lua] Fix occasional missing \ at the end --- addons/libs/dialog.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addons/libs/dialog.lua b/addons/libs/dialog.lua index 7565c92bef..6f2e16d593 100644 --- a/addons/libs/dialog.lua +++ b/addons/libs/dialog.lua @@ -214,6 +214,9 @@ function dialog.open_dat_by_zone_id(zone_id, language) end local dat_path = windower.ffxi_path + if not dat_path:endswith('\\') then + dat_path = dat_path..'\\' + end local path local vtable = dat_path .. 'VTABLE.DAT' local ftable = dat_path .. 'FTABLE.DAT' From c4e95e8783a7a0a4930caad4274affc02c8f4b8f Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Wed, 10 Aug 2022 12:31:20 +0200 Subject: [PATCH 0861/1002] [slips lib] August 10, 2022 FFXI Update Adding items to slips from the august 10 update --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 9bb58a67ac..fdc1f0f142 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -15,7 +15,7 @@ slips.storages = L{29312, 29313, 29314, 29315, 29316, 29317, 29318, 2931 slips.items = { [slips.storages[1]] = L{16084, 14546, 14961, 15625, 15711, 16085, 14547, 14962, 15626, 15712, 16086, 14548, 14963, 15627, 15713, 16087, 14549, 14964, 15628, 15714, 16088, 14550, 14965, 15629, 15715, 16089, 14551, 14966, 15630, 15716, 16090, 14552, 14967, 15631, 15717, 16091, 14553, 14968, 15632, 15718, 16092, 14554, 14969, 15633, 15719, 16093, 14555, 14970, 15634, 15720, 16094, 14556, 14971, 15635, 15721, 16095, 14557, 14972, 15636, 15722, 16096, 14558, 14973, 15637, 15723, 16097, 14559, 14974, 15638, 15724, 16098, 14560, 14975, 15639, 15725, 16099, 14561, 14976, 15640, 15726, 16100, 14562, 14977, 15641, 15727, 16101, 14563, 14978, 15642, 15728, 16102, 14564, 14979, 15643, 15729, 16103, 14565, 14980, 15644, 15730, 16106, 14568, 14983, 15647, 15733, 16107, 14569, 14984, 15648, 15734, 16108, 14570, 14985, 15649, 15735, 16602, 17741, 18425, 18491, 18588, 18717, 18718, 18850, 18943, 16069, 14530, 14940, 15609, 15695, 16062, 14525, 14933, 15604, 15688, 16064, 14527, 14935, 15606, 15690, 18685, 18065, 17851, 18686, 18025, 18435, 18113, 17951, 17715, 18485, 18408, 18365, 18583, 18417, 18388, 16267, 16268, 16269, 16228, 16229, 15911, 15799, 15800, 15990, 17745, 18121, 16117, 14577, 17857}, -- 168 [slips.storages[2]] = L{12421, 12549, 12677, 12805, 12933, 13911, 14370, 14061, 14283, 14163, 12429, 12557, 12685, 12813, 12941, 13924, 14371, 14816, 14296, 14175, 13934, 14387, 14821, 14303, 14184, 13935, 14388, 14822, 14304, 14185, 13876, 13787, 14006, 14247, 14123, 13877, 13788, 14007, 14248, 14124, 13908, 14367, 14058, 14280, 14160, 13909, 14368, 14059, 14281, 14161, 16113, 14573, 14995, 15655, 15740, 16115, 14575, 14997, 15657, 15742, 16114, 14574, 14996, 15656, 15741, 16116, 14576, 14998, 15658, 15743, 12818, 18198, 12946, 18043, 12690, 17659, 12296, 12434, 15471, 15472, 15473, 15508, 15509, 15510, 15511, 15512, 15513, 15514, 17710, 17595, 18397, 18360, 18222, 17948, 18100, 15475, 15476, 15477, 15488, 15961, 14815, 14812, 14813, 15244, 15240, 14488, 14905, 15576, 15661, 15241, 14489, 14906, 15577, 15662, 13927, 14378, 14076, 14308, 14180, 13928, 14379, 14077, 14309, 14181, 10438, 10276, 10320, 10326, 10367, 10439, 10277, 10321, 10327, 10368, 10440, 10278, 10322, 10328, 10369, 10441, 10279, 10323, 10329, 10370, 25734, 25735, 25736, 25737, 25738, 25739, 25740, 25741, 25742, 25743, 25744}, -- 155 - [slips.storages[3]] = L{16155, 11282, 15021, 16341, 11376, 16156, 11283, 15022, 16342, 11377, 16157, 11284, 15023, 16343, 11378, 16148, 14590, 15011, 16317, 15757, 16143, 14591, 15012, 16318, 15758, 16146, 14588, 15009, 16315, 15755, 16147, 14589, 15010, 16316, 15756, 15966, 15967, 19041, 17684, 17685, 11636, 15844, 15934, 16258, 18735, 18734, 16291, 16292, 19042, 15935, 16293, 16294, 15936, 18618, 11588, 11545, 16158, 16159, 16160, 16149, 14583, 15007, 16314, 15751, 16141, 14581, 15005, 16312, 15749, 16142, 14582, 15006, 16313, 15750, 10876, 10450, 10500, 11969, 10600, 10877, 10451, 10501, 11970, 10601, 10878, 10452, 10502, 11971, 10602, 19132, 18551, 11798, 11362, 11363, 11625, 15959, 16259, 22299, 26414, 21623, 26219, 21886, 23792, 23793, 23794, 23795, 23796, 22032, 22043, 21530, 22044, 26273, 25415, 25416, 25414, 22050}, -- 116 + [slips.storages[3]] = L{16155, 11282, 15021, 16341, 11376, 16156, 11283, 15022, 16342, 11377, 16157, 11284, 15023, 16343, 11378, 16148, 14590, 15011, 16317, 15757, 16143, 14591, 15012, 16318, 15758, 16146, 14588, 15009, 16315, 15755, 16147, 14589, 15010, 16316, 15756, 15966, 15967, 19041, 17684, 17685, 11636, 15844, 15934, 16258, 18735, 18734, 16291, 16292, 19042, 15935, 16293, 16294, 15936, 18618, 11588, 11545, 16158, 16159, 16160, 16149, 14583, 15007, 16314, 15751, 16141, 14581, 15005, 16312, 15749, 16142, 14582, 15006, 16313, 15750, 10876, 10450, 10500, 11969, 10600, 10877, 10451, 10501, 11970, 10601, 10878, 10452, 10502, 11971, 10602, 19132, 18551, 11798, 11362, 11363, 11625, 15959, 16259, 22299, 26414, 21623, 26219, 21886, 23792, 23793, 23794, 23795, 23796, 22032, 22043, 21530, 22044, 26273, 25415, 25416, 25414, 22050, 22302}, -- 117 [slips.storages[4]] = L{12511, 12638, 13961, 14214, 14089, 12512, 12639, 13962, 14215, 14090, 13855, 12640, 13963, 14216, 14091, 13856, 12641, 13964, 14217, 14092, 12513, 12642, 13965, 14218, 14093, 12514, 12643, 13966, 14219, 14094, 12515, 12644, 13967, 14220, 14095, 12516, 12645, 13968, 14221, 14096, 12517, 12646, 13969, 14222, 14097, 13857, 12647, 13970, 14223, 14098, 12518, 12648, 13971, 14099, 14224, 13868, 13781, 13972, 14225, 14100, 13869, 13782, 13973, 14226, 14101, 12519, 12649, 13974, 14227, 14102, 12520, 12650, 13975, 14228, 14103, 15265, 14521, 14928, 15600, 15684, 15266, 14522, 14929, 15601, 15685, 15267, 14523, 14930, 15602, 15686, 16138, 14578, 15002, 15659, 15746, 16139, 14579, 15003, 15660, 15747, 16140, 14580, 15004, 16311, 15748, 16678, 17478, 17422, 17423, 16829, 16764, 17643, 16798, 16680, 16766, 17188, 17812, 17771, 17772, 16887, 17532, 17717, 18702, 17858, 19203, 21461, 21124, 20776, 27786, 27926, 28066, 28206, 28346, 27787, 27927, 28067, 28207, 28347}, -- 138 [slips.storages[5]] = L{15225, 14473, 14890, 15561, 15352, 15226, 14474, 14891, 15562, 15353, 15227, 14475, 14892, 15563, 15354, 15228, 14476, 14893, 15564, 15355, 15229, 14477, 14894, 15565, 15356, 15230, 14478, 14895, 15566, 15357, 15231, 14479, 14896, 15567, 15358, 15232, 14480, 14897, 15568, 15359, 15233, 14481, 14898, 15569, 15360, 15234, 14482, 14899, 15570, 15361, 15235, 14483, 14900, 15362, 15571, 15236, 14484, 14901, 15572, 15363, 15237, 14485, 14902, 15573, 15364, 15238, 14486, 14903, 15574, 15365, 15239, 14487, 14904, 15575, 15366, 11464, 11291, 15024, 16345, 11381, 11467, 11294, 15027, 16348, 11384, 11470, 11297, 15030, 16351, 11387, 11475, 11302, 15035, 16357, 11393, 11476, 11303, 15036, 16358, 11394, 11477, 11304, 15037, 16359, 11395}, -- 105 [slips.storages[6]] = L{15072, 15087, 15102, 15117, 15132, 15871, 15073, 15088, 15103, 15118, 15133, 15478, 15074, 15089, 15104, 15119, 15134, 15872, 15075, 15090, 15105, 15120, 15135, 15874, 15076, 15091, 15106, 15121, 15136, 15873, 15077, 15092, 15107, 15122, 15137, 15480, 15078, 15093, 15108, 15123, 15138, 15481, 15079, 15094, 15109, 15124, 15139, 15479, 15080, 15095, 15110, 15125, 15140, 15875, 15081, 15096, 15111, 15126, 15141, 15482, 15082, 15097, 15112, 15127, 15142, 15876, 15083, 15098, 15113, 15128, 15143, 15879, 15084, 15099, 15114, 15129, 15144, 15877, 15085, 15100, 15115, 15130, 15145, 15878, 15086, 15101, 15116, 15131, 15146, 15484, 11465, 11292, 15025, 16346, 11382, 16244, 11468, 11295, 15028, 16349, 11385, 15920, 11471, 11298, 15031, 16352, 11388, 16245, 11478, 11305, 15038, 16360, 11396, 16248, 11480, 11307, 15040, 16362, 11398, 15925}, -- 120 From ed1d6e1d1f124cdbd5216ffb8bf1c732d65330d0 Mon Sep 17 00:00:00 2001 From: funkworkz Date: Thu, 11 Aug 2022 01:02:03 -0500 Subject: [PATCH 0862/1002] Update setbgm.lua Song name released via ffxi official YouTube channel video --- addons/setbgm/setbgm.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/setbgm/setbgm.lua b/addons/setbgm/setbgm.lua index c0b49f0d5c..0080faadbb 100644 --- a/addons/setbgm/setbgm.lua +++ b/addons/setbgm/setbgm.lua @@ -50,7 +50,8 @@ music_types = { } songs = { - [25]='Voracious Resurgence Unknown 1', [26]='Voracious Resurgence Unknown 2', [27]='Voracious Resurgence Unknown 3', [28]='Voracious Resurgence Unknown 4', [29]="Devils' Delight", [30]="Odyssey - Bumba", [31]='Voracious Resurgence Unknown 5', [32]='Voracious Resurgence Unknown 6', [33]='Voracious Resurgence Unknown 7', [34]="We Are Vana'diel", + [25]='Voracious Resurgence Unknown 1', [26]='Voracious Resurgence Unknown 2', [27]='Voracious Resurgence Unknown 3', [28]='Voracious Resurgence Unknown 4', [29]="Devils' Delight", [30]="Odyssey - Bumba", [31]='Voracious Resurgence Unknown 5', [32]='Voracious Resurgence Unknown 6', + [33]='Voracious Resurgence Unknown 7', [34]="We Are Vana'diel", [35]='Goddessspeed', [40]='Cloister of Time and Souls', [41]='Royal Wanderlust', [42]='Snowdrift Waltz', [43]='Troubled Shadows', [44]='Where Lords Rule Not', [45]='Summers Lost', [46]='Goddess Divine', [47]='Echoes of Creation', [48]='Main Theme', [49]='Luck of the Mog', [50]='Feast of the Ladies', [51]='Abyssea - Scarlet Skies, Shadowed Plains', [52]='Melodies Errant', [53]='Shinryu', [54]='Everlasting Bonds', [55]='Provenance Watcher', [56]='Where it All Begins', [57]='Steel Sings, Blades Dance', [58]='A New Direction', [59]='The Pioneers', [60]='Into Lands Primeval - Ulbuka', [61]="Water's Umbral Knell", [62]='Keepers of the Wild', [63]='The Sacred City of Adoulin', [64]='Breaking Ground', [65]='Hades', [66]='Arciela', [67]='Mog Resort', [68]='Worlds Away', [69]="Distant Worlds (Nanaa Mihgo's version)", From 6573db347584bf59f68f374afeb948323842a537 Mon Sep 17 00:00:00 2001 From: Dean James Date: Sat, 20 Aug 2022 15:22:04 +0100 Subject: [PATCH 0863/1002] Update EmpyPopTracker to 2.7.0 --- addons/EmpyPopTracker/EmpyPopTracker.lua | 9 +++- addons/EmpyPopTracker/nms/amphitrite.lua | 38 ++++++++++++++ addons/EmpyPopTracker/nms/bennu.lua | 38 ++++++++++++++ addons/EmpyPopTracker/nms/index.lua | 6 +++ addons/EmpyPopTracker/nms/ironclad smiter.lua | 49 +++++++++++++++++++ .../EmpyPopTracker/nms/ironclad sunderer.lua | 49 +++++++++++++++++++ .../nms/ironclad triturator.lua | 49 +++++++++++++++++++ addons/EmpyPopTracker/nms/resheph.lua | 38 ++++++++++++++ 8 files changed, 274 insertions(+), 2 deletions(-) create mode 100644 addons/EmpyPopTracker/nms/amphitrite.lua create mode 100644 addons/EmpyPopTracker/nms/bennu.lua create mode 100644 addons/EmpyPopTracker/nms/ironclad smiter.lua create mode 100644 addons/EmpyPopTracker/nms/ironclad sunderer.lua create mode 100644 addons/EmpyPopTracker/nms/ironclad triturator.lua create mode 100644 addons/EmpyPopTracker/nms/resheph.lua diff --git a/addons/EmpyPopTracker/EmpyPopTracker.lua b/addons/EmpyPopTracker/EmpyPopTracker.lua index a6ae2aa549..2b5b431a8a 100644 --- a/addons/EmpyPopTracker/EmpyPopTracker.lua +++ b/addons/EmpyPopTracker/EmpyPopTracker.lua @@ -29,7 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _addon.name = 'Empy Pop Tracker' _addon.author = 'Dean James (Xurion of Bismarck)' _addon.commands = { 'ept', 'empypoptracker' } -_addon.version = '2.5.0' +_addon.version = '2.7.0' config = require('config') res = require('resources') @@ -224,7 +224,12 @@ end EmpyPopTracker.generate_info = function(nm, key_items, items) return { has_all_pops = not nm.pops or T(nm.pops):all(function(item) - return item.type == 'item' and owns_item(item.id, items) or owns_key_item(item.id, key_items) + -- Avoids confusing item and key item IDs + if item.type == 'item' then + return owns_item(item.id, items) + end + + return owns_key_item(item.id, key_items) end), text = generate_text(nm, key_items, items, 1) } diff --git a/addons/EmpyPopTracker/nms/amphitrite.lua b/addons/EmpyPopTracker/nms/amphitrite.lua new file mode 100644 index 0000000000..f9209cc158 --- /dev/null +++ b/addons/EmpyPopTracker/nms/amphitrite.lua @@ -0,0 +1,38 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = 'Amphitrite', + pops = { { + id = 1532, --Variegated Uragnite Shell + type = 'key item', + dropped_from = { + name = 'Melo Melo, Timed (F-11/G-11)', + } + } } +} diff --git a/addons/EmpyPopTracker/nms/bennu.lua b/addons/EmpyPopTracker/nms/bennu.lua new file mode 100644 index 0000000000..f632bfafa3 --- /dev/null +++ b/addons/EmpyPopTracker/nms/bennu.lua @@ -0,0 +1,38 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = 'Bennu', + pops = { { + id = 1522, --Resplendent roc quill + type = 'key item', + dropped_from = { + name = 'Ouzelum, Timed (I-8/J-9)', + } + } } +} diff --git a/addons/EmpyPopTracker/nms/index.lua b/addons/EmpyPopTracker/nms/index.lua index a2ab5b6049..fd21e34556 100644 --- a/addons/EmpyPopTracker/nms/index.lua +++ b/addons/EmpyPopTracker/nms/index.lua @@ -28,9 +28,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. local nms = { 'alfard', + 'amphitrite', 'apademak', 'arch dynamis lord', 'azdaja', + 'bennu', 'briareus', 'brulo', 'bukhis', @@ -39,12 +41,16 @@ local nms = { 'cirein-croin', 'dragua', 'glavoid', + 'ironclad smiter', + 'ironclad sunderer', + 'ironclad triturator', 'isgebind', 'itzpapalotl', 'kukulkan', 'maere', 'ogopogo', 'orthrus', + 'resheph', 'sedna', 'sobek', 'ulhuadshi', diff --git a/addons/EmpyPopTracker/nms/ironclad smiter.lua b/addons/EmpyPopTracker/nms/ironclad smiter.lua new file mode 100644 index 0000000000..ef04bcda07 --- /dev/null +++ b/addons/EmpyPopTracker/nms/ironclad smiter.lua @@ -0,0 +1,49 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = 'Ironclad Smiter', + collectable = 3293, --Iron Plate + collectable_target_count = 50, + pops = { { + id = 3230, --Tablilla Mercury + type = 'item', + dropped_from = { + name = 'Tablilla, Forced (C-11)', + pops = { { + id = 3235, --Sandy Shard + type = 'item', + dropped_from = { name = 'Sand Sweeper, (D-10)' } + } } + } + }, { + id = 3236, --Smoldering Arm + type = 'item', + dropped_from = { name = 'Bonfire, (D-11/E-11)' } + } } +} diff --git a/addons/EmpyPopTracker/nms/ironclad sunderer.lua b/addons/EmpyPopTracker/nms/ironclad sunderer.lua new file mode 100644 index 0000000000..17382875d3 --- /dev/null +++ b/addons/EmpyPopTracker/nms/ironclad sunderer.lua @@ -0,0 +1,49 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = 'Ironclad Sunderer', + collectable = 3293, --Iron Plate + collectable_target_count = 50, + pops = { { + id = 3260, --Teekesselchen Fragment + type = 'item', + dropped_from = { + name = 'Teekesselchen, Forced (I-5)', + pops = { { + id = 3265, --Bubbling Oil + type = 'item', + dropped_from = { name = 'Sinister Seidel, (J-5)' } + } } + } + }, { + id = 3266, --Darkflame Arm + type = 'item', + dropped_from = { name = 'Stygian Djinn, (K-7)' } + } } +} diff --git a/addons/EmpyPopTracker/nms/ironclad triturator.lua b/addons/EmpyPopTracker/nms/ironclad triturator.lua new file mode 100644 index 0000000000..225ff88fff --- /dev/null +++ b/addons/EmpyPopTracker/nms/ironclad triturator.lua @@ -0,0 +1,49 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = 'Ironclad Triturator', + collectable = 3293, --Iron Plate + collectable_target_count = 50, + pops = { { + id = 3245, --Bevel Gear + type = 'item', + dropped_from = { + name = 'Koghatu, Forced (G-8)', + pops = { { + id = 3250, --Helical Gear + type = 'item', + dropped_from = { name = 'Mechanical Menace, (G-8/H-8)' } + } } + } + }, { + id = 3251, --Gear Fluid + type = 'item', + dropped_from = { name = 'Sub-zero Gear, (F-8/F-9)' } + } } +} diff --git a/addons/EmpyPopTracker/nms/resheph.lua b/addons/EmpyPopTracker/nms/resheph.lua new file mode 100644 index 0000000000..21080197ca --- /dev/null +++ b/addons/EmpyPopTracker/nms/resheph.lua @@ -0,0 +1,38 @@ +--[[ +Copyright © 2020, Dean James (Xurion of Bismarck) +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 Empy Pop Tracker 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 Dean James (Xurion of Bismarck) 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. +]] + +return { + name = 'Resheph', + pops = { { + id = 1527, --Decaying Diremite Fang + type = 'key item', + dropped_from = { + name = 'Awahondo, Timed (K-6/K-7)', + } + } } +} From b30897f6ce662bf1de63a80858a9f7ddd89f4307 Mon Sep 17 00:00:00 2001 From: trv6 Date: Sun, 21 Aug 2022 16:46:07 -0400 Subject: [PATCH 0864/1002] Remove strings method Strings isn't required --- addons/libs/dialog.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/dialog.lua b/addons/libs/dialog.lua index 6f2e16d593..02423389cb 100644 --- a/addons/libs/dialog.lua +++ b/addons/libs/dialog.lua @@ -214,8 +214,8 @@ function dialog.open_dat_by_zone_id(zone_id, language) end local dat_path = windower.ffxi_path - if not dat_path:endswith('\\') then - dat_path = dat_path..'\\' + if sub(dat_path, -1, -1) ~= '\\' then + dat_path = dat_path .. '\\' end local path local vtable = dat_path .. 'VTABLE.DAT' From 913134503000968f31908f44e23369355e94b33e Mon Sep 17 00:00:00 2001 From: Cameron Gunnin Date: Mon, 29 Aug 2022 22:46:59 +0900 Subject: [PATCH 0865/1002] Update fields.lua: Update 0x0E0 (Linkshell Equip) Added definition for which bag the linkshell is being equipped from. --- addons/libs/packets/fields.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 0dea088c5a..68bf1191b6 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -3609,8 +3609,9 @@ fields.incoming[0x0DF] = L{ -- Linkshell Equip fields.incoming[0x0E0] = L{ {ctype='unsigned char', label='Linkshell Number'}, -- 04 - {ctype='unsigned char', label='Inventory Slot'}, -- 05 - {ctype='unsigned short', label='_junk1'}, -- 06 + {ctype='unsigned char', label='Slot'}, -- 05 + {ctype='unsigned char', label='Bag'}, -- 06 + {ctype='unsigned char', label='_junk1'}, -- 07 } -- Party Member List From 099f32f5be3b04f26cd440b26b9d0ead43ef0c27 Mon Sep 17 00:00:00 2001 From: Nifim Date: Mon, 29 Aug 2022 19:05:01 -0700 Subject: [PATCH 0866/1002] Set label back to 'Inventory Slot' Slot is a better name but we dont want to break existing code that relies on the name. This could be revisited later --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 68bf1191b6..cac93ff2c4 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -3609,7 +3609,7 @@ fields.incoming[0x0DF] = L{ -- Linkshell Equip fields.incoming[0x0E0] = L{ {ctype='unsigned char', label='Linkshell Number'}, -- 04 - {ctype='unsigned char', label='Slot'}, -- 05 + {ctype='unsigned char', label='Inventory Slot'}, -- 05 {ctype='unsigned char', label='Bag'}, -- 06 {ctype='unsigned char', label='_junk1'}, -- 07 } From b100b7a0f1f65d42fd8a64baa23dd904e0d70975 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Tue, 30 Aug 2022 14:27:57 +0100 Subject: [PATCH 0867/1002] Added new currencies. The August 2022 update to the game added 4 new fields to the currencies menu. This update reflects that. --- addons/libs/packets/fields.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index cac93ff2c4..ac65ce1666 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -4009,6 +4009,10 @@ fields.incoming[0x118] = L{ {ctype='unsigned char', label='Darkness Spheres Set'}, -- 7C {ctype='data[0x03]', label='_unknown1'}, -- 7D Presumably Unused Padding {ctype='signed int', label='Silver A.M.A.N. Vouchers Stored'}, -- 80 + {ctype='signed int', label='Domain Points'}, -- 84 + {ctype='signed int', label='Domain Points Earned Today'}, -- 88 + {ctype='signed int', label='Mog Segments'}, -- 8C + {ctype='signed int', label='Gallimaufry'}, -- 90 } types.ability_recast = L{ From 97e9203d4e865e6c806ffaecad865d23f155ef71 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Fri, 9 Sep 2022 15:21:24 -0400 Subject: [PATCH 0868/1002] Preemptive for Sept 2022 Update Will need double checking that SE didn't screw up and for the Slip Item ID to be added. --- addons/libs/slips.lua | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index fdc1f0f142..08c0223c25 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -35,12 +35,13 @@ slips.items = { [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752}, -- 156 SE Skipped an index hence the 0 as one of the items - [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067, 21680, 22071}, --177 - [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, --115 - [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, --115 - [slips.storages[26]] = L{23063, 23130, 23197, 23264, 23331, 23064, 23131, 23198, 23265, 23332, 23065, 23132, 23199, 23266, 23333, 23066, 23133, 23200, 23267, 23334, 23067, 23134, 23201, 23268, 23335, 23068, 23135, 23202, 23269, 23336, 23069, 23136, 23203, 23270, 23337, 23070, 23137, 23204, 23271, 23338, 23071, 23138, 23205, 23272, 23339, 23072, 23139, 23206, 23273, 23340, 23073, 23140, 23207, 23274, 23341, 23074, 23141, 23208, 23275, 23342, 23075, 23142, 23209, 23276, 23343, 23076, 23143, 23210, 23277, 23344, 23077, 23144, 23211, 23278, 23345, 23078, 23145, 23212, 23279, 23346, 23079, 23146, 23213, 23280, 23347, 23080, 23147, 23214, 23281, 23348, 23081, 23148, 23215, 23282, 23349, 23082, 23149, 23216, 23283, 23350, 23083, 23150, 23217, 23284, 23351, 23084, 23151, 23218, 23285, 23352}, --110 - [slips.storages[27]] = L{23398, 23465, 23532, 23599, 23666, 23399, 23466, 23533, 23600, 23667, 23400, 23467, 23534, 23601, 23668, 23401, 23468, 23535, 23602, 23669, 23402, 23469, 23536, 23603, 23670, 23403, 23470, 23537, 23604, 23671, 23404, 23471, 23538, 23605, 23672, 23405, 23472, 23539, 23606, 23673, 23406, 23473, 23540, 23607, 23674, 23407, 23474, 23541, 23608, 23675, 23408, 23475, 23542, 23609, 23676, 23409, 23476, 23543, 23610, 23677, 23410, 23477, 23544, 23611, 23678, 23411, 23478, 23545, 23612, 23679, 23412, 23479, 23546, 23613, 23680, 23413, 23480, 23547, 23614, 23681, 23414, 23481, 23548, 23615, 23682, 23415, 23482, 23549, 23616, 23683, 23416, 23483, 23550, 23617, 23684, 23417, 23484, 23551, 23618, 23685, 23418, 23485, 23552, 23619, 23686, 23419, 23486, 23553, 23620, 23687}, --110 + [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067, 21680, 22071}, -- 177 + [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, -- 115 + [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, -- 115 + [slips.storages[26]] = L{23063, 23130, 23197, 23264, 23331, 23064, 23131, 23198, 23265, 23332, 23065, 23132, 23199, 23266, 23333, 23066, 23133, 23200, 23267, 23334, 23067, 23134, 23201, 23268, 23335, 23068, 23135, 23202, 23269, 23336, 23069, 23136, 23203, 23270, 23337, 23070, 23137, 23204, 23271, 23338, 23071, 23138, 23205, 23272, 23339, 23072, 23139, 23206, 23273, 23340, 23073, 23140, 23207, 23274, 23341, 23074, 23141, 23208, 23275, 23342, 23075, 23142, 23209, 23276, 23343, 23076, 23143, 23210, 23277, 23344, 23077, 23144, 23211, 23278, 23345, 23078, 23145, 23212, 23279, 23346, 23079, 23146, 23213, 23280, 23347, 23080, 23147, 23214, 23281, 23348, 23081, 23148, 23215, 23282, 23349, 23082, 23149, 23216, 23283, 23350, 23083, 23150, 23217, 23284, 23351, 23084, 23151, 23218, 23285, 23352}, -- 110 + [slips.storages[27]] = L{23398, 23465, 23532, 23599, 23666, 23399, 23466, 23533, 23600, 23667, 23400, 23467, 23534, 23601, 23668, 23401, 23468, 23535, 23602, 23669, 23402, 23469, 23536, 23603, 23670, 23403, 23470, 23537, 23604, 23671, 23404, 23471, 23538, 23605, 23672, 23405, 23472, 23539, 23606, 23673, 23406, 23473, 23540, 23607, 23674, 23407, 23474, 23541, 23608, 23675, 23408, 23475, 23542, 23609, 23676, 23409, 23476, 23543, 23610, 23677, 23410, 23477, 23544, 23611, 23678, 23411, 23478, 23545, 23612, 23679, 23412, 23479, 23546, 23613, 23680, 23413, 23480, 23547, 23614, 23681, 23414, 23481, 23548, 23615, 23682, 23415, 23482, 23549, 23616, 23683, 23416, 23483, 23550, 23617, 23684, 23417, 23484, 23551, 23618, 23685, 23418, 23485, 23552, 23619, 23686, 23419, 23486, 23553, 23620, 23687}, -- 110 [slips.storages[28]] = L{21515, 21561, 21617, 21670, 21718, 21775, 21826, 21879, 21918, 21971, 22027, 22082, 22108, 22214, 21516, 21562, 21618, 21671, 21719, 21776, 21827, 21880, 21919, 21972, 22028, 22083, 22109, 22215, 21517, 21563, 21619, 21672, 21720, 21777, 21828, 21881, 21920, 21973, 22029, 22084, 22110, 22216, 21518, 21564, 21620, 21673, 21721, 21778, 21829, 21882, 21921, 21974, 22030, 22085, 22111, 22217, 21519, 21565, 21621, 21674, 21722, 21779, 21830, 21883, 21922, 21975, 22031, 22086, 22107, 22218, 22089}, --71 + --[slips.storages[29]] = L{23085, 23152, 23219, 23286, 23353, 23086, 23153, 23220, 23287, 23354, 23087, 23154, 23221, 23288, 23355, 23088, 23155, 23222, 23289, 23356, 23089, 23156, 23223, 23290, 23357, 23090, 23157, 23224, 23291, 23358, 23091, 23158, 23225, 23292, 23359, 23092, 23159, 23226, 23293, 23360, 23093, 23160, 23227, 23294, 23361, 23094, 23161, 23228, 23295, 23362, 23095, 23162, 23229, 23363, 23096, 23163, 23230, 23297, 23364, 23097, 23164, 23231, 23298, 23365, 23098, 23165, 23232, 23299, 23366, 23099, 23166, 23233, 23300, 23367, 23100, 23167, 23234, 23301, 23368, 23101, 23168, 23235, 23302, 23369, 23102, 23169, 23236, 23303, 23370, 23103, 23170, 23237, 23304, 23371, 23104, 23171, 23238, 23305, 23372, 23105, 23172, 23239, 23306, 23373, 23106, 23173, 23240, 23307, 23374}, -- 110 } function slips.get_slip_id(n) From 32e943ccff9686f587c885420af883d414863806 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Fri, 9 Sep 2022 15:33:54 -0400 Subject: [PATCH 0869/1002] Amini Bragues +2 23296 Added --- addons/DressUp/DressUp.lua | 4 +- addons/DressUp/main.lua | 3630 ++++++++++++++++++++++++++++++++++++ addons/DressUp/ranged.lua | 656 +++++++ addons/DressUp/sub.lua | 1729 +++++++++++++++++ addons/libs/slips.lua | 2 +- 5 files changed, 6019 insertions(+), 2 deletions(-) create mode 100644 addons/DressUp/main.lua create mode 100644 addons/DressUp/ranged.lua create mode 100644 addons/DressUp/sub.lua diff --git a/addons/DressUp/DressUp.lua b/addons/DressUp/DressUp.lua index 85ea1e48e6..adb3c06abf 100644 --- a/addons/DressUp/DressUp.lua +++ b/addons/DressUp/DressUp.lua @@ -26,7 +26,7 @@ _addon.name = 'DressUp' _addon.author = 'Cair' -_addon.version = '1.21' +_addon.version = '1.30' _addon.commands = {'DressUp','du'} @@ -37,6 +37,8 @@ require('static_variables') models = {} +require('main') +require('sub') require('head') require('body') require('hands') diff --git a/addons/DressUp/main.lua b/addons/DressUp/main.lua new file mode 100644 index 0000000000..bce4aaf016 --- /dev/null +++ b/addons/DressUp/main.lua @@ -0,0 +1,3630 @@ +-- Copyright © 2013-2022, Cairthenn +-- 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 DressUp 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 Cairthenn 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. + + +models.main = {} + +models.main["None"] = { name = "empty" , model = 24576 } + +models.main[16385] = { name = "Cesti" , model = 24702} +models.main[16386] = { name = "Lizard Cesti" , model = 24703} +models.main[16387] = { name = "Poison Cesti" , model = 24704} +models.main[16388] = { name = "Himantes" , model = 24703} +models.main[16389] = { name = "Coeurl Cesti" , model = 24702} +models.main[16390] = { name = "Bronze Knuckles" , model = 24706} +models.main[16391] = { name = "Brass Knuckles" , model = 24707} +models.main[16392] = { name = "Metal Knuckles" , model = 24708} +models.main[16393] = { name = "Mythril Knuckles" , model = 24709} +models.main[16394] = { name = "Dst. Knuckles" , model = 24705} +models.main[16395] = { name = "Diamond Knuckles" , model = 24711} +models.main[16396] = { name = "Koenigs Knuckles" , model = 24710} +models.main[16397] = { name = "Behemoth Cesti" , model = 24704} +models.main[16398] = { name = "Burning Cesti" , model = 24703} +models.main[16399] = { name = "Katars" , model = 24695} +models.main[16400] = { name = "Darksteel Katars" , model = 24694} +models.main[16401] = { name = "Jamadhars" , model = 24696} +models.main[16403] = { name = "Poison Katars" , model = 24695} +models.main[16404] = { name = "Venom Katars" , model = 24694} +models.main[16405] = { name = "Cat Baghnakhs" , model = 24716} +models.main[16406] = { name = "Baghnakhs" , model = 24718} +models.main[16407] = { name = "Brass Baghnakhs" , model = 24717} +models.main[16408] = { name = "Rune Baghnakhs" , model = 24719} +models.main[16409] = { name = "Lynx Baghnakhs" , model = 24716} +models.main[16410] = { name = "Psn. Baghnakhs" , model = 24718} +models.main[16411] = { name = "Claws" , model = 24699} +models.main[16412] = { name = "Mythril Claws" , model = 24700} +models.main[16413] = { name = "Darksteel Claws" , model = 24698} +models.main[16414] = { name = "Cermet Claws" , model = 24701} +models.main[16416] = { name = "Dragon Claws" , model = 24701} +models.main[16417] = { name = "Poison Claws" , model = 24699} +models.main[16418] = { name = "Venom Claws" , model = 24698} +models.main[16419] = { name = "Patas" , model = 24714} +models.main[16420] = { name = "Bone Patas" , model = 24715} +models.main[16421] = { name = "Gold Patas" , model = 24713} +models.main[16422] = { name = "Tigerfangs" , model = 24715} +models.main[16423] = { name = "Manoples" , model = 24712} +models.main[16425] = { name = "Venom Claws +1" , model = 24698} +models.main[16426] = { name = "Avengers" , model = 24693} +models.main[16427] = { name = "Lunaris Claws" , model = 24693} +models.main[16428] = { name = "Afflictors" , model = 25075} +models.main[16429] = { name = "Slc. Baghnakhs" , model = 24717} +models.main[16430] = { name = "Acid Claws" , model = 24700} +models.main[16431] = { name = "Stun Claws" , model = 24701} +models.main[16432] = { name = "Stun Jamadhars" , model = 24696} +models.main[16433] = { name = "Lgn. Knuckles" , model = 24707} +models.main[16434] = { name = "Sonic Knuckles" , model = 24705} +models.main[16437] = { name = "Metal Knuckles +1" , model = 24708} +models.main[16438] = { name = "Slc. Baghnakhs +1" , model = 24717} +models.main[16439] = { name = "Poison Claws +1" , model = 24699} +models.main[16440] = { name = "Brz. Knuckles +1" , model = 24706} +models.main[16441] = { name = "Brs. Baghnakhs +1" , model = 24717} +models.main[16442] = { name = "Fsd. Baghnakhs" , model = 24716} +models.main[16443] = { name = "Fruit Punches" , model = 24702} +models.main[16444] = { name = "Baghnakhs +1" , model = 24718} +models.main[16445] = { name = "Claws +1" , model = 24699} +models.main[16446] = { name = "Mtl. Knuckles +1" , model = 24709} +models.main[16447] = { name = "Rusty Dagger" , model = 24740} +models.main[16448] = { name = "Bronze Dagger" , model = 24740} +models.main[16449] = { name = "Brass Dagger" , model = 24741} +models.main[16450] = { name = "Dagger" , model = 24742} +models.main[16451] = { name = "Mythril Dagger" , model = 24743} +models.main[16452] = { name = "Misericorde" , model = 24739} +models.main[16453] = { name = "Orichalcum Dagger" , model = 24755} +models.main[16454] = { name = "Blind Dagger" , model = 24740} +models.main[16455] = { name = "Baselard" , model = 24745} +models.main[16456] = { name = "Mythril Baselard" , model = 24746} +models.main[16457] = { name = "Dst. Baselard" , model = 24744} +models.main[16458] = { name = "Poison Baselard" , model = 24745} +models.main[16459] = { name = "Acid Baselard" , model = 24746} +models.main[16460] = { name = "Kris" , model = 24754} +models.main[16461] = { name = "Adaman Kris" , model = 24753} +models.main[16463] = { name = "Cmb.Cst. Dagger" , model = 24753} +models.main[16465] = { name = "Bronze Knife" , model = 24735} +models.main[16466] = { name = "Knife" , model = 24736} +models.main[16467] = { name = "Mythril Knife" , model = 24737} +models.main[16468] = { name = "Darksteel Knife" , model = 24734} +models.main[16469] = { name = "Cermet Knife" , model = 24738} +models.main[16470] = { name = "Gully" , model = 24733} +models.main[16471] = { name = "Blind Knife" , model = 24735} +models.main[16472] = { name = "Poison Knife" , model = 24736} +models.main[16473] = { name = "Kukri" , model = 24748} +models.main[16475] = { name = "Mythril Kukri" , model = 24749} +models.main[16476] = { name = "Darksteel Kukri" , model = 24747} +models.main[16477] = { name = "Cermet Kukri" , model = 24750} +models.main[16478] = { name = "Poison Kukri" , model = 24748} +models.main[16479] = { name = "Acid Kukri" , model = 24749} +models.main[16480] = { name = "Thief's Knife" , model = 24752} +models.main[16481] = { name = "Yataghan +1" , model = 24974} +models.main[16482] = { name = "Onion Dagger" , model = 24740} +models.main[16483] = { name = "Onion Knife" , model = 24735} +models.main[16484] = { name = "Burglar's Dagger" , model = 24742} +models.main[16485] = { name = "Yataghan" , model = 24974} +models.main[16486] = { name = "Beestinger" , model = 24743} +models.main[16487] = { name = "Minstrel's Dagger" , model = 24740} +models.main[16488] = { name = "Nguul" , model = 24733} +models.main[16489] = { name = "Poison Kukri +1" , model = 24748} +models.main[16490] = { name = "Blind Knife +1" , model = 24735} +models.main[16491] = { name = "Bronze Knife +1" , model = 24735} +models.main[16492] = { name = "Bronze Dagger +1" , model = 24740} +models.main[16493] = { name = "Blind Dagger +1" , model = 24740} +models.main[16494] = { name = "Corrosive Kukri" , model = 24749} +models.main[16495] = { name = "Silence Dagger" , model = 24741} +models.main[16496] = { name = "Poison Dagger" , model = 24742} +models.main[16497] = { name = "Sleep Dagger" , model = 24743} +models.main[16498] = { name = "Carabineer Dagger" , model = 24755} +models.main[16499] = { name = "Venom Kris" , model = 24754} +models.main[16500] = { name = "Aluh Jambiya" , model = 24985} +models.main[16501] = { name = "Acid Knife" , model = 24737} +models.main[16502] = { name = "Venom Knife" , model = 24734} +models.main[16503] = { name = "Stun Knife" , model = 24738} +models.main[16504] = { name = "Oynos Knife" , model = 24738} +models.main[16505] = { name = "Venom Kukri" , model = 24747} +models.main[16506] = { name = "Stun Kukri" , model = 24750} +models.main[16507] = { name = "Venom Baselard" , model = 24744} +models.main[16508] = { name = "Silence Dagger +1" , model = 24741} +models.main[16509] = { name = "Aspir Knife" , model = 24735} +models.main[16510] = { name = "Vnm. Baselard +1" , model = 24744} +models.main[16511] = { name = "Burnite Shell" , model = 24756} +models.main[16512] = { name = "Bilbo" , model = 24759} +models.main[16513] = { name = "Tuck" , model = 24760} +models.main[16514] = { name = "Mailbreaker" , model = 24763} +models.main[16515] = { name = "Colichemarde" , model = 24757} +models.main[16516] = { name = "Jr.Msk. Tuck" , model = 24760} +models.main[16517] = { name = "Degen" , model = 24764} +models.main[16518] = { name = "Mythril Degen" , model = 24765} +models.main[16519] = { name = "Schlaeger" , model = 24762} +models.main[16520] = { name = "Verdun" , model = 24761} +models.main[16521] = { name = "Rapier" , model = 24763} +models.main[16522] = { name = "Flame Degen" , model = 24764} +models.main[16523] = { name = "Holy Degen" , model = 24765} +models.main[16524] = { name = "Fleuret" , model = 24767} +models.main[16525] = { name = "Hornet Fleuret" , model = 24769} +models.main[16526] = { name = "Schwert" , model = 24768} +models.main[16527] = { name = "Epee" , model = 24766} +models.main[16528] = { name = "Bloody Rapier" , model = 24764} +models.main[16529] = { name = "Musketeer's Sword" , model = 24764} +models.main[16530] = { name = "Xiphos" , model = 24840} +models.main[16531] = { name = "Brass Xiphos" , model = 24841} +models.main[16532] = { name = "Gladius" , model = 24842} +models.main[16533] = { name = "Ancient Sword" , model = 24859} +models.main[16534] = { name = "Onion Sword" , model = 24841} +models.main[16535] = { name = "Bronze Sword" , model = 24844} +models.main[16536] = { name = "Iron Sword" , model = 24846} +models.main[16537] = { name = "Mythril Sword" , model = 24847} +models.main[16538] = { name = "Darksteel Sword" , model = 24843} +models.main[16539] = { name = "Cermet Sword" , model = 24849} +models.main[16540] = { name = "Tyrfing" , model = 25094} +models.main[16541] = { name = "Jagdplaute" , model = 24845} +models.main[16542] = { name = "Wing Sword" , model = 24864} +models.main[16543] = { name = "Fire Sword" , model = 24844} +models.main[16544] = { name = "Ryl.Arc. Sword" , model = 24827} +models.main[16545] = { name = "Broadsword" , model = 24852} +models.main[16546] = { name = "Katzbalger" , model = 24851} +models.main[16547] = { name = "Anelace" , model = 24850} +models.main[16548] = { name = "Coral Sword" , model = 24853} +models.main[16549] = { name = "Divine Sword" , model = 24852} +models.main[16550] = { name = "Hallowed Sword" , model = 24852} +models.main[16551] = { name = "Sapara" , model = 24831} +models.main[16552] = { name = "Scimitar" , model = 24832} +models.main[16553] = { name = "Tulwar" , model = 24833} +models.main[16554] = { name = "Hanger" , model = 24834} +models.main[16555] = { name = "Ridill" , model = 24835} +models.main[16556] = { name = "Bloody Blade" , model = 24838} +models.main[16557] = { name = "Msk.Cmd. Falchion" , model = 24838} +models.main[16558] = { name = "Falchion" , model = 24838} +models.main[16559] = { name = "Darksteel Falchion" , model = 24836} +models.main[16560] = { name = "Cutlass" , model = 24839} +models.main[16562] = { name = "Platinum Cutlass" , model = 24837} +models.main[16563] = { name = "Rune Blade" , model = 24830} +models.main[16564] = { name = "Flame Blade" , model = 24838} +models.main[16565] = { name = "Spatha" , model = 24825} +models.main[16566] = { name = "Longsword" , model = 24827} +models.main[16567] = { name = "Knight's Sword" , model = 24828} +models.main[16568] = { name = "Saber" , model = 24829} +models.main[16569] = { name = "Gold Sword" , model = 24826} +models.main[16571] = { name = "T.K. Army Sword" , model = 24827} +models.main[16572] = { name = "Bee Spatha" , model = 24825} +models.main[16575] = { name = "Curtana" , model = 24845} +models.main[16576] = { name = "Hunting Sword" , model = 24856} +models.main[16577] = { name = "Bastard Sword" , model = 24855} +models.main[16578] = { name = "Espadon" , model = 24857} +models.main[16579] = { name = "Kaskara" , model = 24854} +models.main[16580] = { name = "Bloodsword" , model = 24863} +models.main[16581] = { name = "Holy Sword" , model = 24862} +models.main[16582] = { name = "Vetala Sword" , model = 24864} +models.main[16583] = { name = "Claymore" , model = 24642} +models.main[16584] = { name = "Mythril Claymore" , model = 24643} +models.main[16585] = { name = "Dst. Claymore" , model = 24641} +models.main[16586] = { name = "Adaman Claymore" , model = 24640} +models.main[16587] = { name = "Gold Algol" , model = 24962} +models.main[16588] = { name = "Flame Claymore" , model = 24642} +models.main[16589] = { name = "Two-Hand. Sword" , model = 24647} +models.main[16590] = { name = "Greatsword" , model = 24648} +models.main[16591] = { name = "Zweihander" , model = 24646} +models.main[16592] = { name = "Gigant Sword" , model = 24645} +models.main[16593] = { name = "Plain Sword" , model = 24647} +models.main[16594] = { name = "Inferno Sword" , model = 24647} +models.main[16595] = { name = "Ram-Dao" , model = 24651} +models.main[16596] = { name = "Flamberge" , model = 24650} +models.main[16597] = { name = "Nagan" , model = 24649} +models.main[16598] = { name = "Gold Algol +1" , model = 24962} +models.main[16599] = { name = "Ryl.Grd. Sword" , model = 24649} +models.main[16600] = { name = "Wax Sword" , model = 24844} +models.main[16601] = { name = "Ryl.Swd. Blade" , model = 24648} +models.main[16602] = { name = "Perdu Sword" , model = 24646} +models.main[16603] = { name = "Halo Claymore" , model = 24642} +models.main[16604] = { name = "Save the Queen" , model = 24828} +models.main[16605] = { name = "Enhancing Sword" , model = 24826} +models.main[16606] = { name = "Rusty Greatsword" , model = 24648} +models.main[16607] = { name = "Chaosbringer" , model = 24641} +models.main[16608] = { name = "Gladiator" , model = 24842} +models.main[16609] = { name = "Bloody Sword" , model = 24843} +models.main[16610] = { name = "Wax Sword +1" , model = 24844} +models.main[16611] = { name = "Bee Spatha +1" , model = 24825} +models.main[16612] = { name = "Saber +1" , model = 24829} +models.main[16613] = { name = "Spirit Sword" , model = 24862} +models.main[16614] = { name = "Knife +1" , model = 24736} +models.main[16615] = { name = "Falchion +1" , model = 24838} +models.main[16616] = { name = "Zweihander +1" , model = 24646} +models.main[16617] = { name = "Tuck +1" , model = 24760} +models.main[16618] = { name = "Mailbreaker +1" , model = 24763} +models.main[16619] = { name = "Epee +1" , model = 24766} +models.main[16620] = { name = "Merman's Sword" , model = 24853} +models.main[16621] = { name = "Flame Sword" , model = 24844} +models.main[16622] = { name = "Judge's Sword" , model = 24884} +models.main[16623] = { name = "Bronze Sword +1" , model = 24844} +models.main[16624] = { name = "Xiphos +1" , model = 24840} +models.main[16625] = { name = "Scimitar +1" , model = 24832} +models.main[16626] = { name = "Iron Sword +1" , model = 24846} +models.main[16627] = { name = "Spatha +1" , model = 24825} +models.main[16628] = { name = "Longsword +1" , model = 24827} +models.main[16629] = { name = "Small Sword" , model = 24758} +models.main[16630] = { name = "Striker Sword" , model = 24859} +models.main[16631] = { name = "Kaiser Sword" , model = 24860} +models.main[16632] = { name = "Bilbo +1" , model = 24759} +models.main[16633] = { name = "Degen +1" , model = 24764} +models.main[16634] = { name = "Broadsword +1" , model = 24852} +models.main[16635] = { name = "Mythril Sword +1" , model = 24847} +models.main[16636] = { name = "Tulwar +1" , model = 24833} +models.main[16637] = { name = "Deathbringer" , model = 24641} +models.main[16638] = { name = "Claymore +1" , model = 24642} +models.main[16639] = { name = "Fine Claymore" , model = 24643} +models.main[16640] = { name = "Bronze Axe" , model = 24652} +models.main[16641] = { name = "Brass Axe" , model = 24653} +models.main[16642] = { name = "Bone Axe" , model = 24656} +models.main[16643] = { name = "Battleaxe" , model = 24654} +models.main[16644] = { name = "Mythril Axe" , model = 24655} +models.main[16645] = { name = "Darksteel Axe" , model = 24660} +models.main[16646] = { name = "Bronze Axe +1" , model = 24652} +models.main[16647] = { name = "Rune Axe" , model = 24661} +models.main[16648] = { name = "Legionnaire's Axe" , model = 24654} +models.main[16649] = { name = "Bone Pick" , model = 24666} +models.main[16650] = { name = "War Pick" , model = 24664} +models.main[16651] = { name = "Mythril Pick" , model = 24665} +models.main[16652] = { name = "Darksteel Pick" , model = 24663} +models.main[16653] = { name = "Nadziak" , model = 24662} +models.main[16654] = { name = "Glyph Axe" , model = 25095} +models.main[16655] = { name = "Rusty Pick" , model = 24664} +models.main[16656] = { name = "Orcish Axe" , model = 24667} +models.main[16657] = { name = "Tabar" , model = 24659} +models.main[16658] = { name = "Darksteel Tabar" , model = 24658} +models.main[16659] = { name = "Tabarzin" , model = 24657} +models.main[16660] = { name = "Doom Tabar" , model = 24657} +models.main[16661] = { name = "Brass Axe +1" , model = 24653} +models.main[16662] = { name = "Doom Tabar +1" , model = 24657} +models.main[16663] = { name = "Battleaxe +1" , model = 24654} +models.main[16664] = { name = "War Pick +1" , model = 24664} +models.main[16665] = { name = "Mythril Axe +1" , model = 24655} +models.main[16666] = { name = "Bone Axe +1" , model = 24656} +models.main[16667] = { name = "Light Axe" , model = 24654} +models.main[16668] = { name = "Bone Pick +1" , model = 24666} +models.main[16669] = { name = "Cmb.Cst. Axe" , model = 24659} +models.main[16670] = { name = "Mythril Pick +1" , model = 24665} +models.main[16671] = { name = "Tabar +1" , model = 24659} +models.main[16672] = { name = "Tigerhunter" , model = 24656} +models.main[16673] = { name = "Warrior's Axe" , model = 24654} +models.main[16674] = { name = "Emeth Pick" , model = 24665} +models.main[16675] = { name = "Storm Axe" , model = 24655} +models.main[16676] = { name = "Viking Axe" , model = 24660} +models.main[16677] = { name = "Darksteel Axe +1" , model = 24660} +models.main[16678] = { name = "Razor Axe" , model = 24654} +models.main[16679] = { name = "Wrath Tabar" , model = 24658} +models.main[16680] = { name = "Barbaroi Axe" , model = 24667} +models.main[16681] = { name = "Gerwitz's Axe" , model = 24659} +models.main[16682] = { name = "Darksteel Pick +1" , model = 24663} +models.main[16683] = { name = "Dst. Tabar +1" , model = 24658} +models.main[16684] = { name = "Kabrakan's Axe" , model = 24667} +models.main[16685] = { name = "Nadziak +1" , model = 24662} +models.main[16686] = { name = "Arcanabane" , model = 24666} +models.main[16687] = { name = "Platoon Axe" , model = 24653} +models.main[16688] = { name = "Mythril Claws +1" , model = 24700} +models.main[16689] = { name = "Brass Knuckles +1" , model = 24707} +models.main[16690] = { name = "Cesti +1" , model = 24702} +models.main[16691] = { name = "Ryl.Arc. Cesti" , model = 24702} +models.main[16692] = { name = "Psn. Baghnakhs +1" , model = 24718} +models.main[16693] = { name = "Poison Katars +1" , model = 24695} +models.main[16694] = { name = "Tct.Mag. Hooks" , model = 24715} +models.main[16695] = { name = "Katars +1" , model = 24695} +models.main[16696] = { name = "Patas +1" , model = 24714} +models.main[16697] = { name = "Dst. Claws +1" , model = 24698} +models.main[16698] = { name = "Dst. Knuckles +1" , model = 24705} +models.main[16699] = { name = "Himantes +1" , model = 24703} +models.main[16700] = { name = "Poison Cesti +1" , model = 24704} +models.main[16701] = { name = "Strike Baghnakhs" , model = 24716} +models.main[16702] = { name = "Cougar Baghnakhs" , model = 24717} +models.main[16703] = { name = "Impact Knuckles" , model = 24706} +models.main[16704] = { name = "Butterfly Axe" , model = 24670} +models.main[16705] = { name = "Greataxe" , model = 24671} +models.main[16706] = { name = "Heavy Axe" , model = 24669} +models.main[16707] = { name = "Bhuj" , model = 24672} +models.main[16708] = { name = "Horror Voulge" , model = 24941} +models.main[16709] = { name = "Inferno Axe" , model = 24670} +models.main[16710] = { name = "Gigant Axe" , model = 24674} +models.main[16711] = { name = "Demon's Axe" , model = 24673} +models.main[16712] = { name = "Centurion's Axe" , model = 24668} +models.main[16713] = { name = "Hellfire Axe" , model = 24669} +models.main[16714] = { name = "Neckchopper" , model = 24671} +models.main[16716] = { name = "Butterfly Axe +1" , model = 24670} +models.main[16717] = { name = "Greataxe +1" , model = 24671} +models.main[16718] = { name = "Heavy Axe +1" , model = 24669} +models.main[16719] = { name = "Moth Axe" , model = 24670} +models.main[16720] = { name = "Plantbane" , model = 24669} +models.main[16721] = { name = "Huge Moth Axe" , model = 24671} +models.main[16722] = { name = "Heavy Moth Axe" , model = 24670} +models.main[16723] = { name = "Executioner" , model = 24669} +models.main[16724] = { name = "Heavy Dst. Axe" , model = 24669} +models.main[16725] = { name = "Massive Dst. Axe" , model = 24668} +models.main[16726] = { name = "Forseti's Axe" , model = 24673} +models.main[16727] = { name = "Eisentaenzer" , model = 24673} +models.main[16728] = { name = "Schwarz Axt" , model = 24669} +models.main[16729] = { name = "Berserker's Axe" , model = 24669} +models.main[16730] = { name = "Colossal Axe" , model = 24674} +models.main[16731] = { name = "Colossal Axe +1" , model = 24674} +models.main[16732] = { name = "Bas. Greataxe" , model = 24668} +models.main[16733] = { name = "Republic Greataxe" , model = 24668} +models.main[16734] = { name = "Pendragon Axe" , model = 24672} +models.main[16735] = { name = "Axe of Trials" , model = 24670} +models.main[16736] = { name = "Dagger +1" , model = 24742} +models.main[16737] = { name = "Baselard +1" , model = 24745} +models.main[16738] = { name = "Mythril Dagger +1" , model = 24743} +models.main[16739] = { name = "Mythril Knife +1" , model = 24737} +models.main[16740] = { name = "Brass Dagger +1" , model = 24741} +models.main[16741] = { name = "Poison Dagger +1" , model = 24742} +models.main[16742] = { name = "Poison Knife +1" , model = 24736} +models.main[16743] = { name = "Python Baselard" , model = 24745} +models.main[16744] = { name = "Ryl.Sqr. Dagger" , model = 24746} +models.main[16745] = { name = "Decurion's Dagger" , model = 24743} +models.main[16746] = { name = "Mercenary's Knife" , model = 24736} +models.main[16747] = { name = "Mrc.Cpt. Kukri" , model = 24748} +models.main[16748] = { name = "Kukri +1" , model = 24748} +models.main[16749] = { name = "Kris +1" , model = 24754} +models.main[16750] = { name = "Mythril Kukri +1" , model = 24749} +models.main[16751] = { name = "Dst. Knife +1" , model = 24734} +models.main[16752] = { name = "Fine Baselard" , model = 24743} +models.main[16753] = { name = "Ceremonial Dagger" , model = 24740} +models.main[16754] = { name = "Parrying Knife" , model = 24752} +models.main[16755] = { name = "Archer's Knife" , model = 24737} +models.main[16756] = { name = "Leste Jambiya" , model = 24955} +models.main[16757] = { name = "Corsair's Knife" , model = 24747} +models.main[16758] = { name = "Dst. Baselard +1" , model = 24744} +models.main[16759] = { name = "Darksteel Kris" , model = 24754} +models.main[16760] = { name = "Darksteel Kris +1" , model = 24754} +models.main[16761] = { name = "Venom Kris +1" , model = 24754} +models.main[16762] = { name = "Venom Knife +1" , model = 24734} +models.main[16763] = { name = "Darksteel Kukri +1" , model = 24747} +models.main[16764] = { name = "Marauder's Knife" , model = 24736} +models.main[16765] = { name = "Lust Dagger" , model = 24741} +models.main[16766] = { name = "Paper Knife" , model = 24735} +models.main[16767] = { name = "Triple Dagger" , model = 24755} +models.main[16768] = { name = "Bronze Zaghnal" , model = 24773} +models.main[16769] = { name = "Brass Zaghnal" , model = 24774} +models.main[16770] = { name = "Zaghnal" , model = 24775} +models.main[16771] = { name = "Falcastra" , model = 24776} +models.main[16772] = { name = "Brass Zaghnal +1" , model = 24774} +models.main[16773] = { name = "Cruel Scythe" , model = 24771} +models.main[16774] = { name = "Scythe" , model = 24771} +models.main[16775] = { name = "Mythril Scythe" , model = 24772} +models.main[16776] = { name = "Mrc.Cpt. Scythe" , model = 24770} +models.main[16777] = { name = "Death Scythe" , model = 24777} +models.main[16778] = { name = "Brz. Zaghnal +1" , model = 24773} +models.main[16779] = { name = "Zaghnal +1" , model = 24775} +models.main[16780] = { name = "Lgn. Scythe" , model = 24774} +models.main[16781] = { name = "Scythe +1" , model = 24771} +models.main[16782] = { name = "Mythril Scythe +1" , model = 24772} +models.main[16783] = { name = "Plantreaper" , model = 24773} +models.main[16784] = { name = "Frostreaper" , model = 24774} +models.main[16785] = { name = "Harvester" , model = 24775} +models.main[16786] = { name = "Brb. Scythe" , model = 24772} +models.main[16787] = { name = "Demonslicer" , model = 24777} +models.main[16788] = { name = "Vassago's Scythe" , model = 24777} +models.main[16789] = { name = "Darksteel Scythe" , model = 24770} +models.main[16790] = { name = "Dst. Scythe +1" , model = 24770} +models.main[16791] = { name = "Death Scythe +1" , model = 24777} +models.main[16792] = { name = "Goshisho's Scythe" , model = 24773} +models.main[16793] = { name = "Scythe of Trials" , model = 24771} +models.main[16794] = { name = "Bone Scythe" , model = 24898} +models.main[16795] = { name = "Bone Scythe +1" , model = 24898} +models.main[16796] = { name = "Mythril Zaghnal" , model = 24776} +models.main[16797] = { name = "Mythril Zaghnal +1" , model = 24776} +models.main[16798] = { name = "Raven Scythe" , model = 24770} +models.main[16799] = { name = "Snr.Msk. Scythe" , model = 24921} +models.main[16800] = { name = "Knight's Sword +1" , model = 24828} +models.main[16801] = { name = "Sapara +1" , model = 24831} +models.main[16802] = { name = "Brass Xiphos +1" , model = 24841} +models.main[16803] = { name = "Fleuret +1" , model = 24767} +models.main[16804] = { name = "Flame Blade +1" , model = 24838} +models.main[16805] = { name = "Ryl.Grd. Fleuret" , model = 24769} +models.main[16806] = { name = "Centurion's Sword" , model = 24847} +models.main[16807] = { name = "Cmb.Cst. Scimitar" , model = 24833} +models.main[16808] = { name = "Wis.Wiz. Bilbo" , model = 24758} +models.main[16809] = { name = "Wis.Wiz. Anelace" , model = 24850} +models.main[16810] = { name = "Tct.Mag. Espadon" , model = 24856} +models.main[16811] = { name = "Dst. Sword +1" , model = 24843} +models.main[16812] = { name = "War Sword" , model = 24856} +models.main[16813] = { name = "Schlaeger +1" , model = 24762} +models.main[16814] = { name = "Crescent Sword" , model = 24836} +models.main[16815] = { name = "Mythril Degen +1" , model = 24765} +models.main[16816] = { name = "Holy Sword +1" , model = 24862} +models.main[16817] = { name = "Holy Degen +1" , model = 24765} +models.main[16818] = { name = "San d'Orian Sword" , model = 24827} +models.main[16819] = { name = "Mithran Scimitar" , model = 24832} +models.main[16820] = { name = "Strider Sword" , model = 24846} +models.main[16821] = { name = "Duel Rapier" , model = 24763} +models.main[16822] = { name = "Crimson Blade" , model = 24844} +models.main[16823] = { name = "Flame Degen +1" , model = 24764} +models.main[16824] = { name = "Carnage Rapier" , model = 24764} +models.main[16825] = { name = "Cermet Sword +1" , model = 24849} +models.main[16826] = { name = "Divine Sword +1" , model = 24852} +models.main[16827] = { name = "Carnage Blade" , model = 24838} +models.main[16828] = { name = "Bastard Sword +1" , model = 24855} +models.main[16829] = { name = "Fencing Degen" , model = 24764} +models.main[16830] = { name = "Gluttony Sword" , model = 24863} +models.main[16831] = { name = "Greed Scimitar" , model = 24858} +models.main[16832] = { name = "Harpoon" , model = 24784} +models.main[16833] = { name = "Bronze Spear" , model = 24781} +models.main[16834] = { name = "Brass Spear" , model = 24782} +models.main[16835] = { name = "Spear" , model = 24783} +models.main[16836] = { name = "Halberd" , model = 24778} +models.main[16837] = { name = "Trident" , model = 24792} +models.main[16838] = { name = "Tonbo-Giri" , model = 24790} +models.main[16839] = { name = "Partisan" , model = 24780} +models.main[16840] = { name = "Ox Tongue" , model = 24779} +models.main[16841] = { name = "Wyvern Spear" , model = 24791} +models.main[16842] = { name = "Golden Spear" , model = 24782} +models.main[16843] = { name = "Draconis Lance" , model = 24788} +models.main[16844] = { name = "Ryl.Sqr. Halberd" , model = 24778} +models.main[16845] = { name = "Lance" , model = 24786} +models.main[16846] = { name = "Bloody Lance" , model = 24785} +models.main[16847] = { name = "Mythril Lance" , model = 24787} +models.main[16848] = { name = "Darksteel Lance" , model = 24785} +models.main[16849] = { name = "Cermet Lance" , model = 24789} +models.main[16850] = { name = "Mercurial Spear" , model = 24783} +models.main[16851] = { name = "R.K. Army Lance" , model = 24786} +models.main[16852] = { name = "Ryl.Spr. Spear" , model = 24782} +models.main[16853] = { name = "Lizard Piercer" , model = 24783} +models.main[16854] = { name = "Vougier's Contus" , model = 25012} +models.main[16855] = { name = "Colossal Lance" , model = 24786} +models.main[16856] = { name = "Obelisk" , model = 24781} +models.main[16857] = { name = "Wind Spear" , model = 24783} +models.main[16858] = { name = "Sacred Lance" , model = 24786} +models.main[16859] = { name = "Bronze Spear +1" , model = 24781} +models.main[16860] = { name = "Holy Lance" , model = 24786} +models.main[16861] = { name = "Ice Lance" , model = 24789} +models.main[16862] = { name = "Harpoon +1" , model = 24784} +models.main[16863] = { name = "Cruel Spear" , model = 24783} +models.main[16864] = { name = "Brass Spear +1" , model = 24782} +models.main[16865] = { name = "Spear +1" , model = 24783} +models.main[16866] = { name = "Halberd +1" , model = 24778} +models.main[16867] = { name = "Orc Piercer" , model = 24784} +models.main[16868] = { name = "Heavy Halberd" , model = 24778} +models.main[16869] = { name = "Thundercloud" , model = 24782} +models.main[16870] = { name = "Envy Spear" , model = 24781} +models.main[16871] = { name = "Kamayari" , model = 24790} +models.main[16872] = { name = "Kamayari +1" , model = 24790} +models.main[16873] = { name = "Wyvern Spear +1" , model = 24791} +models.main[16874] = { name = "Partisan +1" , model = 24780} +models.main[16875] = { name = "Golden Spear +1" , model = 24782} +models.main[16876] = { name = "Lance +1" , model = 24786} +models.main[16877] = { name = "Mythril Lance +1" , model = 24787} +models.main[16878] = { name = "Dst. Lance +1" , model = 24785} +models.main[16879] = { name = "Cermet Lance +1" , model = 24789} +models.main[16880] = { name = "Holy Lance +1" , model = 24786} +models.main[16881] = { name = "Carnage Lance" , model = 24785} +models.main[16882] = { name = "Calamar" , model = 24792} +models.main[16883] = { name = "Monsoon Spear" , model = 24790} +models.main[16884] = { name = "Narval" , model = 24789} +models.main[16885] = { name = "Gae Bolg" , model = 24786} +models.main[16886] = { name = "Gnd.Kgt. Lance" , model = 24787} +models.main[16887] = { name = "Peregrine" , model = 24786} +models.main[16888] = { name = "Battle Fork" , model = 24792} +models.main[16889] = { name = "Battle Fork +1" , model = 24792} +models.main[16890] = { name = "Obelisk Lance" , model = 24946} +models.main[16891] = { name = "Obelisk Lance +1" , model = 24946} +models.main[16892] = { name = "Spear of Trials" , model = 24781} +models.main[16893] = { name = "Rsv.Cpt. Lance" , model = 24788} +models.main[16894] = { name = "Ox Tongue +1" , model = 24779} +models.main[16895] = { name = "Ice Lance +1" , model = 24789} +models.main[16896] = { name = "Kunai" , model = 24891} +models.main[16897] = { name = "Kageboshi" , model = 24890} +models.main[16898] = { name = "Cmb.Cst. Kusabi" , model = 24890} +models.main[16899] = { name = "Hototogisu" , model = 24891} +models.main[16900] = { name = "Wakizashi" , model = 24886} +models.main[16901] = { name = "Kodachi" , model = 24887} +models.main[16902] = { name = "Sakurafubuki" , model = 24888} +models.main[16903] = { name = "Kabutowari" , model = 24889} +models.main[16904] = { name = "Fudo" , model = 24885} +models.main[16905] = { name = "Bokuto" , model = 24886} +models.main[16906] = { name = "Mokuto" , model = 24886} +models.main[16907] = { name = "Busuto" , model = 24886} +models.main[16908] = { name = "Yoto" , model = 24886} +models.main[16909] = { name = "Kororito" , model = 24886} +models.main[16910] = { name = "Mamushito" , model = 24886} +models.main[16911] = { name = "Amanojaku" , model = 24886} +models.main[16912] = { name = "Kitsutsuki" , model = 24891} +models.main[16913] = { name = "Shinogi" , model = 24887} +models.main[16914] = { name = "Kunai +1" , model = 24891} +models.main[16915] = { name = "Hien" , model = 24891} +models.main[16916] = { name = "Hien +1" , model = 24891} +models.main[16917] = { name = "Suzume" , model = 24891} +models.main[16918] = { name = "Wakizashi +1" , model = 24886} +models.main[16919] = { name = "Shinobi-Gatana" , model = 24886} +models.main[16920] = { name = "Shinobi-Gatana +1" , model = 24886} +models.main[16921] = { name = "Kodachi +1" , model = 24887} +models.main[16922] = { name = "Sakurafubuki +1" , model = 24888} +models.main[16923] = { name = "Kabutowari +1" , model = 24889} +models.main[16924] = { name = "Hocho" , model = 24888} +models.main[16925] = { name = "Mokuto +1" , model = 24886} +models.main[16926] = { name = "Bokuto +1" , model = 24886} +models.main[16927] = { name = "Busuto +1" , model = 24886} +models.main[16928] = { name = "Hellfire Sword" , model = 24647} +models.main[16929] = { name = "Burning Claymore" , model = 24642} +models.main[16930] = { name = "Mrc. Greatsword" , model = 24642} +models.main[16931] = { name = "2-Hand. Sword +1" , model = 24647} +models.main[16932] = { name = "Greatsword +1" , model = 24648} +models.main[16933] = { name = "Dst. Claymore +1" , model = 24641} +models.main[16934] = { name = "Braveheart" , model = 24642} +models.main[16935] = { name = "Barbarian's Sword" , model = 24642} +models.main[16936] = { name = "Demonic Sword" , model = 24647} +models.main[16937] = { name = "Ice Brand" , model = 24648} +models.main[16938] = { name = "Glorious Sword" , model = 24644} +models.main[16939] = { name = "Ram-Dao +1" , model = 24651} +models.main[16940] = { name = "Gerwitz's Sword" , model = 24642} +models.main[16941] = { name = "Flamberge +1" , model = 24650} +models.main[16942] = { name = "Balmung" , model = 24897} +models.main[16943] = { name = "Ascalon" , model = 24649} +models.main[16944] = { name = "Lockheart" , model = 24643} +models.main[16945] = { name = "Arondight" , model = 24645} +models.main[16946] = { name = "Windurstian Sword" , model = 24642} +models.main[16947] = { name = "Federation Sword" , model = 24642} +models.main[16948] = { name = "Ryl.Swd. Blade +1" , model = 24648} +models.main[16949] = { name = "Ryl.Swd. Blade +2" , model = 24648} +models.main[16950] = { name = "Mythril Heart" , model = 24643} +models.main[16951] = { name = "Mythril Heart +1" , model = 24643} +models.main[16952] = { name = "Sword of Trials" , model = 24642} +models.main[16953] = { name = "Rsv.Cpt.Grt. sword" , model = 24640} +models.main[16954] = { name = "Pealing Nagan" , model = 24649} +models.main[16955] = { name = "Nagan +1" , model = 24649} +models.main[16956] = { name = "Skofnung" , model = 24645} +models.main[16957] = { name = "Faussar" , model = 24651} +models.main[16958] = { name = "Faussar +1" , model = 24651} +models.main[16959] = { name = "Platoon Sword" , model = 24647} +models.main[16960] = { name = "Uchigatana" , model = 24730} +models.main[16961] = { name = "Murasame" , model = 24731} +models.main[16962] = { name = "Ashura" , model = 24732} +models.main[16963] = { name = "Taimakuniyuki" , model = 24968} +models.main[16964] = { name = "Zanbato" , model = 24727} +models.main[16965] = { name = "Koryukagemitsu" , model = 24723} +models.main[16966] = { name = "Tachi" , model = 24721} +models.main[16967] = { name = "Mikazuki" , model = 24722} +models.main[16968] = { name = "Kamewari" , model = 24722} +models.main[16969] = { name = "Onikiri" , model = 24724} +models.main[16970] = { name = "Hosodachi" , model = 24723} +models.main[16971] = { name = "Yukitsugu" , model = 24899} +models.main[16972] = { name = "Kazaridachi" , model = 24899} +models.main[16973] = { name = "Homura" , model = 24721} +models.main[16974] = { name = "Dotanuki" , model = 24730} +models.main[16975] = { name = "Kanesada" , model = 24731} +models.main[16976] = { name = "Onimaru" , model = 24720} +models.main[16977] = { name = "Yukitsugu +1" , model = 24899} +models.main[16978] = { name = "Uchigatana +1" , model = 24730} +models.main[16979] = { name = "Ashura +1" , model = 24732} +models.main[16980] = { name = "Sukesada" , model = 24732} +models.main[16981] = { name = "Tachi +1" , model = 24721} +models.main[16982] = { name = "Nodachi" , model = 24721} +models.main[16983] = { name = "Nodachi +1" , model = 24721} +models.main[16984] = { name = "Jindachi" , model = 24721} +models.main[16985] = { name = "Jindachi +1" , model = 24721} +models.main[16986] = { name = "Homura +1" , model = 24721} +models.main[16987] = { name = "Okanehira" , model = 24721} +models.main[16988] = { name = "Kotetsu" , model = 24721} +models.main[16989] = { name = "Mikazuki +1" , model = 24722} +models.main[16990] = { name = "Daihannya" , model = 24722} +models.main[16991] = { name = "Odenta" , model = 24722} +models.main[17024] = { name = "Ash Club" , model = 24684} +models.main[17025] = { name = "Chestnut Club" , model = 24685} +models.main[17026] = { name = "Bone Cudgel" , model = 24677} +models.main[17027] = { name = "Oak Cudgel" , model = 24676} +models.main[17028] = { name = "Freesword's Club" , model = 24684} +models.main[17029] = { name = "Bouncer Club" , model = 24685} +models.main[17030] = { name = "Great Club" , model = 24687} +models.main[17031] = { name = "Shell Scepter" , model = 25168} +models.main[17032] = { name = "Gobbie Gavel" , model = 25169} +models.main[17033] = { name = "Bone Cudgel +1" , model = 24677} +models.main[17034] = { name = "Bronze Mace" , model = 24680} +models.main[17035] = { name = "Mace" , model = 24682} +models.main[17036] = { name = "Mythril Mace" , model = 24683} +models.main[17037] = { name = "Darksteel Mace" , model = 24679} +models.main[17038] = { name = "Buzdygan" , model = 24678} +models.main[17039] = { name = "Platinum Mace" , model = 24681} +models.main[17040] = { name = "Warp Cudgel" , model = 24676} +models.main[17041] = { name = "Holy Mace" , model = 24683} +models.main[17042] = { name = "Bronze Hammer" , model = 24689} +models.main[17043] = { name = "Brass Hammer" , model = 24690} +models.main[17044] = { name = "Warhammer" , model = 24691} +models.main[17045] = { name = "Maul" , model = 24692} +models.main[17046] = { name = "Darksteel Maul" , model = 24688} +models.main[17047] = { name = "Magnus Hammer" , model = 24692} +models.main[17048] = { name = "Decurion's Hammer" , model = 24691} +models.main[17049] = { name = "Maple Wand" , model = 24803} +models.main[17050] = { name = "Willow Wand" , model = 24808} +models.main[17051] = { name = "Yew Wand" , model = 24802} +models.main[17052] = { name = "Chestnut Wand" , model = 24807} +models.main[17053] = { name = "Rose Wand" , model = 24806} +models.main[17054] = { name = "Ebony Wand" , model = 24801} +models.main[17056] = { name = "Mythic Wand" , model = 24804} +models.main[17057] = { name = "Tefnut Wand" , model = 25108} +models.main[17058] = { name = "Caduceus" , model = 24809} +models.main[17059] = { name = "Bronze Rod" , model = 24796} +models.main[17060] = { name = "Rod" , model = 24798} +models.main[17061] = { name = "Mythril Rod" , model = 24799} +models.main[17062] = { name = "Bone Rod" , model = 24800} +models.main[17063] = { name = "Darksteel Rod" , model = 24795} +models.main[17064] = { name = "Scepter" , model = 24794} +models.main[17065] = { name = "Platinum Rod" , model = 24797} +models.main[17066] = { name = "Molva Maul" , model = 24690} +models.main[17067] = { name = "Ryl. Guard's Rod" , model = 24797} +models.main[17068] = { name = "Onion Rod" , model = 24796} +models.main[17069] = { name = "Moepapa Mace" , model = 24683} +models.main[17070] = { name = "Living Rod" , model = 24797} +models.main[17071] = { name = "Heat Rod" , model = 24796} +models.main[17072] = { name = "Lilith's Rod" , model = 24796} +models.main[17073] = { name = "Mistilteinn" , model = 24805} +models.main[17074] = { name = "Chocobo Wand" , model = 24812} +models.main[17075] = { name = "Star Rod" , model = 24816} +models.main[17076] = { name = "Earth Wand" , model = 24820} +models.main[17077] = { name = "Beneficus" , model = 24794} +models.main[17078] = { name = "Siriti" , model = 24809} +models.main[17079] = { name = "Winged Wand" , model = 24804} +models.main[17080] = { name = "Holy Maul" , model = 24692} +models.main[17081] = { name = "Brass Rod" , model = 24797} +models.main[17082] = { name = "Tct.Mag. Wand" , model = 24807} +models.main[17083] = { name = "Time Hammer" , model = 24691} +models.main[17085] = { name = "Holy Wand" , model = 24804} +models.main[17086] = { name = "Bronze Mace +1" , model = 24680} +models.main[17087] = { name = "Maple Wand +1" , model = 24803} +models.main[17088] = { name = "Ash Staff" , model = 24868} +models.main[17089] = { name = "Holly Staff" , model = 24866} +models.main[17090] = { name = "Elm Staff" , model = 24865} +models.main[17091] = { name = "Oak Staff" , model = 24867} +models.main[17092] = { name = "Mahogany Staff" , model = 24869} +models.main[17093] = { name = "Rune Staff" , model = 24881} +models.main[17094] = { name = "Wis.Wiz. Staff" , model = 24871} +models.main[17095] = { name = "Ash Pole" , model = 24878} +models.main[17096] = { name = "Holly Pole" , model = 24876} +models.main[17097] = { name = "Elm Pole" , model = 24875} +models.main[17098] = { name = "Oak Pole" , model = 24877} +models.main[17099] = { name = "Mahogany Pole" , model = 24880} +models.main[17100] = { name = "Ebony Pole" , model = 24874} +models.main[17101] = { name = "Mythic Pole" , model = 24879} +models.main[17102] = { name = "Eight-Sided Pole" , model = 24872} +models.main[17103] = { name = "Mercenary's Pole" , model = 24878} +models.main[17104] = { name = "Onion Staff" , model = 24867} +models.main[17105] = { name = "Soulscourge" , model = 24881} +models.main[17106] = { name = "Rockmasher" , model = 24873} +models.main[17108] = { name = "Healing Staff" , model = 24867} +models.main[17110] = { name = "Celeritas Pole" , model = 24873} +models.main[17111] = { name = "Bronze Rod +1" , model = 24796} +models.main[17112] = { name = "Fulcrum Pole" , model = 24937} +models.main[17113] = { name = "Owleyes" , model = 25100} +models.main[17114] = { name = "Holy Maul +1" , model = 24692} +models.main[17115] = { name = "Warhammer +1" , model = 24691} +models.main[17116] = { name = "Misery Staff" , model = 24870} +models.main[17117] = { name = "Hypno Staff" , model = 24866} +models.main[17118] = { name = "Lituus +1" , model = 24879} +models.main[17119] = { name = "Elm Pole +1" , model = 24875} +models.main[17120] = { name = "Oak Pole +1" , model = 24877} +models.main[17121] = { name = "Maul +1" , model = 24692} +models.main[17122] = { name = "Ash Pole +1" , model = 24878} +models.main[17123] = { name = "Ash Staff +1" , model = 24868} +models.main[17124] = { name = "Holly Pole +1" , model = 24876} +models.main[17125] = { name = "Holly Staff +1" , model = 24866} +models.main[17126] = { name = "Elm Staff +1" , model = 24865} +models.main[17127] = { name = "Oak Staff +1" , model = 24867} +models.main[17128] = { name = "Lgn. Staff" , model = 24870} +models.main[17129] = { name = "Musketeer's Pole" , model = 24880} +models.main[17130] = { name = "Freesword's Staff" , model = 24866} +models.main[17131] = { name = "Lituus" , model = 24879} +models.main[17132] = { name = "Monster Signa" , model = 24882} +models.main[17133] = { name = "Chanter's Staff" , model = 24869} +models.main[17134] = { name = "Dolphin Staff" , model = 24868} +models.main[17135] = { name = "Walrus Staff" , model = 24866} +models.main[17136] = { name = "Sloth Wand" , model = 24806} +models.main[17137] = { name = "Ash Club +1" , model = 24684} +models.main[17138] = { name = "Willow Wand +1" , model = 24808} +models.main[17139] = { name = "Solid Club" , model = 24685} +models.main[17140] = { name = "Yew Wand +1" , model = 24802} +models.main[17141] = { name = "Solid Wand" , model = 24807} +models.main[17142] = { name = "Oak Cudgel +1" , model = 24676} +models.main[17143] = { name = "Rose Wand +1" , model = 24806} +models.main[17144] = { name = "Bronze Hammer +1" , model = 24689} +models.main[17145] = { name = "Mace +1" , model = 24682} +models.main[17146] = { name = "Rod +1" , model = 24798} +models.main[17147] = { name = "Mythril Mace +1" , model = 24683} +models.main[17148] = { name = "Brass Rod +1" , model = 24797} +models.main[17149] = { name = "Brass Hammer +1" , model = 24690} +models.main[17150] = { name = "Ryl.Sqr. Mace" , model = 24682} +models.main[17151] = { name = "Msk.Cmd. Rod" , model = 24795} +models.main[17408] = { name = "Great Club +1" , model = 24687} +models.main[17409] = { name = "Mythril Rod +1" , model = 24799} +models.main[17410] = { name = "Bone Rod +1" , model = 24800} +models.main[17411] = { name = "Holy Mace +1" , model = 24683} +models.main[17412] = { name = "Wild Cudgel" , model = 24677} +models.main[17413] = { name = "Hermit's Wand" , model = 24808} +models.main[17414] = { name = "Pixie Mace" , model = 24683} +models.main[17415] = { name = "Shellbuster" , model = 24686} +models.main[17416] = { name = "Arcana Breaker" , model = 24689} +models.main[17417] = { name = "Rabbit Stick" , model = 24804} +models.main[17418] = { name = "Moonlight Wand" , model = 24804} +models.main[17419] = { name = "Artemis's Wand" , model = 24804} +models.main[17420] = { name = "Selene's Wand" , model = 24804} +models.main[17421] = { name = "Moonwatch Wand" , model = 24804} +models.main[17422] = { name = "Blessed Hammer" , model = 24691} +models.main[17423] = { name = "Casting Wand" , model = 24802} +models.main[17424] = { name = "Spiked Club" , model = 24872} +models.main[17425] = { name = "Spiked Club +1" , model = 24872} +models.main[17426] = { name = "Replica Maul" , model = 24692} +models.main[17427] = { name = "Ebony Wand +1" , model = 24801} +models.main[17428] = { name = "Darksteel Mace +1" , model = 24679} +models.main[17429] = { name = "Dominion Mace" , model = 24681} +models.main[17430] = { name = "Fey Wand" , model = 24824} +models.main[17431] = { name = "Platinum Mace +1" , model = 24681} +models.main[17432] = { name = "Darksteel Maul +1" , model = 24688} +models.main[17433] = { name = "Mythic Wand +1" , model = 24804} +models.main[17434] = { name = "Holy Wand +1" , model = 24804} +models.main[17435] = { name = "Darksteel Rod +1" , model = 24795} +models.main[17436] = { name = "Platinum Rod +1" , model = 24797} +models.main[17437] = { name = "Curse Wand" , model = 24818} +models.main[17438] = { name = "Titan's Cudgel" , model = 24676} +models.main[17439] = { name = "Leviathan's Rod" , model = 24797} +models.main[17440] = { name = "Kraken Club" , model = 24686} +models.main[17441] = { name = "Eremite's Wand" , model = 24808} +models.main[17442] = { name = "Eremite's Wand +1" , model = 24808} +models.main[17443] = { name = "Thoth's Wand" , model = 24804} +models.main[17444] = { name = "Windurstian Club" , model = 24684} +models.main[17445] = { name = "Federation Club" , model = 24684} +models.main[17446] = { name = "T.M. Wand +1" , model = 24807} +models.main[17447] = { name = "T.M. Wand +2" , model = 24807} +models.main[17448] = { name = "San d'Orian Mace" , model = 24682} +models.main[17449] = { name = "Kingdom Mace" , model = 24682} +models.main[17450] = { name = "Healing Mace" , model = 24680} +models.main[17451] = { name = "Morgenstern" , model = 24936} +models.main[17452] = { name = "Bastokan Hammer" , model = 24691} +models.main[17453] = { name = "Republic Hammer" , model = 24691} +models.main[17454] = { name = "Asklepios" , model = 24817} +models.main[17455] = { name = "Skirnir's Wand" , model = 24819} +models.main[17456] = { name = "Club of Trials" , model = 24684} +models.main[17457] = { name = "Snr.Msk. Rod" , model = 24794} +models.main[17458] = { name = "Rsv.Cpt. Mace" , model = 24681} +models.main[17459] = { name = "Scepter +1" , model = 24794} +models.main[17460] = { name = "Buzdygan +1" , model = 24678} +models.main[17461] = { name = "Rune Rod" , model = 24912} +models.main[17462] = { name = "Platoon Mace" , model = 24680} +models.main[17463] = { name = "Sealed Mace" , model = 24682} +models.main[17464] = { name = "Purgatory Mace" , model = 24679} +models.main[17465] = { name = "Mighty Cudgel" , model = 24676} +models.main[17466] = { name = "Dia Wand" , model = 24803} +models.main[17467] = { name = "Martial Wand" , model = 24818} +models.main[17468] = { name = "Raise Rod" , model = 24799} +models.main[17469] = { name = "Raise II Rod" , model = 24799} +models.main[17470] = { name = "Pealing Buzdygan" , model = 24678} +models.main[17471] = { name = "Horrent Mace" , model = 24679} +models.main[17472] = { name = "Cross-Counters" , model = 24705} +models.main[17473] = { name = "Torama Cesti" , model = 24702} +models.main[17474] = { name = "Grapnel" , model = 24576} +models.main[17475] = { name = "Dst. Katars +1" , model = 24694} +models.main[17476] = { name = "Cat Baghnakhs +1" , model = 24716} +models.main[17477] = { name = "Bone Patas +1" , model = 24715} +models.main[17478] = { name = "Beat Cesti" , model = 24703} +models.main[17479] = { name = "Behem. Cesti +1" , model = 24704} +models.main[17480] = { name = "Dmd. Knuckles +1" , model = 24711} +models.main[17481] = { name = "Kaiser Knuckles" , model = 24710} +models.main[17482] = { name = "Jamadhars +1" , model = 24696} +models.main[17483] = { name = "Venom Katars +1" , model = 24694} +models.main[17484] = { name = "Stun Jamadhars +1" , model = 24696} +models.main[17485] = { name = "Dragon Claws +1" , model = 24701} +models.main[17486] = { name = "Stun Claws +1" , model = 24701} +models.main[17487] = { name = "Corrosive Claws" , model = 24700} +models.main[17488] = { name = "Cermet Claws +1" , model = 24701} +models.main[17489] = { name = "Gold Patas +1" , model = 24713} +models.main[17490] = { name = "Feral Fangs" , model = 24715} +models.main[17491] = { name = "Spartan Cesti" , model = 24704} +models.main[17492] = { name = "Shiva's Claws" , model = 24701} +models.main[17493] = { name = "Tropical Punches" , model = 24702} +models.main[17494] = { name = "Trp. Punches +1" , model = 24702} +models.main[17495] = { name = "San d'Orian Cesti" , model = 24702} +models.main[17496] = { name = "Kingdom Cesti" , model = 24702} +models.main[17497] = { name = "Win. Baghnakhs" , model = 24716} +models.main[17498] = { name = "Fed. Baghnakhs" , model = 24716} +models.main[17499] = { name = "Bas. Knuckles" , model = 24707} +models.main[17500] = { name = "Republic Knuckles" , model = 24707} +models.main[17501] = { name = "T.M. Hooks +1" , model = 24715} +models.main[17502] = { name = "T.M. Hooks +2" , model = 24715} +models.main[17503] = { name = "Exocets" , model = 24697} +models.main[17504] = { name = "Pagures" , model = 24709} +models.main[17505] = { name = "Narasimha's Cesti" , model = 24702} +models.main[17506] = { name = "Vishnu's Cesti" , model = 24702} +models.main[17507] = { name = "Knuckles of Trials" , model = 24706} +models.main[17508] = { name = "Mst.Cst.Baghnakhs" , model = 24718} +models.main[17509] = { name = "Destroyers" , model = 24703} +models.main[17510] = { name = "Vampiric Claws" , model = 24698} +models.main[17511] = { name = "Indra Katars" , model = 24696} +models.main[17512] = { name = "Hydro Baghnakhs" , model = 24717} +models.main[17513] = { name = "Hyd.Baghnakhs +1" , model = 24717} +models.main[17514] = { name = "Hydro Claws" , model = 24699} +models.main[17515] = { name = "Hydro Claws +1" , model = 24699} +models.main[17516] = { name = "Hydro Patas" , model = 24715} +models.main[17517] = { name = "Hydro Patas +1" , model = 24715} +models.main[17518] = { name = "Manoples +1" , model = 24712} +models.main[17519] = { name = "Platoon Cesti" , model = 24703} +models.main[17520] = { name = "Heavy Staff" , model = 24869} +models.main[17521] = { name = "Mahogany Pole +1" , model = 24880} +models.main[17522] = { name = "Pride Staff" , model = 24870} +models.main[17523] = { name = "Quarterstaff" , model = 24872} +models.main[17524] = { name = "Footman's Staff" , model = 24872} +models.main[17525] = { name = "Ebony Pole +1" , model = 24874} +models.main[17526] = { name = "Mythic Pole +1" , model = 24879} +models.main[17527] = { name = "Pole of Trials" , model = 24878} +models.main[17528] = { name = "Astral Signa" , model = 24882} +models.main[17529] = { name = "Sunlight Pole" , model = 24875} +models.main[17530] = { name = "Mst.Cst. Pole" , model = 24877} +models.main[17531] = { name = "Ramuh's Staff" , model = 24865} +models.main[17532] = { name = "Kukulcan's Staff" , model = 24869} +models.main[17533] = { name = "Whale Staff" , model = 24868} +models.main[17534] = { name = "Whale Staff +1" , model = 24868} +models.main[17535] = { name = "Windurstian Pole" , model = 24878} +models.main[17536] = { name = "Federation Pole" , model = 24878} +models.main[17537] = { name = "Windurstian Staff" , model = 24866} +models.main[17538] = { name = "Federation Staff" , model = 24866} +models.main[17539] = { name = "Msk. Pole +1" , model = 24880} +models.main[17540] = { name = "Msk. Pole +2" , model = 24880} +models.main[17541] = { name = "Bastokan Staff" , model = 24870} +models.main[17542] = { name = "Republic Staff" , model = 24870} +models.main[17543] = { name = "Battle Staff" , model = 24872} +models.main[17544] = { name = "Battle Staff +1" , model = 24872} +models.main[17545] = { name = "Fire Staff" , model = 24905} +models.main[17546] = { name = "Vulcan's Staff" , model = 24905} +models.main[17547] = { name = "Ice Staff" , model = 24903} +models.main[17548] = { name = "Aquilo's Staff" , model = 24903} +models.main[17549] = { name = "Wind Staff" , model = 24902} +models.main[17550] = { name = "Auster's Staff" , model = 24902} +models.main[17551] = { name = "Earth Staff" , model = 24907} +models.main[17552] = { name = "Terra's Staff" , model = 24907} +models.main[17553] = { name = "Thunder Staff" , model = 24904} +models.main[17554] = { name = "Jupiter's Staff" , model = 24904} +models.main[17555] = { name = "Water Staff" , model = 24901} +models.main[17556] = { name = "Neptune's Staff" , model = 24901} +models.main[17557] = { name = "Light Staff" , model = 24906} +models.main[17558] = { name = "Apollo's Staff" , model = 24906} +models.main[17559] = { name = "Dark Staff" , model = 24900} +models.main[17560] = { name = "Pluto's Staff" , model = 24900} +models.main[17561] = { name = "Revenging Staff" , model = 24867} +models.main[17562] = { name = "Rvg. Staff +1" , model = 24867} +models.main[17563] = { name = "Power Staff" , model = 24871} +models.main[17564] = { name = "Cocytus Pole" , model = 24874} +models.main[17565] = { name = "Trick Staff" , model = 24908} +models.main[17566] = { name = "Treat Staff" , model = 24908} +models.main[17567] = { name = "Kirin's Pole" , model = 24876} +models.main[17568] = { name = "Eight-Sd. Pole +1" , model = 24872} +models.main[17569] = { name = "Iron-splitter" , model = 24917} +models.main[17570] = { name = "Iron-splitter +1" , model = 24917} +models.main[17571] = { name = "Platoon Pole" , model = 24875} +models.main[17572] = { name = "Dusky Staff" , model = 24868} +models.main[17573] = { name = "Himmel Stock" , model = 24866} +models.main[17574] = { name = "Archalaus's Pole" , model = 24880} +models.main[17575] = { name = "Somnus Signa" , model = 24882} +models.main[17576] = { name = "Grim Staff" , model = 24869} +models.main[17577] = { name = "Capricorn Staff" , model = 24867} +models.main[17578] = { name = "Zen Pole" , model = 24879} +models.main[17579] = { name = "Wyvern Perch" , model = 24874} +models.main[17580] = { name = "Military Pole" , model = 24875} +models.main[17581] = { name = "Mighty Pole" , model = 24876} +models.main[17582] = { name = "Prelatic Pole" , model = 24879} +models.main[17583] = { name = "Kgd. Signet Staff" , model = 24931} +models.main[17584] = { name = "Rep. Signet Staff" , model = 24933} +models.main[17585] = { name = "Fed. Signet Staff" , model = 24932} +models.main[17586] = { name = "Mercurial Pole" , model = 24879} +models.main[17587] = { name = "Trick Staff II" , model = 24908} +models.main[17588] = { name = "Treat Staff II" , model = 24908} +models.main[17589] = { name = "Thyrsusstab" , model = 24865} +models.main[17590] = { name = "Primate Staff" , model = 24937} +models.main[17591] = { name = "Primate Staff +1" , model = 24937} +models.main[17592] = { name = "Kinkobo" , model = 24937} +models.main[17593] = { name = "Martial Staff" , model = 24865} +models.main[17594] = { name = "Gelong Staff" , model = 24867} +models.main[17595] = { name = "Hope Staff" , model = 24881} +models.main[17596] = { name = "Steel-splitter" , model = 24917} +models.main[17597] = { name = "Dragon Staff" , model = 24869} +models.main[17598] = { name = "Bahamut's Staff" , model = 24869} +models.main[17599] = { name = "Diabolos's Pole" , model = 24874} +models.main[17600] = { name = "Stun Knife +1" , model = 24738} +models.main[17601] = { name = "Demon's Knife" , model = 24756} +models.main[17602] = { name = "Demon's Knife +1" , model = 24756} +models.main[17603] = { name = "Cermet Kukri +1" , model = 24750} +models.main[17604] = { name = "Venom Kukri +1" , model = 24747} +models.main[17605] = { name = "Acid Dagger" , model = 24743} +models.main[17606] = { name = "Corrosive Dagger" , model = 24743} +models.main[17607] = { name = "Corrosive Baselard" , model = 24746} +models.main[17608] = { name = "Corrosive Knife" , model = 24737} +models.main[17609] = { name = "Cermet Knife +1" , model = 24738} +models.main[17610] = { name = "Bone Knife" , model = 24756} +models.main[17611] = { name = "Bone Knife +1" , model = 24756} +models.main[17612] = { name = "Beetle Knife" , model = 24756} +models.main[17613] = { name = "Beetle Knife +1" , model = 24756} +models.main[17614] = { name = "Stun Kukri +1" , model = 24750} +models.main[17615] = { name = "Chicken Knife" , model = 24735} +models.main[17616] = { name = "Dagger of Trials" , model = 24740} +models.main[17617] = { name = "Mst.Cst. Knife" , model = 24756} +models.main[17618] = { name = "Kidney Dagger" , model = 24745} +models.main[17619] = { name = "Daylight Dagger" , model = 24746} +models.main[17620] = { name = "Misericorde +1" , model = 24739} +models.main[17621] = { name = "Gully +1" , model = 24733} +models.main[17622] = { name = "Buccaneer's Knife" , model = 24749} +models.main[17623] = { name = "Btm. Knife" , model = 24749} +models.main[17624] = { name = "Anubis's Knife" , model = 24733} +models.main[17625] = { name = "Ponderous Gully" , model = 24733} +models.main[17626] = { name = "Auric Dagger" , model = 25093} +models.main[17627] = { name = "Garuda's Dagger" , model = 24742} +models.main[17628] = { name = "Behemoth Knife" , model = 24756} +models.main[17629] = { name = "Behem. Knife +1" , model = 24756} +models.main[17630] = { name = "Hawker's Knife" , model = 24737} +models.main[17631] = { name = "Hawker's Knife +1" , model = 24737} +models.main[17632] = { name = "Colichemarde +1" , model = 24757} +models.main[17633] = { name = "Rapier +1" , model = 24763} +models.main[17634] = { name = "Wasp Fleuret" , model = 24769} +models.main[17635] = { name = "Schwert +1" , model = 24768} +models.main[17636] = { name = "Jagdplaute +1" , model = 24845} +models.main[17637] = { name = "Wing Sword +1" , model = 24864} +models.main[17638] = { name = "Katzbalger +1" , model = 24851} +models.main[17639] = { name = "Cutlass +1" , model = 24839} +models.main[17640] = { name = "Ptm. Cutlass +1" , model = 24837} +models.main[17641] = { name = "Gold Sword +1" , model = 24826} +models.main[17642] = { name = "Hanger +1" , model = 24834} +models.main[17643] = { name = "Honor Sword" , model = 24828} +models.main[17644] = { name = "Judge's Sword" , model = 24966} +models.main[17645] = { name = "Espadon +1" , model = 24857} +models.main[17646] = { name = "Carnage Sword" , model = 24843} +models.main[17647] = { name = "Aramis's Rapier" , model = 24763} +models.main[17648] = { name = "Dragvandil" , model = 24856} +models.main[17649] = { name = "Nightmare Sword" , model = 24843} +models.main[17650] = { name = "Nadrs" , model = 24858} +models.main[17651] = { name = "Dainslaif" , model = 24848} +models.main[17652] = { name = "Joyeuse" , model = 24761} +models.main[17653] = { name = "Hrotti" , model = 24854} +models.main[17654] = { name = "Sapara of Trials" , model = 24831} +models.main[17655] = { name = "Snr.Msk. Scimitar" , model = 24837} +models.main[17656] = { name = "Verdun +1" , model = 24761} +models.main[17657] = { name = "Anelace +1" , model = 24850} +models.main[17658] = { name = "Tutelary" , model = 24760} +models.main[17659] = { name = "Seiryu's Sword" , model = 24835} +models.main[17660] = { name = "Kilij" , model = 24951} +models.main[17661] = { name = "Storm Scimitar" , model = 24858} +models.main[17662] = { name = "Company Sword" , model = 24857} +models.main[17663] = { name = "Kilij +1" , model = 24951} +models.main[17664] = { name = "Firmament" , model = 24853} +models.main[17665] = { name = "Ifrit's Blade" , model = 24831} +models.main[17666] = { name = "Jr.Msk. Tuck +1" , model = 24760} +models.main[17667] = { name = "Jr.Msk. Tuck +2" , model = 24760} +models.main[17668] = { name = "Firmament +1" , model = 24853} +models.main[17669] = { name = "Sagasinger" , model = 25104} +models.main[17670] = { name = "T.K. Sword +1" , model = 24827} +models.main[17671] = { name = "T.K. Sword +2" , model = 24827} +models.main[17672] = { name = "Bastokan Sword" , model = 24847} +models.main[17673] = { name = "Republic Sword" , model = 24847} +models.main[17674] = { name = "Cmb.Cst.Scmtr. +1" , model = 24833} +models.main[17675] = { name = "Cmb.Cst.Scmtr. +2" , model = 24833} +models.main[17676] = { name = "T.M. Espadon +1" , model = 24856} +models.main[17677] = { name = "T.M. Espadon +2" , model = 24856} +models.main[17678] = { name = "San d'Orian Sword" , model = 24841} +models.main[17679] = { name = "Kingdom Sword" , model = 24841} +models.main[17680] = { name = "Msk. Sword +1" , model = 24764} +models.main[17681] = { name = "Msk. Sword +2" , model = 24764} +models.main[17682] = { name = "Sacred Sword" , model = 24862} +models.main[17683] = { name = "Sacred Degen" , model = 24765} +models.main[17684] = { name = "Griffinclaw" , model = 24826} +models.main[17685] = { name = "Lex Talionis" , model = 24760} +models.main[17686] = { name = "Spark Bilbo" , model = 24760} +models.main[17687] = { name = "Spark Bilbo +1" , model = 24760} +models.main[17688] = { name = "Spark Degen" , model = 24765} +models.main[17689] = { name = "Spark Degen +1" , model = 24765} +models.main[17690] = { name = "Spark Rapier" , model = 24763} +models.main[17691] = { name = "Spark Rapier +1" , model = 24763} +models.main[17692] = { name = "Platoon Spatha" , model = 24825} +models.main[17693] = { name = "Grudge Sword" , model = 24828} +models.main[17694] = { name = "Guespiere" , model = 24762} +models.main[17695] = { name = "Bayard's Sword" , model = 24849} +models.main[17696] = { name = "Buzzard Tuck" , model = 24760} +models.main[17697] = { name = "Mighty Talwar" , model = 24833} +models.main[17698] = { name = "Princely Sword" , model = 24854} +models.main[17699] = { name = "Dissector" , model = 24861} +models.main[17700] = { name = "Durandal" , model = 24853} +models.main[17701] = { name = "Shotel" , model = 24934} +models.main[17702] = { name = "Shotel +1" , model = 24934} +models.main[17703] = { name = "Pealing Anelace" , model = 24850} +models.main[17704] = { name = "Vulcan Sword" , model = 24844} +models.main[17705] = { name = "Vulcan Degen" , model = 24764} +models.main[17706] = { name = "Vulcan Blade" , model = 24839} +models.main[17707] = { name = "Martial Anelace" , model = 24850} +models.main[17708] = { name = "Auriga Xiphos" , model = 24840} +models.main[17709] = { name = "Swan Bilbo" , model = 24757} +models.main[17710] = { name = "Justice Sword" , model = 24830} +models.main[17711] = { name = "Shiva's Shotel" , model = 24934} +models.main[17712] = { name = "Kaskara +1" , model = 24854} +models.main[17713] = { name = "Macuahuitl" , model = 24957} +models.main[17714] = { name = "Macuahuitl +1" , model = 24957} +models.main[17715] = { name = "Storm Tulwar" , model = 24833} +models.main[17716] = { name = "Macuahuitl -1" , model = 24957} +models.main[17717] = { name = "Immortal's Scimitar" , model = 24858} +models.main[17718] = { name = "Leech Scimitar" , model = 24832} +models.main[17719] = { name = "Mensur Epee" , model = 24769} +models.main[17720] = { name = "Company Fleuret" , model = 24767} +models.main[17721] = { name = "Sanguine Sword" , model = 24966} +models.main[17722] = { name = "Phantom Fleuret" , model = 24767} +models.main[17723] = { name = "Singh Kilij" , model = 24951} +models.main[17724] = { name = "Darksteel Kilij" , model = 24958} +models.main[17725] = { name = "Darksteel Kilij +1" , model = 24958} +models.main[17726] = { name = "Immortal's Shotel" , model = 24934} +models.main[17727] = { name = "Adaman Kilij" , model = 24960} +models.main[17728] = { name = "Adaman Kilij +1" , model = 24960} +models.main[17729] = { name = "Vermin Slayer" , model = 24958} +models.main[17730] = { name = "Insect Slayer" , model = 24958} +models.main[17731] = { name = "Aquan Slayer" , model = 24958} +models.main[17732] = { name = "Marine Slayer" , model = 24958} +models.main[17733] = { name = "Dragon Slayer" , model = 24960} +models.main[17734] = { name = "Wyrm Slayer" , model = 24960} +models.main[17735] = { name = "Demon Slayer" , model = 24960} +models.main[17736] = { name = "Devil Slayer" , model = 24960} +models.main[17737] = { name = "Corsair's Scimitar" , model = 24832} +models.main[17738] = { name = "Hauteclaire" , model = 24975} +models.main[17739] = { name = "Steel Kilij" , model = 24978} +models.main[17740] = { name = "Steel Kilij +1" , model = 24978} +models.main[17741] = { name = "Perdu Hanger" , model = 24834} +models.main[17742] = { name = "Vorpal Sword" , model = 24767} +models.main[17743] = { name = "Wightslayer" , model = 24951} +models.main[17744] = { name = "Brave Blade" , model = 24857} +models.main[17745] = { name = "Hofud" , model = 24980} +models.main[17746] = { name = "Cermet Kilij" , model = 24978} +models.main[17747] = { name = "Cermet Kilij +1" , model = 24978} +models.main[17748] = { name = "Ibushi Shinai" , model = 24988} +models.main[17749] = { name = "Ibushi Shinai +1" , model = 24988} +models.main[17750] = { name = "Anthos Xiphos" , model = 24840} +models.main[17751] = { name = "Fragarach" , model = 25007} +models.main[17753] = { name = "Organics" , model = 25021} +models.main[17754] = { name = "Sylphid Epee" , model = 24766} +models.main[17755] = { name = "Beast Slayer" , model = 24978} +models.main[17756] = { name = "Sinfender" , model = 24832} +models.main[17757] = { name = "Merveilleuse" , model = 24826} +models.main[17758] = { name = "Ruler" , model = 24829} +models.main[17759] = { name = "Koggelmander" , model = 24842} +models.main[17760] = { name = "Buc. Scimitar" , model = 24834} +models.main[17761] = { name = "Oberon's Rapier" , model = 24763} +models.main[17762] = { name = "Erlking's Sword" , model = 24851} +models.main[17763] = { name = "Erlking's Blade" , model = 24836} +models.main[17764] = { name = "Trainee Sword" , model = 24829} +models.main[17765] = { name = "Concordia" , model = 25036} +models.main[17766] = { name = "Lyft Scimitar" , model = 24831} +models.main[17767] = { name = "Chipped Scimitar" , model = 24832} +models.main[17768] = { name = "Yoto +1" , model = 24886} +models.main[17769] = { name = "Kororito +1" , model = 24886} +models.main[17770] = { name = "Mamushito +1" , model = 24886} +models.main[17771] = { name = "Anju" , model = 24891} +models.main[17772] = { name = "Zushio" , model = 24887} +models.main[17773] = { name = "Kodachi of Trials" , model = 24887} +models.main[17774] = { name = "Shiranui" , model = 24889} +models.main[17775] = { name = "Fukuro" , model = 24890} +models.main[17776] = { name = "Hibari" , model = 24891} +models.main[17777] = { name = "Hibari +1" , model = 24891} +models.main[17778] = { name = "Muketsu" , model = 24888} +models.main[17779] = { name = "Muketsu +1" , model = 24888} +models.main[17780] = { name = "Kyofu" , model = 24886} +models.main[17781] = { name = "Kyofu +1" , model = 24886} +models.main[17782] = { name = "Reppu" , model = 24887} +models.main[17783] = { name = "Reppu +1" , model = 24887} +models.main[17784] = { name = "Keppu" , model = 24888} +models.main[17785] = { name = "Keppu +1" , model = 24888} +models.main[17786] = { name = "Ganko" , model = 24890} +models.main[17787] = { name = "Ohaguro" , model = 24890} +models.main[17788] = { name = "Sairen" , model = 24888} +models.main[17789] = { name = "Unsho" , model = 24888} +models.main[17790] = { name = "Unji" , model = 24888} +models.main[17791] = { name = "Rai Kunimitsu" , model = 24887} +models.main[17792] = { name = "Nikkariaoe" , model = 24888} +models.main[17793] = { name = "Senjuinrikio" , model = 24889} +models.main[17794] = { name = "Niokiyotsuna" , model = 24887} +models.main[17795] = { name = "Sai" , model = 24943} +models.main[17796] = { name = "Sai +1" , model = 24943} +models.main[17797] = { name = "Seito" , model = 24886} +models.main[17798] = { name = "Shamo" , model = 24889} +models.main[17799] = { name = "Imanotsurugi" , model = 24947} +models.main[17800] = { name = "Hosodachi +1" , model = 24723} +models.main[17801] = { name = "Kikugosaku" , model = 25016} +models.main[17802] = { name = "Kiku-Ichimonji" , model = 24723} +models.main[17803] = { name = "Zanbato +1" , model = 24727} +models.main[17804] = { name = "Ushikirimaru" , model = 24727} +models.main[17805] = { name = "Kazaridachi +1" , model = 24899} +models.main[17806] = { name = "Asa-arashi" , model = 24899} +models.main[17807] = { name = "Gld.Msk. Uchigat." , model = 24731} +models.main[17808] = { name = "Scathacha" , model = 25099} +models.main[17809] = { name = "Mumeito" , model = 24730} +models.main[17810] = { name = "Futsuno Mitama" , model = 24916} +models.main[17811] = { name = "Katayama" , model = 24722} +models.main[17812] = { name = "Magoroku" , model = 24722} +models.main[17813] = { name = "Soboro Sukehiro" , model = 24731} +models.main[17814] = { name = "Raikiri" , model = 24720} +models.main[17815] = { name = "Tachi of Trials" , model = 24721} +models.main[17816] = { name = "Kotetsu +1" , model = 24721} +models.main[17817] = { name = "Shinkotetsu" , model = 24721} +models.main[17818] = { name = "Kanesada +1" , model = 24731} +models.main[17819] = { name = "Shinkanesada" , model = 24731} +models.main[17820] = { name = "Gunromaru" , model = 24730} +models.main[17821] = { name = "Kagehide" , model = 24723} +models.main[17822] = { name = "Omokage" , model = 24722} +models.main[17823] = { name = "Shinsoku" , model = 24899} +models.main[17824] = { name = "Nukemaru" , model = 24720} +models.main[17825] = { name = "Honebami" , model = 24732} +models.main[17826] = { name = "Messhikimaru" , model = 24899} +models.main[17827] = { name = "Michishiba" , model = 24732} +models.main[17828] = { name = "Koen" , model = 24721} +models.main[17829] = { name = "Hagun" , model = 24727} +models.main[17830] = { name = "Wooden Katana" , model = 24944} +models.main[17831] = { name = "Hardwood Katana" , model = 24944} +models.main[17924] = { name = "Tungi" , model = 24667} +models.main[17925] = { name = "Fransisca" , model = 24667} +models.main[17926] = { name = "Acha d'Armas" , model = 24657} +models.main[17927] = { name = "Lohar" , model = 24662} +models.main[17928] = { name = "Juggernaut" , model = 24667} +models.main[17929] = { name = "Bastokan Axe" , model = 24654} +models.main[17930] = { name = "Republic Axe" , model = 24654} +models.main[17931] = { name = "Cmb.Cst. Axe +1" , model = 24659} +models.main[17932] = { name = "Cmb.Cst. Axe +2" , model = 24659} +models.main[17933] = { name = "Pick of Trials" , model = 24666} +models.main[17934] = { name = "Rsv.Cpt. Pick" , model = 24662} +models.main[17935] = { name = "Tabarzin +1" , model = 24657} +models.main[17936] = { name = "De Saintre's Axe" , model = 24652} +models.main[17937] = { name = "Leopard Axe" , model = 24653} +models.main[17938] = { name = "Woodville's Axe" , model = 24659} +models.main[17939] = { name = "Kriegsbeil" , model = 24667} +models.main[17940] = { name = "Military Pick" , model = 24664} +models.main[17941] = { name = "Mighty Pick" , model = 24663} +models.main[17942] = { name = "Tomahawk" , model = 24929} +models.main[17943] = { name = "Tomahawk +1" , model = 24929} +models.main[17944] = { name = "Retributor" , model = 24929} +models.main[17945] = { name = "Martial Axe" , model = 24652} +models.main[17946] = { name = "Maneater" , model = 24658} +models.main[17947] = { name = "Garde Pick" , model = 24665} +models.main[17948] = { name = "Temperance Axe" , model = 24661} +models.main[17949] = { name = "Furnace Tabarzin" , model = 24657} +models.main[17950] = { name = "Marid Ancus" , model = 24662} +models.main[17951] = { name = "Storm Tabar" , model = 24658} +models.main[17952] = { name = "Sirius Axe" , model = 24963} +models.main[17953] = { name = "Zoraal Ja's Axe" , model = 24929} +models.main[17954] = { name = "Jolt Axe" , model = 24652} +models.main[17955] = { name = "Plain Pick" , model = 24664} +models.main[17956] = { name = "Double Axe" , model = 24660} +models.main[17957] = { name = "Navy Axe" , model = 24655} +models.main[17958] = { name = "Iron Ram Pick" , model = 24664} +models.main[17959] = { name = "Viperine Pick" , model = 24664} +models.main[17960] = { name = "Labrys" , model = 25009} +models.main[17961] = { name = "Lion Tamer" , model = 24664} +models.main[17962] = { name = "Fleetwing" , model = 24660} +models.main[17963] = { name = "Rainmaker" , model = 24929} +models.main[17964] = { name = "Barkborer" , model = 24666} +models.main[17965] = { name = "Sirocco Axe" , model = 24655} +models.main[17966] = { name = "Erlking's Tabar" , model = 24658} +models.main[17967] = { name = "Felling Axe" , model = 24653} +models.main[17968] = { name = "Veldt Axe" , model = 24653} +models.main[17969] = { name = "Fendoir" , model = 24652} +models.main[17970] = { name = "Lyft Tabar" , model = 24657} +models.main[17971] = { name = "Tartaglia" , model = 24655} +models.main[17972] = { name = "San. Dagger" , model = 24743} +models.main[17973] = { name = "Kingdom Dagger" , model = 24743} +models.main[17974] = { name = "Bastokan Dagger" , model = 24743} +models.main[17975] = { name = "Republic Dagger" , model = 24743} +models.main[17976] = { name = "Windurstian Knife" , model = 24736} +models.main[17977] = { name = "Federation Knife" , model = 24736} +models.main[17978] = { name = "Windurstian Kukri" , model = 24748} +models.main[17979] = { name = "Federation Kukri" , model = 24748} +models.main[17980] = { name = "Hornetneedle" , model = 24739} +models.main[17981] = { name = "Bano del Sol" , model = 24753} +models.main[17982] = { name = "Kard" , model = 24893} +models.main[17983] = { name = "Valiant Knife" , model = 24733} +models.main[17984] = { name = "Spark Dagger" , model = 24742} +models.main[17985] = { name = "Spark Dagger +1" , model = 24742} +models.main[17986] = { name = "Spark Baselard" , model = 24746} +models.main[17987] = { name = "Spark Baselard +1" , model = 24746} +models.main[17988] = { name = "Spark Kris" , model = 24754} +models.main[17989] = { name = "Spark Kris +1" , model = 24754} +models.main[17990] = { name = "Cmb.Cst.Dagger +1" , model = 24753} +models.main[17991] = { name = "Cmb.Cst.Dagger +2" , model = 24753} +models.main[17992] = { name = "Triton's Dagger" , model = 24755} +models.main[17993] = { name = "Platoon Dagger" , model = 24741} +models.main[17994] = { name = "Calveley's Dagger" , model = 24971} +models.main[17995] = { name = "Jongleur's Dagger" , model = 24740} +models.main[17996] = { name = "Stylet" , model = 24745} +models.main[17997] = { name = "Argent Dagger" , model = 24922} +models.main[17998] = { name = "Thanatos Baselard" , model = 24744} +models.main[17999] = { name = "Taillefer's Dagger" , model = 24755} +models.main[18000] = { name = "Mighty Knife" , model = 24734} +models.main[18001] = { name = "Harpe" , model = 24930} +models.main[18002] = { name = "Perseus's Harpe" , model = 24930} +models.main[18003] = { name = "Swordbreaker" , model = 24751} +models.main[18004] = { name = "Trailer's Kukri" , model = 24750} +models.main[18005] = { name = "Heart Snatcher" , model = 24751} +models.main[18006] = { name = "Hoplites Harpe" , model = 24930} +models.main[18007] = { name = "Chiroptera Dagger" , model = 24922} +models.main[18008] = { name = "Hushed Dagger" , model = 24741} +models.main[18009] = { name = "Martial Knife" , model = 24734} +models.main[18010] = { name = "Melt Dagger" , model = 24743} +models.main[18011] = { name = "Melt Knife" , model = 24737} +models.main[18012] = { name = "Melt Baselard" , model = 24746} +models.main[18013] = { name = "Melt Kukri" , model = 24749} +models.main[18014] = { name = "Odorous Knife" , model = 24893} +models.main[18015] = { name = "Blau Dolch" , model = 24739} +models.main[18016] = { name = "Odorous Knife +1" , model = 24893} +models.main[18017] = { name = "Asn. Jambiya" , model = 24955} +models.main[18018] = { name = "Sirocco Kukri" , model = 24747} +models.main[18019] = { name = "X's Knife" , model = 24756} +models.main[18020] = { name = "Mercurial Kris" , model = 24754} +models.main[18021] = { name = "Titan's Baselarde" , model = 24745} +models.main[18022] = { name = "Adaman Kris +1" , model = 24753} +models.main[18023] = { name = "Jambiya" , model = 24955} +models.main[18024] = { name = "Jambiya +1" , model = 24955} +models.main[18025] = { name = "Khanjar" , model = 24753} +models.main[18026] = { name = "Magnet Knife" , model = 24734} +models.main[18027] = { name = "Palladium Dagger" , model = 24971} +models.main[18028] = { name = "Matron's Knife" , model = 24972} +models.main[18029] = { name = "Piercing Dagger" , model = 24741} +models.main[18030] = { name = "Khimaira Jambiya" , model = 24974} +models.main[18031] = { name = "Amir Jambiya" , model = 24974} +models.main[18032] = { name = "Adder Jambiya" , model = 24974} +models.main[18033] = { name = "Adder Jambiya +1" , model = 24974} +models.main[18034] = { name = "Dancing Dagger" , model = 24922} +models.main[18035] = { name = "Deathbone Knife" , model = 24756} +models.main[18036] = { name = "Win. Scythe" , model = 24770} +models.main[18037] = { name = "Federation Scythe" , model = 24770} +models.main[18038] = { name = "Bastokan Scythe" , model = 24774} +models.main[18039] = { name = "Republic Scythe" , model = 24774} +models.main[18040] = { name = "Webcutter" , model = 24771} +models.main[18041] = { name = "A l'Outrance" , model = 24777} +models.main[18042] = { name = "Ascention" , model = 24898} +models.main[18043] = { name = "Suzaku's Scythe" , model = 24773} +models.main[18044] = { name = "Scarecrow Scythe" , model = 24772} +models.main[18045] = { name = "Platoon Zaghnal" , model = 24773} +models.main[18046] = { name = "Mutilator" , model = 24772} +models.main[18047] = { name = "Havoc Scythe" , model = 24777} +models.main[18048] = { name = "King Maker" , model = 24921} +models.main[18049] = { name = "Mighty Zaghnal" , model = 24921} +models.main[18050] = { name = "Mandibular Sickle" , model = 24926} +models.main[18051] = { name = "Antlion Sickle" , model = 24926} +models.main[18052] = { name = "Tredecim Scythe" , model = 24777} +models.main[18053] = { name = "Gravedigger" , model = 24926} +models.main[18054] = { name = "Ivory Sickle" , model = 24942} +models.main[18055] = { name = "Ivory Sickle +1" , model = 24942} +models.main[18056] = { name = "Martial Scythe" , model = 24770} +models.main[18057] = { name = "Y's Scythe" , model = 24777} +models.main[18058] = { name = "Orichalcum Scythe" , model = 24948} +models.main[18059] = { name = "Triton's Scythe" , model = 24948} +models.main[18060] = { name = "Blizzard Scythe" , model = 24948} +models.main[18061] = { name = "Bahamut Zaghnal" , model = 24776} +models.main[18062] = { name = "Lucent Scythe" , model = 24770} +models.main[18063] = { name = "Garuda's Sickle" , model = 24942} +models.main[18064] = { name = "Volunt. Scythe" , model = 24772} +models.main[18065] = { name = "Storm Zaghnal" , model = 24921} +models.main[18066] = { name = "Blackjack" , model = 24926} +models.main[18067] = { name = "Keen Zaghnal" , model = 24774} +models.main[18068] = { name = "San d'Orian Spear" , model = 24781} +models.main[18069] = { name = "Kingdom Spear" , model = 24781} +models.main[18070] = { name = "San. Halberd" , model = 24778} +models.main[18071] = { name = "Kingdom Halberd" , model = 24778} +models.main[18072] = { name = "R.K. Lance +1" , model = 24786} +models.main[18073] = { name = "R.K. Lance +2" , model = 24786} +models.main[18074] = { name = "Iron Ram Lance" , model = 24788} +models.main[18075] = { name = "Rossignol" , model = 24783} +models.main[18076] = { name = "Spark Spear" , model = 24782} +models.main[18077] = { name = "Spark Spear +1" , model = 24782} +models.main[18078] = { name = "Spark Lance" , model = 24946} +models.main[18079] = { name = "Spark Lance +1" , model = 24946} +models.main[18080] = { name = "Spark Fork" , model = 24792} +models.main[18081] = { name = "Spark Fork +1" , model = 24792} +models.main[18082] = { name = "Barchha" , model = 24788} +models.main[18083] = { name = "Barchha +1" , model = 24788} +models.main[18084] = { name = "Rune Halberd" , model = 24913} +models.main[18085] = { name = "Platoon Lance" , model = 24787} +models.main[18086] = { name = "Behourd Lance" , model = 24787} +models.main[18087] = { name = "Schwarz Lance" , model = 24786} +models.main[18088] = { name = "Dreizack" , model = 24792} +models.main[18089] = { name = "Schiltron Spear" , model = 24780} +models.main[18090] = { name = "Military Spear" , model = 24783} +models.main[18091] = { name = "Mighty Lance" , model = 24789} +models.main[18092] = { name = "Bourdonasse" , model = 24786} +models.main[18093] = { name = "Couse" , model = 24925} +models.main[18094] = { name = "Couse +1" , model = 24925} +models.main[18095] = { name = "Dispel Couse" , model = 24925} +models.main[18096] = { name = "Heavy Lance" , model = 24786} +models.main[18097] = { name = "Gondo-Shizunori" , model = 24925} +models.main[18098] = { name = "Martial Lance" , model = 24788} +models.main[18099] = { name = "Stone-splitter" , model = 24925} +models.main[18100] = { name = "Love Halberd" , model = 24913} +models.main[18101] = { name = "Z's Trident" , model = 24792} +models.main[18102] = { name = "Pitchfork" , model = 24945} +models.main[18103] = { name = "Pitchfork +1" , model = 24945} +models.main[18104] = { name = "Fuscina" , model = 24792} +models.main[18105] = { name = "Orichalcum Lance" , model = 24946} +models.main[18106] = { name = "Triton's Lance" , model = 24946} +models.main[18107] = { name = "Ponderous Lance" , model = 24946} +models.main[18108] = { name = "Lucent Lance" , model = 24786} +models.main[18109] = { name = "Leviathan's Couse" , model = 24925} +models.main[18110] = { name = "Mezraq" , model = 24954} +models.main[18111] = { name = "Mezraq +1" , model = 24954} +models.main[18112] = { name = "Puk Lance" , model = 24787} +models.main[18113] = { name = "Imperial Neza" , model = 24788} +models.main[18114] = { name = "Tournament Lance" , model = 24786} +models.main[18115] = { name = "Engetsuto" , model = 24967} +models.main[18116] = { name = "Engetsuto +1" , model = 24967} +models.main[18117] = { name = "Gimlet Spear" , model = 24782} +models.main[18118] = { name = "Dark Mezraq" , model = 24964} +models.main[18119] = { name = "Dark Mezraq +1" , model = 24964} +models.main[18120] = { name = "Radiant Lance" , model = 24946} +models.main[18121] = { name = "Valkyrie's Fork" , model = 24981} +models.main[18122] = { name = "Broach Lance" , model = 24786} +models.main[18123] = { name = "Thalassocrat" , model = 24984} +models.main[18124] = { name = "Thalassocrat +1" , model = 24984} +models.main[18125] = { name = "Cletine" , model = 25012} +models.main[18126] = { name = "Tomoe" , model = 25020} +models.main[18127] = { name = "Achilles' Spear" , model = 24789} +models.main[18128] = { name = "Skystrider" , model = 24787} +models.main[18129] = { name = "Dabo" , model = 25029} +models.main[18130] = { name = "Dabo +1" , model = 25029} +models.main[18131] = { name = "Zaide" , model = 25028} +models.main[18196] = { name = "Snr.Msk. Axe" , model = 24668} +models.main[18197] = { name = "Bhuj +1" , model = 24672} +models.main[18198] = { name = "Byakko's Axe" , model = 24674} +models.main[18199] = { name = "Ulfhedinn Axe" , model = 24671} +models.main[18200] = { name = "Hydro Axe" , model = 24671} +models.main[18201] = { name = "Hydro Axe +1" , model = 24671} +models.main[18202] = { name = "Hydro Cutter" , model = 24670} +models.main[18203] = { name = "Hydro Cutter +1" , model = 24670} +models.main[18204] = { name = "Hydro Chopper" , model = 24669} +models.main[18205] = { name = "Hydro Chopper +1" , model = 24669} +models.main[18206] = { name = "Rune Chopper" , model = 24911} +models.main[18207] = { name = "Kheten" , model = 24673} +models.main[18208] = { name = "Kheten +1" , model = 24673} +models.main[18209] = { name = "Platoon Cutter" , model = 24670} +models.main[18210] = { name = "Raifu" , model = 24673} +models.main[18211] = { name = "Gawain's Axe" , model = 24674} +models.main[18212] = { name = "Military Axe" , model = 24671} +models.main[18213] = { name = "Mighty Axe" , model = 24670} +models.main[18214] = { name = "Voulge" , model = 24924} +models.main[18215] = { name = "Voulge +1" , model = 24924} +models.main[18216] = { name = "Twicer" , model = 24924} +models.main[18217] = { name = "Rampager" , model = 24924} +models.main[18218] = { name = "Leucous Voulge" , model = 24941} +models.main[18219] = { name = "Lcs. Voulge +1" , model = 24941} +models.main[18220] = { name = "Prominence Axe" , model = 24670} +models.main[18221] = { name = "Martial Bhuj" , model = 24672} +models.main[18222] = { name = "Fortitude Axe" , model = 24911} +models.main[18223] = { name = "Toporok" , model = 24668} +models.main[18224] = { name = "Toporok +1" , model = 24668} +models.main[18225] = { name = "Blizzard Toporok" , model = 24668} +models.main[18226] = { name = "Darksteel Voulge" , model = 24939} +models.main[18227] = { name = "Dst. Voulge +1" , model = 24939} +models.main[18260] = { name = "Relic Knuckles" , model = 24711} +models.main[18261] = { name = "Militant Knuckles" , model = 24711} +models.main[18262] = { name = "Dynamis Knuckles" , model = 24711} +models.main[18263] = { name = "Caestus" , model = 24711} +models.main[18264] = { name = "Spharai" , model = 25087} +models.main[18265] = { name = "Spharai" , model = 25087} +models.main[18266] = { name = "Relic Dagger" , model = 24739} +models.main[18267] = { name = "Malefic Dagger" , model = 24739} +models.main[18268] = { name = "Dynamis Dagger" , model = 24739} +models.main[18269] = { name = "Batardeau" , model = 24739} +models.main[18270] = { name = "Mandau" , model = 24910} +models.main[18271] = { name = "Mandau" , model = 24910} +models.main[18272] = { name = "Relic Sword" , model = 24845} +models.main[18273] = { name = "Glyptic Sword" , model = 24845} +models.main[18274] = { name = "Dynamis Sword" , model = 24845} +models.main[18275] = { name = "Caliburn" , model = 24845} +models.main[18276] = { name = "Excalibur" , model = 24896} +models.main[18277] = { name = "Excalibur" , model = 24896} +models.main[18278] = { name = "Relic Blade" , model = 24648} +models.main[18279] = { name = "Gilded Blade" , model = 24648} +models.main[18280] = { name = "Dynamis Blade" , model = 24648} +models.main[18281] = { name = "Valhalla" , model = 24640} +models.main[18282] = { name = "Ragnarok" , model = 24895} +models.main[18283] = { name = "Ragnarok" , model = 24895} +models.main[18284] = { name = "Relic Axe" , model = 24667} +models.main[18285] = { name = "Leonine Axe" , model = 24667} +models.main[18286] = { name = "Dynamis Axe" , model = 24667} +models.main[18287] = { name = "Ogre Killer" , model = 24667} +models.main[18288] = { name = "Guttler" , model = 24923} +models.main[18289] = { name = "Guttler" , model = 24923} +models.main[18290] = { name = "Relic Bhuj" , model = 24672} +models.main[18291] = { name = "Agonal Bhuj" , model = 24672} +models.main[18292] = { name = "Dynamis Bhuj" , model = 24672} +models.main[18293] = { name = "Abaddon Killer" , model = 24672} +models.main[18294] = { name = "Bravura" , model = 24915} +models.main[18295] = { name = "Bravura" , model = 24915} +models.main[18296] = { name = "Relic Lance" , model = 24786} +models.main[18297] = { name = "Hotspur Lance" , model = 24786} +models.main[18298] = { name = "Dynamis Lance" , model = 24786} +models.main[18299] = { name = "Gae Assail" , model = 24786} +models.main[18300] = { name = "Gungnir" , model = 24793} +models.main[18301] = { name = "Gungnir" , model = 24793} +models.main[18302] = { name = "Relic Scythe" , model = 24898} +models.main[18303] = { name = "Memento Scythe" , model = 24898} +models.main[18304] = { name = "Dynamis Scythe" , model = 24898} +models.main[18305] = { name = "Bec de Faucon" , model = 24898} +models.main[18306] = { name = "Apocalypse" , model = 24914} +models.main[18307] = { name = "Apocalypse" , model = 24914} +models.main[18308] = { name = "Ihintanto" , model = 24885} +models.main[18309] = { name = "Mimizuku" , model = 24885} +models.main[18310] = { name = "Rogetsu" , model = 24885} +models.main[18311] = { name = "Yoshimitsu" , model = 24885} +models.main[18312] = { name = "Kikoku" , model = 24920} +models.main[18313] = { name = "Kikoku" , model = 24920} +models.main[18314] = { name = "Ito" , model = 24723} +models.main[18315] = { name = "Hayatemaru" , model = 24723} +models.main[18316] = { name = "Oboromaru" , model = 24723} +models.main[18317] = { name = "Totsukanotsurugi" , model = 24724} +models.main[18318] = { name = "Amanomurakumo" , model = 24916} +models.main[18319] = { name = "Amanomurakumo" , model = 24916} +models.main[18320] = { name = "Relic Maul" , model = 24690} +models.main[18321] = { name = "Battering Maul" , model = 24690} +models.main[18322] = { name = "Dynamis Maul" , model = 24690} +models.main[18323] = { name = "Gullintani" , model = 24690} +models.main[18324] = { name = "Mjollnir" , model = 24883} +models.main[18325] = { name = "Mjollnir" , model = 24883} +models.main[18326] = { name = "Relic Staff" , model = 24871} +models.main[18327] = { name = "Sage's Staff" , model = 24871} +models.main[18328] = { name = "Dynamis Staff" , model = 24871} +models.main[18329] = { name = "Thyrus" , model = 24871} +models.main[18330] = { name = "Claustrum" , model = 24918} +models.main[18331] = { name = "Claustrum" , model = 24918} +models.main[18350] = { name = "Tourney Patas" , model = 24713} +models.main[18351] = { name = "Meteor Cesti" , model = 24704} +models.main[18352] = { name = "Mighty Patas" , model = 24715} +models.main[18353] = { name = "Adargas" , model = 25086} +models.main[18354] = { name = "Adargas +1" , model = 25086} +models.main[18355] = { name = "Hushed Baghnakhs" , model = 24717} +models.main[18356] = { name = "Martial Knuckles" , model = 24708} +models.main[18357] = { name = "Melt Claws" , model = 24700} +models.main[18358] = { name = "Wagh Baghnakhs" , model = 24718} +models.main[18359] = { name = "Boreas Cesti" , model = 24704} +models.main[18360] = { name = "Faith Baghnakhs" , model = 24719} +models.main[18361] = { name = "Ponder. Manoples" , model = 24712} +models.main[18362] = { name = "Sainti" , model = 25085} +models.main[18363] = { name = "Sainti +1" , model = 25085} +models.main[18364] = { name = "Pahluwan Katars" , model = 24694} +models.main[18365] = { name = "Pahluwan Patas" , model = 24715} +models.main[18366] = { name = "Gust Claymore" , model = 24642} +models.main[18367] = { name = "Gust Claymore +1" , model = 24642} +models.main[18368] = { name = "Gust Sword" , model = 24648} +models.main[18369] = { name = "Gust Sword +1" , model = 24648} +models.main[18370] = { name = "Gust Tongue" , model = 24650} +models.main[18371] = { name = "Gust Tongue +1" , model = 24650} +models.main[18372] = { name = "Balan's Sword" , model = 24651} +models.main[18373] = { name = "Balin's Sword" , model = 24650} +models.main[18374] = { name = "Mighty Sword" , model = 24646} +models.main[18375] = { name = "Falx" , model = 24928} +models.main[18376] = { name = "Falx +1" , model = 24928} +models.main[18377] = { name = "Mercurial Sword" , model = 24646} +models.main[18378] = { name = "Subduer" , model = 24644} +models.main[18379] = { name = "Vulcan Claymore" , model = 24642} +models.main[18380] = { name = "Martial Sword" , model = 24646} +models.main[18381] = { name = "Prominence Sword" , model = 24647} +models.main[18382] = { name = "Darksteel Falx" , model = 24938} +models.main[18383] = { name = "Darksteel Falx +1" , model = 24938} +models.main[18384] = { name = "Lucent Sword" , model = 24647} +models.main[18385] = { name = "Algol" , model = 24953} +models.main[18386] = { name = "Gloom Claymore" , model = 24641} +models.main[18387] = { name = "Djinnbringer" , model = 24641} +models.main[18388] = { name = "Doombringer" , model = 24641} +models.main[18389] = { name = "Crude Sword" , model = 24647} +models.main[18390] = { name = "Templar Hammer" , model = 24689} +models.main[18391] = { name = "Sacred Mace" , model = 24683} +models.main[18392] = { name = "Sacred Maul" , model = 24692} +models.main[18393] = { name = "Sacred Wand" , model = 24804} +models.main[18394] = { name = "Pilgrim's Wand" , model = 24818} +models.main[18395] = { name = "Seawolf Cudgel" , model = 24676} +models.main[18396] = { name = "Sea Rob. Cudgel" , model = 24677} +models.main[18397] = { name = "Prudence Rod" , model = 24912} +models.main[18398] = { name = "Raphael's Rod" , model = 24816} +models.main[18399] = { name = "Charm Wand" , model = 24949} +models.main[18400] = { name = "Charm Wand +1" , model = 24949} +models.main[18401] = { name = "Moogle Rod" , model = 24950} +models.main[18402] = { name = "Mana Wand" , model = 24808} +models.main[18403] = { name = "High Mana Wand" , model = 24807} +models.main[18404] = { name = "Ramuh's Mace" , model = 24936} +models.main[18405] = { name = "Jadagna" , model = 24956} +models.main[18406] = { name = "Jadagna +1" , model = 24956} +models.main[18407] = { name = "Imperial Wand" , model = 24821} +models.main[18408] = { name = "Yigit Bulawa" , model = 24936} +models.main[18409] = { name = "Jadagna -1" , model = 24956} +models.main[18410] = { name = "Melt Katana" , model = 24886} +models.main[18411] = { name = "Buboso" , model = 24890} +models.main[18412] = { name = "Gassan" , model = 24888} +models.main[18413] = { name = "Hirenjaku" , model = 24947} +models.main[18414] = { name = "Hirenjaku +1" , model = 24947} +models.main[18415] = { name = "Tojaku" , model = 24947} +models.main[18416] = { name = "Karasuageha" , model = 24890} +models.main[18417] = { name = "Sayosamonji" , model = 24887} +models.main[18418] = { name = "Otori" , model = 24943} +models.main[18419] = { name = "Kugui" , model = 24943} +models.main[18420] = { name = "Hayabusa" , model = 24970} +models.main[18421] = { name = "Hayabusa +1" , model = 24970} +models.main[18422] = { name = "Ryumon" , model = 24965} +models.main[18423] = { name = "Izayoi" , model = 24976} +models.main[18424] = { name = "Izayoi +1" , model = 24976} +models.main[18425] = { name = "Perdu Blade" , model = 24970} +models.main[18426] = { name = "Sasuke Katana" , model = 24965} +models.main[18427] = { name = "Hanafubuki" , model = 24888} +models.main[18428] = { name = "Kogitsunemaru" , model = 24976} +models.main[18429] = { name = "Shusui" , model = 25015} +models.main[18430] = { name = "Oninohocho" , model = 25023} +models.main[18431] = { name = "Butachi" , model = 24720} +models.main[18432] = { name = "Butachi +1" , model = 24720} +models.main[18433] = { name = "Kagiroi" , model = 24720} +models.main[18434] = { name = "Kosetsusamonji" , model = 24723} +models.main[18435] = { name = "Hotarumaru" , model = 24722} +models.main[18436] = { name = "Lotus Katana" , model = 24944} +models.main[18437] = { name = "Namikirimaru" , model = 24732} +models.main[18438] = { name = "Kumokirimaru" , model = 24722} +models.main[18439] = { name = "Shirogatana" , model = 24968} +models.main[18440] = { name = "Shirogatana +1" , model = 24968} +models.main[18441] = { name = "Shinai" , model = 24979} +models.main[18442] = { name = "Taimakuniyuki +1" , model = 24968} +models.main[18443] = { name = "Windslicer" , model = 24732} +models.main[18444] = { name = "Tsurugitachi" , model = 24723} +models.main[18445] = { name = "Amakura" , model = 24724} +models.main[18446] = { name = "Pachipachio" , model = 25016} +models.main[18447] = { name = "Nanatsusaya" , model = 25019} +models.main[18448] = { name = "Hacchonenbutsu" , model = 24723} +models.main[18449] = { name = "Namioyogi" , model = 24722} +models.main[18450] = { name = "Mukademaru" , model = 24729} +models.main[18451] = { name = "Mokusa" , model = 24968} +models.main[18452] = { name = "Rindomaru" , model = 24727} +models.main[18453] = { name = "Unshomaru" , model = 24722} +models.main[18454] = { name = "Ishikirimaru" , model = 24723} +models.main[18455] = { name = "Ame-no-ohabari" , model = 24724} +models.main[18456] = { name = "Yoshihiro" , model = 24720} +models.main[18457] = { name = "Murasamemaru" , model = 25113} +models.main[18458] = { name = "Bizen-osafune" , model = 24731} +models.main[18459] = { name = "Heshikiri-hasebe" , model = 24727} +models.main[18460] = { name = "Kagotsurube" , model = 24720} +models.main[18461] = { name = "Nikko-ichimonji" , model = 24722} +models.main[18462] = { name = "Sasanuki" , model = 24731} +models.main[18463] = { name = "Sasanuki +1" , model = 24731} +models.main[18464] = { name = "Ark Tachi" , model = 25164} +models.main[18465] = { name = "Genjito" , model = 24724} +models.main[18466] = { name = "Tenkomaru" , model = 25178} +models.main[18481] = { name = "Lucent Axe" , model = 24670} +models.main[18482] = { name = "Amood" , model = 24952} +models.main[18483] = { name = "Amood +1" , model = 24952} +models.main[18484] = { name = "Wamoura Axe" , model = 24671} +models.main[18485] = { name = "Imperial Bhuj" , model = 24672} +models.main[18486] = { name = "Wardancer" , model = 24939} +models.main[18487] = { name = "Erik's Axe" , model = 24911} +models.main[18488] = { name = "Assailant's Axe" , model = 24670} +models.main[18489] = { name = "Dark Amood" , model = 24961} +models.main[18490] = { name = "Dark Amood +1" , model = 24961} +models.main[18491] = { name = "Perdu Voulge" , model = 24941} +models.main[18492] = { name = "Sturdy Axe" , model = 24939} +models.main[18493] = { name = "Regiment Kheten" , model = 24673} +models.main[18494] = { name = "Fourth Toporok" , model = 24668} +models.main[18495] = { name = "Wootz Amood" , model = 24982} +models.main[18496] = { name = "Wootz Amood +1" , model = 24982} +models.main[18497] = { name = "Foolkiller" , model = 25010} +models.main[18498] = { name = "Balestarius" , model = 25024} +models.main[18499] = { name = "Alastor" , model = 24940} +models.main[18500] = { name = "Sparth" , model = 25024} +models.main[18501] = { name = "Seismic Axe" , model = 24674} +models.main[18502] = { name = "Trainee Axe" , model = 24924} +models.main[18503] = { name = "Mammut" , model = 24674} +models.main[18504] = { name = "Eventreuse" , model = 25027} +models.main[18505] = { name = "Erlking's Kheten" , model = 24673} +models.main[18506] = { name = "Tewhatewha" , model = 24924} +models.main[18507] = { name = "Kinship Axe" , model = 24670} +models.main[18508] = { name = "Lyft Voulge" , model = 24940} +models.main[18509] = { name = "Tewhatewha+1" , model = 24924} +models.main[18510] = { name = "Vermeil Bhuj" , model = 25096} +models.main[18511] = { name = "Dolor Bhuj" , model = 24672} +models.main[18512] = { name = "Dolor Bhuj +1" , model = 24672} +models.main[18513] = { name = "Barbarus Bhuj" , model = 24672} +models.main[18514] = { name = "Magnus Toporok" , model = 24668} +models.main[18515] = { name = "Widowmaker" , model = 25027} +models.main[18516] = { name = "Warlord's Axe" , model = 24674} +models.main[18517] = { name = "Elephas Axe" , model = 24669} +models.main[18518] = { name = "Elephas Axe +1" , model = 24669} +models.main[18519] = { name = "Oneiros Axe" , model = 24669} +models.main[18520] = { name = "Laceratrice" , model = 24672} +models.main[18521] = { name = "Dies Irae" , model = 24924} +models.main[18522] = { name = "Firnaxe" , model = 24669} +models.main[18523] = { name = "Firnaxe +1" , model = 24669} +models.main[18524] = { name = "Huskarl Axe" , model = 25179} +models.main[18525] = { name = "Himthige" , model = 25179} +models.main[18531] = { name = "Veldt Axe +1" , model = 24653} +models.main[18532] = { name = "Cleofun Axe" , model = 24667} +models.main[18533] = { name = "Magnus Axe" , model = 24657} +models.main[18534] = { name = "Charmer's Merlin" , model = 24657} +models.main[18535] = { name = "Carabinier's Axe" , model = 24654} +models.main[18536] = { name = "Artio's Axe" , model = 24654} +models.main[18537] = { name = "Maiden Tabar" , model = 24658} +models.main[18538] = { name = "Maiden Tabar +1" , model = 24658} +models.main[18539] = { name = "Tonatiuh Axe" , model = 25167} +models.main[18540] = { name = "Barbican Axe" , model = 24665} +models.main[18541] = { name = "Tjukurrpa Axe" , model = 24658} +models.main[18542] = { name = "Aytanri" , model = 25167} +models.main[18543] = { name = "Breidox" , model = 24658} +models.main[18544] = { name = "Breidox +1" , model = 24658} +models.main[18545] = { name = "Ark Tabar" , model = 25163} +models.main[18546] = { name = "Gibbous Axe" , model = 25107} +models.main[18547] = { name = "Ravana's Axe" , model = 25176} +models.main[18551] = { name = "Twilight Scythe" , model = 25102} +models.main[18552] = { name = "Maleficus" , model = 24926} +models.main[18553] = { name = "Woeborn" , model = 24898} +models.main[18554] = { name = "Darklinn Scythe" , model = 24770} +models.main[18555] = { name = "Sectum Sickle" , model = 24969} +models.main[18556] = { name = "Sectum Sickle+1" , model = 24969} +models.main[18557] = { name = "Sortilege Scythe" , model = 24772} +models.main[18558] = { name = "Wroth Scythe" , model = 25172} +models.main[18559] = { name = "Void Scythe" , model = 24770} +models.main[18560] = { name = "Nirastamo" , model = 24942} +models.main[18561] = { name = "Yhatdhara" , model = 24775} +models.main[18562] = { name = "Yhatdhara +1" , model = 24775} +models.main[18563] = { name = "Ark Scythe" , model = 25162} +models.main[18564] = { name = "Devilish Scythe" , model = 24777} +models.main[18565] = { name = "Adflictio" , model = 25172} +models.main[18581] = { name = "Carbuncle's Pole" , model = 24875} +models.main[18582] = { name = "Yigit Staff" , model = 24871} +models.main[18583] = { name = "Imperial Pole" , model = 24879} +models.main[18584] = { name = "Astral Staff" , model = 24867} +models.main[18585] = { name = "Kinnara Pole" , model = 24937} +models.main[18586] = { name = "Flexible Pole" , model = 24876} +models.main[18587] = { name = "Dryad Staff" , model = 24868} +models.main[18588] = { name = "Perdu Staff" , model = 24917} +models.main[18589] = { name = "Mage's Staff" , model = 24865} +models.main[18590] = { name = "Scepter Staff" , model = 24877} +models.main[18591] = { name = "Pastoral Staff" , model = 24872} +models.main[18592] = { name = "Elder Staff" , model = 24870} +models.main[18593] = { name = "Alkalurops" , model = 25014} +models.main[18594] = { name = "Dorje" , model = 25018} +models.main[18595] = { name = "Mekki Shakki" , model = 25017} +models.main[18596] = { name = "Kebbie" , model = 24867} +models.main[18597] = { name = "Catalyst" , model = 24882} +models.main[18598] = { name = "Prester" , model = 25014} +models.main[18599] = { name = "Pestle" , model = 24872} +models.main[18600] = { name = "Caver's Shovel" , model = 25031} +models.main[18601] = { name = "Fay Crozier" , model = 24900} +models.main[18602] = { name = "Fay Staff" , model = 24870} +models.main[18603] = { name = "Majestas" , model = 25038} +models.main[18604] = { name = "Astaroth Cane" , model = 24866} +models.main[18605] = { name = "Melampus Staff" , model = 24865} +models.main[18606] = { name = "Passaddhi Staff" , model = 24868} +models.main[18607] = { name = "Ceres' Spica" , model = 24869} +models.main[18608] = { name = "Atesh Pole" , model = 24872} +models.main[18609] = { name = "Lyft Pole" , model = 24879} +models.main[18610] = { name = "Spiro Staff" , model = 24870} +models.main[18611] = { name = "Qi Staff" , model = 24869} +models.main[18612] = { name = "Ram Staff" , model = 24931} +models.main[18613] = { name = "Fourth Staff" , model = 24933} +models.main[18614] = { name = "Cobra Staff" , model = 24932} +models.main[18615] = { name = "Passaddhi Staff +1" , model = 24868} +models.main[18616] = { name = "Qi Staff +1" , model = 24869} +models.main[18617] = { name = "Cracked Staff" , model = 24868} +models.main[18618] = { name = "Samudra" , model = 24871} +models.main[18619] = { name = "Chthonic Staff" , model = 24871} +models.main[18620] = { name = "Magnus Pole" , model = 24879} +models.main[18621] = { name = "Warmage's Pole" , model = 24872} +models.main[18622] = { name = "Warmage's Pole +1" , model = 24872} +models.main[18623] = { name = "Chtonic Staff" , model = 24869} +models.main[18624] = { name = "Numen Staff" , model = 24867} +models.main[18625] = { name = "Gerra's Staff" , model = 24905} +models.main[18626] = { name = "Plenitas Virga" , model = 25159} +models.main[18627] = { name = "Bryoja's Staff" , model = 24917} +models.main[18628] = { name = "Flete Pole" , model = 24872} +models.main[18629] = { name = "Flete Pole +1" , model = 24872} +models.main[18630] = { name = "Nathushne" , model = 24868} +models.main[18631] = { name = "Nathushne +1" , model = 24868} +models.main[18632] = { name = "Iridal Staff" , model = 25177} +models.main[18633] = { name = "Chatoyant Staff" , model = 25177} +models.main[18634] = { name = "Zamzummim Staff" , model = 25180} +models.main[18635] = { name = "Melisseus Staff" , model = 25180} +models.main[18637] = { name = "Spharai" , model = 25087} +models.main[18638] = { name = "Mandau" , model = 24910} +models.main[18639] = { name = "Excalibur" , model = 24896} +models.main[18640] = { name = "Ragnarok" , model = 24895} +models.main[18641] = { name = "Guttler" , model = 24923} +models.main[18642] = { name = "Bravura" , model = 24915} +models.main[18643] = { name = "Gungnir" , model = 24793} +models.main[18644] = { name = "Apocalypse" , model = 24914} +models.main[18645] = { name = "Kikoku" , model = 24920} +models.main[18646] = { name = "Amanomurakumo" , model = 24916} +models.main[18647] = { name = "Mjollnir" , model = 24883} +models.main[18648] = { name = "Claustrum" , model = 24918} +models.main[18651] = { name = "Spharai" , model = 25087} +models.main[18652] = { name = "Mandau" , model = 24910} +models.main[18653] = { name = "Excalibur" , model = 24896} +models.main[18654] = { name = "Ragnarok" , model = 24895} +models.main[18655] = { name = "Guttler" , model = 24923} +models.main[18656] = { name = "Bravura" , model = 24915} +models.main[18657] = { name = "Gungnir" , model = 24793} +models.main[18658] = { name = "Apocalypse" , model = 24914} +models.main[18659] = { name = "Kikoku" , model = 24910} +models.main[18660] = { name = "Amanomurakumo" , model = 24916} +models.main[18661] = { name = "Mjollnir" , model = 24883} +models.main[18662] = { name = "Claustrum" , model = 24918} +models.main[18665] = { name = "Spharai" , model = 25087} +models.main[18666] = { name = "Mandau" , model = 24910} +models.main[18667] = { name = "Excalibur" , model = 24896} +models.main[18668] = { name = "Ragnarok" , model = 24895} +models.main[18669] = { name = "Guttler" , model = 24923} +models.main[18670] = { name = "Bravura" , model = 24915} +models.main[18671] = { name = "Gungnir" , model = 24793} +models.main[18672] = { name = "Apocalypse" , model = 24914} +models.main[18673] = { name = "Kikoku" , model = 24920} +models.main[18674] = { name = "Amanomurakumo" , model = 24916} +models.main[18675] = { name = "Mjollnir" , model = 24883} +models.main[18676] = { name = "Claustrum" , model = 24918} +models.main[18741] = { name = "Scogan's Knuckles" , model = 24709} +models.main[18742] = { name = "Puppet Claws" , model = 24700} +models.main[18743] = { name = "Darksteel Sainti" , model = 25084} +models.main[18744] = { name = "Dst. Sainti +1" , model = 25084} +models.main[18745] = { name = "Adaman Sainti" , model = 25082} +models.main[18746] = { name = "Gem Sainti" , model = 25082} +models.main[18747] = { name = "Smash Cesti" , model = 24703} +models.main[18748] = { name = "Hades Sainti" , model = 25083} +models.main[18749] = { name = "Hades Sainti +1" , model = 25083} +models.main[18750] = { name = "Black Adargas" , model = 25081} +models.main[18751] = { name = "Black Adargas +1" , model = 25081} +models.main[18752] = { name = "Retaliators" , model = 24705} +models.main[18753] = { name = "Burning Fists" , model = 24710} +models.main[18754] = { name = "Inferno Claws" , model = 25084} +models.main[18755] = { name = "Noble Himantes" , model = 24703} +models.main[18756] = { name = "Cobra Baghnakhs" , model = 24718} +models.main[18757] = { name = "Gnole Sainti" , model = 25080} +models.main[18758] = { name = "Gnole Sainti +1" , model = 25080} +models.main[18759] = { name = "Shlng. Baghnakhs" , model = 25077} +models.main[18760] = { name = "Useshi" , model = 24704} +models.main[18761] = { name = "Acantha Shavers" , model = 25085} +models.main[18762] = { name = "Custodes" , model = 25081} +models.main[18763] = { name = "Trainee Scissors" , model = 24695} +models.main[18764] = { name = "Oberon's Knuckles" , model = 24710} +models.main[18765] = { name = "Oberon's Sainti" , model = 25084} +models.main[18766] = { name = "Tyro Katars" , model = 24695} +models.main[18767] = { name = "Birdbanes" , model = 24695} +models.main[18768] = { name = "Poppet Katars" , model = 24695} +models.main[18769] = { name = "Severus Claws" , model = 24699} +models.main[18770] = { name = "Pygme Sainti" , model = 25082} +models.main[18771] = { name = "Lyft Sainti" , model = 25080} +models.main[18772] = { name = "Tyro Katars +1" , model = 24695} +models.main[18773] = { name = "Severus Claws +1" , model = 24699} +models.main[18774] = { name = "Savate Fists" , model = 25082} +models.main[18775] = { name = "Savate Fists +1" , model = 25082} +models.main[18776] = { name = "Heofon Knuckles" , model = 24711} +models.main[18777] = { name = "Magnus Sainti" , model = 25082} +models.main[18778] = { name = "Marotte Claws" , model = 24697} +models.main[18779] = { name = "Taurine Cesti" , model = 24702} +models.main[18780] = { name = "Burattinaios" , model = 25085} +models.main[18781] = { name = "Furor Cesti" , model = 24703} +models.main[18782] = { name = "Eyra Baghnakhs" , model = 24716} +models.main[18783] = { name = "Eyra Baghnakhs +1" , model = 24716} +models.main[18784] = { name = "Metasoma Katars" , model = 24694} +models.main[18785] = { name = "Grotesque Cesti" , model = 24704} +models.main[18786] = { name = "Girru" , model = 25074} +models.main[18787] = { name = "Shara's Fists" , model = 24710} +models.main[18788] = { name = "Brawny Adargas" , model = 25081} +models.main[18789] = { name = "Marath Baghnakhs" , model = 24718} +models.main[18790] = { name = "Shivaji Baghnakhs" , model = 24718} +models.main[18791] = { name = "Buzbaz Sainti" , model = 25085} +models.main[18792] = { name = "Buzbaz Sainti +1" , model = 25085} +models.main[18793] = { name = "Blutkrallen" , model = 25069} +models.main[18794] = { name = "Blutklauen" , model = 25069} +models.main[18827] = { name = "Oxossi Facon" , model = 25173} +models.main[18828] = { name = "Oxossi Facon +1" , model = 25173} +models.main[18829] = { name = "Blustery Dagger" , model = 24751} +models.main[18830] = { name = "Gusterion" , model = 24751} +models.main[18841] = { name = "Templar Mace" , model = 24681} +models.main[18842] = { name = "Nmd. Moogle Rod" , model = 24959} +models.main[18843] = { name = "Flan Smasher" , model = 24679} +models.main[18844] = { name = "Miracle Wand" , model = 24949} +models.main[18845] = { name = "Miracle Wand +1" , model = 24949} +models.main[18846] = { name = "Battledore" , model = 24973} +models.main[18847] = { name = "Seveneyes" , model = 24935} +models.main[18848] = { name = "Brass Jadagna" , model = 24977} +models.main[18849] = { name = "Brass Jadagna +1" , model = 24977} +models.main[18850] = { name = "Perdu Wand" , model = 24804} +models.main[18851] = { name = "Werebuster" , model = 24687} +models.main[18852] = { name = "Octave Club" , model = 24686} +models.main[18853] = { name = "Spirit Maul" , model = 24692} +models.main[18854] = { name = "Fourth Mace" , model = 24681} +models.main[18855] = { name = "Trainee Hammer" , model = 24691} +models.main[18856] = { name = "Deae Gratia" , model = 24678} +models.main[18857] = { name = "Antares" , model = 25013} +models.main[18858] = { name = "Flanged Mace" , model = 25022} +models.main[18859] = { name = "Kerykeion" , model = 24809} +models.main[18860] = { name = "Flanged Mace +1" , model = 25022} +models.main[18861] = { name = "Grandeur" , model = 24817} +models.main[18862] = { name = "Clearpath" , model = 24799} +models.main[18863] = { name = "Dream Bell" , model = 25025} +models.main[18864] = { name = "Dream Bell +1" , model = 25025} +models.main[18865] = { name = "Zonure" , model = 24936} +models.main[18866] = { name = "Club Hammer" , model = 25030} +models.main[18867] = { name = "Daedalus Hammer" , model = 24689} +models.main[18868] = { name = "Lady Bell" , model = 25032} +models.main[18869] = { name = "Lady Bell +1" , model = 25032} +models.main[18870] = { name = "Dweomer Maul" , model = 24688} +models.main[18871] = { name = "Kitty Rod" , model = 24816} +models.main[18872] = { name = "Lyft Ferule" , model = 24804} +models.main[18873] = { name = "Brise-os" , model = 24977} +models.main[18874] = { name = "Brise-os +1" , model = 24977} +models.main[18875] = { name = "Vodun Mace" , model = 24679} +models.main[18876] = { name = "Vodun Mace +1" , model = 24679} +models.main[18877] = { name = "Robur Mace" , model = 24679} +models.main[18878] = { name = "Robur Mace +1" , model = 24679} +models.main[18879] = { name = "Rounsey Wand" , model = 25111} +models.main[18880] = { name = "Maestro's Baton" , model = 25115} +models.main[18881] = { name = "Melomane Mallet" , model = 25116} +models.main[18882] = { name = "Beaivi's Scepter" , model = 24797} +models.main[18883] = { name = "Luckitoo" , model = 24936} +models.main[18884] = { name = "Vejovis Wand" , model = 24801} +models.main[18885] = { name = "Vejovis Wand +1" , model = 24801} +models.main[18886] = { name = "Dhyana Rod" , model = 25171} +models.main[18887] = { name = "Dukkha" , model = 25171} +models.main[18888] = { name = "Ankylosis Wand" , model = 25175} +models.main[18891] = { name = "Hannibal's Sword" , model = 24861} +models.main[18892] = { name = "Corbenic Sword" , model = 24845} +models.main[18893] = { name = "Magnus Sword" , model = 24849} +models.main[18894] = { name = "Accolade Sword" , model = 24857} +models.main[18895] = { name = "Chimeric Fleuret" , model = 24769} +models.main[18896] = { name = "Honorbound" , model = 24966} +models.main[18897] = { name = "Isador" , model = 24978} +models.main[18898] = { name = "Mageblade" , model = 24843} +models.main[18899] = { name = "Runic Anelace" , model = 24850} +models.main[18900] = { name = "Skeld Sword" , model = 24857} +models.main[18901] = { name = "Falcata" , model = 24845} +models.main[18902] = { name = "Falcata +1" , model = 24845} +models.main[18903] = { name = "Talekeeper" , model = 25104} +models.main[18904] = { name = "Ephemeron" , model = 25114} +models.main[18905] = { name = "Swiftwing" , model = 24864} +models.main[18906] = { name = "Galenus" , model = 24842} +models.main[18907] = { name = "Devourer" , model = 24863} +models.main[18908] = { name = "Dhampyr Sword" , model = 24851} +models.main[18909] = { name = "Sanus Ensis" , model = 25158} +models.main[18910] = { name = "Apaisante" , model = 24842} +models.main[18911] = { name = "Apaisante +1" , model = 24842} +models.main[18912] = { name = "Ark Saber" , model = 25160} +models.main[18913] = { name = "Ark Sword" , model = 25161} +models.main[18914] = { name = "Killer's Kilij" , model = 24960} +models.main[18915] = { name = "Eradicator's Kilij" , model = 24960} +models.main[18916] = { name = "Heimdall's Doom" , model = 24980} +models.main[18921] = { name = "Taiaha" , model = 24874} +models.main[18922] = { name = "Yantok" , model = 24872} +models.main[18923] = { name = "Shareeravadi" , model = 24871} +models.main[18924] = { name = "Agni's Staff" , model = 24881} +models.main[18925] = { name = "Varuna's Staff" , model = 24881} +models.main[18926] = { name = "Vayu's Staff" , model = 24881} +models.main[18927] = { name = "Kubera's Staff" , model = 24881} +models.main[18928] = { name = "Indra's Staff" , model = 24881} +models.main[18929] = { name = "Soma's Staff" , model = 24881} +models.main[18930] = { name = "Surya's Staff" , model = 24881} +models.main[18931] = { name = "Yama's Staff" , model = 24881} +models.main[18932] = { name = "Sedikutchi" , model = 24879} +models.main[18941] = { name = "Naigama" , model = 24969} +models.main[18942] = { name = "Naigama +1" , model = 24969} +models.main[18943] = { name = "Perdu Sickle" , model = 24969} +models.main[18944] = { name = "Death Sickle" , model = 24926} +models.main[18945] = { name = "Jet Sickle" , model = 24926} +models.main[18946] = { name = "Fourth Zaghnal" , model = 24921} +models.main[18947] = { name = "Moliones's Sickle" , model = 24942} +models.main[18948] = { name = "Enforcer" , model = 25011} +models.main[18949] = { name = "Zareehkl Scythe" , model = 24948} +models.main[18950] = { name = "White Joker" , model = 24942} +models.main[18951] = { name = "Vendetta" , model = 24770} +models.main[18952] = { name = "Faucheuse" , model = 24777} +models.main[18953] = { name = "Beluga" , model = 24942} +models.main[18954] = { name = "Ogre Sickle" , model = 24926} +models.main[18955] = { name = "Dweomer Scythe" , model = 24777} +models.main[18956] = { name = "Serpette" , model = 24898} +models.main[18957] = { name = "Smiting Scythe" , model = 24772} +models.main[18958] = { name = "Lyft Scythe" , model = 24771} +models.main[18959] = { name = "Serpette +1" , model = 24898} +models.main[18960] = { name = "Smiting Scythe +1" , model = 24772} +models.main[18961] = { name = "Plaga Scythe" , model = 25097} +models.main[18962] = { name = "Rusty Zaghnal" , model = 24773} +models.main[18963] = { name = "Gleaming Zaghnal" , model = 24775} +models.main[18964] = { name = "Dire Scythe" , model = 24770} +models.main[18965] = { name = "Dire Scythe +1" , model = 24770} +models.main[18966] = { name = "Crisis Scythe" , model = 24898} +models.main[18967] = { name = "Magnus Scythe" , model = 24948} +models.main[18968] = { name = "Bounty Sickle" , model = 24926} +models.main[18969] = { name = "Terpsichore" , model = 25004} +models.main[18970] = { name = "Tupsimati" , model = 25005} +models.main[18971] = { name = "Conqueror" , model = 24990} +models.main[18972] = { name = "Glanzfaust" , model = 25078} +models.main[18973] = { name = "Yagrush" , model = 24991} +models.main[18974] = { name = "Laevateinn" , model = 24992} +models.main[18975] = { name = "Murgleis" , model = 24996} +models.main[18976] = { name = "Vajra" , model = 24998} +models.main[18977] = { name = "Burtgang" , model = 25002} +models.main[18978] = { name = "Liberator" , model = 25001} +models.main[18979] = { name = "Aymur" , model = 24989} +models.main[18980] = { name = "Carnwenhan" , model = 25003} +models.main[18982] = { name = "Kogarasumaru" , model = 25000} +models.main[18983] = { name = "Nagi" , model = 24997} +models.main[18984] = { name = "Ryunohige" , model = 24999} +models.main[18985] = { name = "Nirvana" , model = 24993} +models.main[18986] = { name = "Tizona" , model = 24995} +models.main[18988] = { name = "Kenkonken" , model = 25079} +models.main[18989] = { name = "Terpsichore" , model = 25004} +models.main[18990] = { name = "Tupsimati" , model = 25005} +models.main[18991] = { name = "Conqueror" , model = 24990} +models.main[18992] = { name = "Glanzfaust" , model = 25078} +models.main[18993] = { name = "Yagrush" , model = 24991} +models.main[18994] = { name = "Laevateinn" , model = 24992} +models.main[18995] = { name = "Murgleis" , model = 24996} +models.main[18996] = { name = "Vajra" , model = 24998} +models.main[18997] = { name = "Burtgang" , model = 25002} +models.main[18998] = { name = "Liberator" , model = 25001} +models.main[18999] = { name = "Aymur" , model = 24989} +models.main[19000] = { name = "Carnwenhan" , model = 25003} +models.main[19002] = { name = "Kogarasumaru" , model = 25000} +models.main[19003] = { name = "Nagi" , model = 24997} +models.main[19004] = { name = "Ryunohige" , model = 24999} +models.main[19005] = { name = "Nirvana" , model = 24993} +models.main[19006] = { name = "Tizona" , model = 24995} +models.main[19008] = { name = "Kenkonken" , model = 25079} +models.main[19060] = { name = "Conqueror" , model = 24990} +models.main[19061] = { name = "Glanzfaust" , model = 25078} +models.main[19062] = { name = "Yagrush" , model = 24991} +models.main[19063] = { name = "Laevateinn" , model = 24992} +models.main[19064] = { name = "Murgleis" , model = 24996} +models.main[19065] = { name = "Vajra" , model = 24998} +models.main[19066] = { name = "Burtgang" , model = 25002} +models.main[19067] = { name = "Liberator" , model = 25001} +models.main[19068] = { name = "Aymur" , model = 24989} +models.main[19069] = { name = "Carnwenhan" , model = 25003} +models.main[19071] = { name = "Kogarasumaru" , model = 25000} +models.main[19072] = { name = "Nagi" , model = 24997} +models.main[19073] = { name = "Ryunohige" , model = 24999} +models.main[19074] = { name = "Nirvana" , model = 24993} +models.main[19075] = { name = "Tizona" , model = 24995} +models.main[19077] = { name = "Kenkonken" , model = 25079} +models.main[19078] = { name = "Terpsichore" , model = 25004} +models.main[19079] = { name = "Tupsimati" , model = 25005} +models.main[19080] = { name = "Conqueror" , model = 24990} +models.main[19081] = { name = "Glanzfaust" , model = 25078} +models.main[19082] = { name = "Yagrush" , model = 24991} +models.main[19083] = { name = "Laevateinn" , model = 24992} +models.main[19084] = { name = "Murgleis" , model = 24996} +models.main[19085] = { name = "Vajra" , model = 24998} +models.main[19086] = { name = "Burtgang" , model = 25002} +models.main[19087] = { name = "Liberator" , model = 25001} +models.main[19088] = { name = "Aymur" , model = 24989} +models.main[19089] = { name = "Carnwenhan" , model = 25003} +models.main[19091] = { name = "Kogarasumaru" , model = 25000} +models.main[19092] = { name = "Nagi" , model = 24997} +models.main[19093] = { name = "Ryunohige" , model = 24999} +models.main[19094] = { name = "Nirvana" , model = 24993} +models.main[19095] = { name = "Tizona" , model = 24995} +models.main[19097] = { name = "Kenkonken" , model = 25079} +models.main[19098] = { name = "Terpsichore" , model = 25004} +models.main[19099] = { name = "Tupsimati" , model = 25005} +models.main[19100] = { name = "Cobra Knife" , model = 24756} +models.main[19101] = { name = "Trainee Knife" , model = 24893} +models.main[19102] = { name = "Main Gauche" , model = 24752} +models.main[19103] = { name = "Darksteel Jambiya" , model = 24985} +models.main[19104] = { name = "Dst. Jambiya +1" , model = 24985} +models.main[19105] = { name = "Thug's Jambiya" , model = 24955} +models.main[19106] = { name = "Thug's Jambiya +1" , model = 24955} +models.main[19107] = { name = "Azoth" , model = 25006} +models.main[19108] = { name = "Zareehkl Jambiya" , model = 24985} +models.main[19109] = { name = "Trilling Dagger" , model = 24744} +models.main[19110] = { name = "Trainee's Needle" , model = 24745} +models.main[19111] = { name = "Silktone" , model = 24744} +models.main[19112] = { name = "Farseer" , model = 24744} +models.main[19113] = { name = "Ermine's Tail" , model = 25026} +models.main[19114] = { name = "Galkan Dagger" , model = 24744} +models.main[19115] = { name = "Fane Baselard" , model = 24744} +models.main[19116] = { name = "Dweomer Knife" , model = 24734} +models.main[19117] = { name = "Ogre Jambiya" , model = 24985} +models.main[19118] = { name = "Machismo" , model = 25035} +models.main[19119] = { name = "Ranging Knife" , model = 24756} +models.main[19120] = { name = "Avis" , model = 24986} +models.main[19121] = { name = "Sleight Kukri" , model = 24750} +models.main[19122] = { name = "Courser's Pugio" , model = 24738} +models.main[19123] = { name = "Cinquedea" , model = 24734} +models.main[19124] = { name = "Creve-coeur" , model = 24955} +models.main[19125] = { name = "Lyft Jambiya" , model = 24955} +models.main[19126] = { name = "Papilio Kirpan" , model = 24985} +models.main[19127] = { name = "Ranging Knife +1" , model = 24756} +models.main[19128] = { name = "Edgeless Knife" , model = 24736} +models.main[19129] = { name = "Rapidus Sax" , model = 24755} +models.main[19130] = { name = "Clement Skean" , model = 24739} +models.main[19131] = { name = "Magnus Dagger" , model = 24739} +models.main[19132] = { name = "Twilight Knife" , model = 25103} +models.main[19133] = { name = "Triplus Dagger" , model = 24753} +models.main[19134] = { name = "Felibre's Dague" , model = 24734} +models.main[19135] = { name = "Acinaces" , model = 24955} +models.main[19136] = { name = "Phurba" , model = 24738} +models.main[19137] = { name = "Angr Harpe" , model = 24930} +models.main[19138] = { name = "Verus Knife" , model = 24734} +models.main[19139] = { name = "Verus Knife +1" , model = 24734} +models.main[19140] = { name = "Mantodea Harpe" , model = 25109} +models.main[19141] = { name = "Oneiros Knife" , model = 24734} +models.main[19142] = { name = "Gnadgott" , model = 24744} +models.main[19143] = { name = "Lux Pugio" , model = 25110} +models.main[19144] = { name = "Coruscanti" , model = 25112} +models.main[19145] = { name = "Asteria" , model = 25117} +models.main[19146] = { name = "Supernal Knife" , model = 24971} +models.main[19147] = { name = "Janamaraka" , model = 24955} +models.main[19148] = { name = "Pugiunculus" , model = 24744} +models.main[19149] = { name = "Strategema Knife" , model = 24733} +models.main[19150] = { name = "Cobra Claymore" , model = 24642} +models.main[19151] = { name = "Bahadur" , model = 24983} +models.main[19152] = { name = "Bahadur +1" , model = 24983} +models.main[19153] = { name = "Naglering" , model = 25008} +models.main[19154] = { name = "Ferrara" , model = 24928} +models.main[19155] = { name = "Cruadin" , model = 24650} +models.main[19156] = { name = "Balisarde" , model = 24647} +models.main[19157] = { name = "Surviver" , model = 24643} +models.main[19158] = { name = "Scheherazade" , model = 24939} +models.main[19159] = { name = "Galatyn" , model = 25039} +models.main[19160] = { name = "Estramacon" , model = 24642} +models.main[19161] = { name = "Lyft Claymore" , model = 24640} +models.main[19162] = { name = "Dull Claymore" , model = 24643} +models.main[19163] = { name = "Nightfall" , model = 25040} +models.main[19164] = { name = "Ferus Algol" , model = 25101} +models.main[19165] = { name = "Cratus Sword" , model = 24649} +models.main[19166] = { name = "Cratus Sword +1" , model = 24649} +models.main[19167] = { name = "Khloros Blade" , model = 24640} +models.main[19168] = { name = "Magnus Claymore" , model = 24641} +models.main[19169] = { name = "Kriegsmesser" , model = 24640} +models.main[19170] = { name = "Kardia Faussar" , model = 24650} +models.main[19171] = { name = "Kardia Faussar +1" , model = 24650} +models.main[19172] = { name = "Jing. Greatsword" , model = 25105} +models.main[19173] = { name = "Gram" , model = 24897} +models.main[19174] = { name = "Borealis" , model = 25119} +models.main[19175] = { name = "Hoarfrost Blade" , model = 25118} +models.main[19176] = { name = "Irasya" , model = 24641} +models.main[19177] = { name = "Etourdissante" , model = 24646} +models.main[19178] = { name = "Etourdissante +1" , model = 24646} +models.main[19179] = { name = "Dervish Sword" , model = 25174} +models.main[19271] = { name = "Osoraku" , model = 24889} +models.main[19272] = { name = "Yagentoshiro" , model = 24888} +models.main[19273] = { name = "Onishibari" , model = 24970} +models.main[19274] = { name = "Trainee Burin" , model = 24891} +models.main[19275] = { name = "Tsukumo" , model = 24890} +models.main[19276] = { name = "Midare" , model = 24888} +models.main[19277] = { name = "Tsugumi" , model = 24891} +models.main[19278] = { name = "Fuchingiri" , model = 24885} +models.main[19279] = { name = "Musanto" , model = 24887} +models.main[19280] = { name = "Narigitsune" , model = 24885} +models.main[19281] = { name = "Midare +1" , model = 24888} +models.main[19282] = { name = "Hochomasamune" , model = 25098} +models.main[19283] = { name = "Rusty Kunai" , model = 24891} +models.main[19284] = { name = "Hiwa" , model = 24890} +models.main[19285] = { name = "Kakko" , model = 24976} +models.main[19286] = { name = "Kakko +1" , model = 24976} +models.main[19287] = { name = "Kamome" , model = 24890} +models.main[19288] = { name = "Sekirei" , model = 24888} +models.main[19289] = { name = "Toki" , model = 24886} +models.main[19290] = { name = "Aizenkunitoshi" , model = 24889} +models.main[19291] = { name = "Oirandori" , model = 24970} +models.main[19292] = { name = "Kogara" , model = 24890} +models.main[19293] = { name = "Ichi-an" , model = 24888} +models.main[19294] = { name = "Ichi-an +1" , model = 24888} +models.main[19295] = { name = "Mujin Tanto" , model = 24889} +models.main[19296] = { name = "Ban" , model = 24891} +models.main[19297] = { name = "Kakesu" , model = 24889} +models.main[19298] = { name = "Ikarigiri" , model = 25165} +models.main[19299] = { name = "Aisa" , model = 24889} +models.main[19300] = { name = "Aisa +1" , model = 24889} +models.main[19301] = { name = "Kawasemi" , model = 24976} +models.main[19302] = { name = "Uguisu" , model = 25181} +models.main[19303] = { name = "Fay Lance" , model = 24785} +models.main[19304] = { name = "Sarissa" , model = 25037} +models.main[19305] = { name = "Pike" , model = 24786} +models.main[19306] = { name = "Lyft Lance" , model = 24788} +models.main[19307] = { name = "Blunt Lance" , model = 24787} +models.main[19308] = { name = "Rusty Spear" , model = 24781} +models.main[19309] = { name = "Gleaming Spear" , model = 24780} +models.main[19310] = { name = "Guisarme" , model = 24946} +models.main[19311] = { name = "Guisarme +1" , model = 24946} +models.main[19312] = { name = "Skogul Lance" , model = 24786} +models.main[19313] = { name = "Magnus Lance" , model = 24786} +models.main[19314] = { name = "Quint Spear" , model = 24779} +models.main[19315] = { name = "Erebus's Lance" , model = 24925} +models.main[19316] = { name = "Fetter Lance" , model = 24785} +models.main[19317] = { name = "Borian Spear" , model = 24780} +models.main[19318] = { name = "Borian Spear +1" , model = 24780} +models.main[19327] = { name = "Pugilists" , model = 24706} +models.main[19328] = { name = "Simian Fists" , model = 24705} +models.main[19329] = { name = "Mantis" , model = 25085} +models.main[19330] = { name = "Wargfangs" , model = 24695} +models.main[19331] = { name = "Cat's Claws" , model = 24701} +models.main[19332] = { name = "Peeler" , model = 24735} +models.main[19333] = { name = "Renegade" , model = 24737} +models.main[19334] = { name = "Kartika" , model = 24986} +models.main[19335] = { name = "Athame" , model = 24752} +models.main[19336] = { name = "Dakini" , model = 24756} +models.main[19337] = { name = "Side-sword" , model = 24844} +models.main[19338] = { name = "Schiavona" , model = 24846} +models.main[19339] = { name = "Nobilis" , model = 24853} +models.main[19340] = { name = "Antea" , model = 24859} +models.main[19341] = { name = "Soulsaber" , model = 24829} +models.main[19342] = { name = "Break Blade" , model = 24647} +models.main[19343] = { name = "Sunblade" , model = 24648} +models.main[19344] = { name = "Albion" , model = 24646} +models.main[19345] = { name = "Salamand Sword" , model = 24650} +models.main[19346] = { name = "Brand d'Arcon" , model = 24641} +models.main[19347] = { name = "Chopper" , model = 24667} +models.main[19348] = { name = "Splinter" , model = 24659} +models.main[19349] = { name = "Bonebiter" , model = 24658} +models.main[19350] = { name = "Punisher" , model = 24664} +models.main[19351] = { name = "Skeggiold" , model = 24654} +models.main[19352] = { name = "Lumberjack" , model = 24669} +models.main[19353] = { name = "Sagaris" , model = 24671} +models.main[19354] = { name = "Bonesplitter" , model = 24669} +models.main[19355] = { name = "Luchtaine" , model = 24674} +models.main[19356] = { name = "Hephaestus" , model = 24924} +models.main[19357] = { name = "Farmhand" , model = 24771} +models.main[19358] = { name = "Stigma" , model = 24772} +models.main[19359] = { name = "Ultimatum" , model = 24770} +models.main[19360] = { name = "Vengeance" , model = 24926} +models.main[19361] = { name = "Severance" , model = 24898} +models.main[19362] = { name = "Ranseur" , model = 24786} +models.main[19363] = { name = "Copperhead" , model = 24787} +models.main[19364] = { name = "Oathkeeper" , model = 24785} +models.main[19365] = { name = "Bradamante" , model = 24925} +models.main[19366] = { name = "Stribog" , model = 24789} +models.main[19367] = { name = "Kibashiri" , model = 24886} +models.main[19368] = { name = "Koruri" , model = 24888} +models.main[19369] = { name = "Mozu" , model = 24889} +models.main[19370] = { name = "Isatu" , model = 24943} +models.main[19371] = { name = "Kuina" , model = 24888} +models.main[19372] = { name = "Donto" , model = 24722} +models.main[19373] = { name = "Shirodachi" , model = 24721} +models.main[19374] = { name = "Radennotachi" , model = 24899} +models.main[19375] = { name = "Kurodachi" , model = 24724} +models.main[19376] = { name = "Efunotachi" , model = 24723} +models.main[19377] = { name = "Stenz" , model = 24689} +models.main[19378] = { name = "Rageblow" , model = 24691} +models.main[19379] = { name = "Culacula" , model = 24692} +models.main[19380] = { name = "Goedendag" , model = 24679} +models.main[19381] = { name = "Ingrimm" , model = 24819} +models.main[19382] = { name = "Crook" , model = 24880} +models.main[19383] = { name = "Shillelagh" , model = 24875} +models.main[19384] = { name = "Slaine" , model = 24874} +models.main[19385] = { name = "Danda" , model = 24872} +models.main[19386] = { name = "Teiwaz" , model = 24866} +models.main[19397] = { name = "Verethragna" , model = 25076} +models.main[19398] = { name = "Twashtar" , model = 25041} +models.main[19399] = { name = "Almace" , model = 25042} +models.main[19400] = { name = "Caladbolg" , model = 25043} +models.main[19401] = { name = "Farsha" , model = 25044} +models.main[19402] = { name = "Ukonvasara" , model = 25045} +models.main[19403] = { name = "Redemption" , model = 25046} +models.main[19404] = { name = "Rhongomiant" , model = 25088} +models.main[19405] = { name = "Kannagi" , model = 25089} +models.main[19406] = { name = "Masamune" , model = 25090} +models.main[19407] = { name = "Gambanteinn" , model = 25091} +models.main[19408] = { name = "Hvergelmir" , model = 25092} +models.main[19412] = { name = "Revenant Fists" , model = 25085} +models.main[19413] = { name = "Ursine Claws" , model = 24695} +models.main[19414] = { name = "Taipan Fangs" , model = 24701} +models.main[19415] = { name = "Barracudas" , model = 24716} +models.main[19416] = { name = "Daka" , model = 24955} +models.main[19417] = { name = "Parazonium" , model = 24752} +models.main[19418] = { name = "Kila" , model = 24756} +models.main[19419] = { name = "Fusetto" , model = 24744} +models.main[19420] = { name = "Badelaire" , model = 24853} +models.main[19421] = { name = "Khanda" , model = 24859} +models.main[19422] = { name = "Shamshir" , model = 24829} +models.main[19423] = { name = "Machaera" , model = 24957} +models.main[19424] = { name = "Espafut" , model = 24646} +models.main[19425] = { name = "Prestelame" , model = 24650} +models.main[19426] = { name = "Sombrelame" , model = 24641} +models.main[19427] = { name = "Kalavejs" , model = 24644} +models.main[19428] = { name = "Alard's Axe" , model = 24658} +models.main[19429] = { name = "Richardet's Axe" , model = 24664} +models.main[19430] = { name = "Guichard's Axe" , model = 24654} +models.main[19431] = { name = "Renaud's Axe" , model = 24654} +models.main[19432] = { name = "Maschu" , model = 24669} +models.main[19433] = { name = "Kunlun" , model = 24674} +models.main[19434] = { name = "Atlas" , model = 24924} +models.main[19435] = { name = "Sumeru" , model = 24672} +models.main[19436] = { name = "Penitence" , model = 24770} +models.main[19437] = { name = "Maleficence" , model = 24926} +models.main[19438] = { name = "Absolution" , model = 24898} +models.main[19439] = { name = "Reckoning" , model = 24942} +models.main[19440] = { name = "Cerastes" , model = 24785} +models.main[19441] = { name = "Corsesca" , model = 24925} +models.main[19442] = { name = "Langdebeve" , model = 24789} +models.main[19443] = { name = "Stingray" , model = 24954} +models.main[19444] = { name = "Tobi" , model = 24889} +models.main[19445] = { name = "Enchu" , model = 24943} +models.main[19446] = { name = "Sekka" , model = 24888} +models.main[19447] = { name = "Uzura" , model = 24886} +models.main[19448] = { name = "Hiradennotachi" , model = 24899} +models.main[19449] = { name = "Kokushitsunotachi" , model = 24724} +models.main[19450] = { name = "Hyogugusarinotachi" , model = 24723} +models.main[19451] = { name = "Keitonotachi" , model = 24721} +models.main[19452] = { name = "Canne de Combat" , model = 24692} +models.main[19453] = { name = "Naboot" , model = 24679} +models.main[19454] = { name = "Hoeroa" , model = 24820} +models.main[19455] = { name = "Makhila" , model = 24687} +models.main[19456] = { name = "Verethragna" , model = 25076} +models.main[19457] = { name = "Twashtar" , model = 25041} +models.main[19458] = { name = "Almace" , model = 25042} +models.main[19459] = { name = "Caladbolg" , model = 25043} +models.main[19460] = { name = "Farsha" , model = 25044} +models.main[19461] = { name = "Ukonvasara" , model = 25045} +models.main[19462] = { name = "Redemption" , model = 25046} +models.main[19463] = { name = "Rhongomiant" , model = 25088} +models.main[19464] = { name = "Kannagi" , model = 25089} +models.main[19465] = { name = "Masamune" , model = 25090} +models.main[19466] = { name = "Gambanteinn" , model = 25091} +models.main[19467] = { name = "Hvergelmir" , model = 25092} +models.main[19470] = { name = "Revenant Fists +1" , model = 25085} +models.main[19471] = { name = "Ursine Claws +1" , model = 24695} +models.main[19472] = { name = "Taipan Fangs +1" , model = 24701} +models.main[19473] = { name = "Barracudas +1" , model = 24716} +models.main[19474] = { name = "Daka +1" , model = 24955} +models.main[19475] = { name = "Parazonium +1" , model = 24752} +models.main[19476] = { name = "Kila +1" , model = 24756} +models.main[19477] = { name = "Fusetto +1" , model = 24744} +models.main[19478] = { name = "Badelaire +1" , model = 24853} +models.main[19479] = { name = "Khanda +1" , model = 24859} +models.main[19480] = { name = "Shamshir +1" , model = 24829} +models.main[19481] = { name = "Machaera +1" , model = 24957} +models.main[19482] = { name = "Espafut +1" , model = 24646} +models.main[19483] = { name = "Prestelame +1" , model = 24650} +models.main[19484] = { name = "Sombrelame +1" , model = 24641} +models.main[19485] = { name = "Kalavejs +1" , model = 24644} +models.main[19486] = { name = "Alard's Axe +1" , model = 24658} +models.main[19487] = { name = "Richardet's Axe +1" , model = 24664} +models.main[19488] = { name = "Guichard's Axe +1" , model = 24654} +models.main[19489] = { name = "Renaud's Axe +1" , model = 24654} +models.main[19490] = { name = "Maschu +1" , model = 24669} +models.main[19491] = { name = "Kunlun +1" , model = 24674} +models.main[19492] = { name = "Atlas +1" , model = 24924} +models.main[19493] = { name = "Sumeru +1" , model = 24672} +models.main[19494] = { name = "Penitence +1" , model = 24770} +models.main[19495] = { name = "Maleficence +1" , model = 24926} +models.main[19496] = { name = "Absolution +1" , model = 24898} +models.main[19497] = { name = "Reckoning +1" , model = 24942} +models.main[19498] = { name = "Cerastes +1" , model = 24785} +models.main[19499] = { name = "Corsesca +1" , model = 24925} +models.main[19500] = { name = "Langdebeve +1" , model = 24789} +models.main[19501] = { name = "Stingray +1" , model = 24954} +models.main[19502] = { name = "Tobi +1" , model = 24889} +models.main[19503] = { name = "Enchu +1" , model = 24943} +models.main[19504] = { name = "Sekka +1" , model = 24888} +models.main[19505] = { name = "Uzura +1" , model = 24886} +models.main[19506] = { name = "Hiradennotachi +1" , model = 24899} +models.main[19507] = { name = "Kokushitsu +1" , model = 24724} +models.main[19508] = { name = "Hyogugusari +1" , model = 24723} +models.main[19509] = { name = "Keitonotachi +1" , model = 24721} +models.main[19510] = { name = "Canne de Cbt. +1" , model = 24692} +models.main[19511] = { name = "Naboot +1" , model = 24679} +models.main[19512] = { name = "Hoeroa +1" , model = 24820} +models.main[19513] = { name = "Makhila +1" , model = 24687} +models.main[19514] = { name = "Taiaha +1" , model = 24874} +models.main[19515] = { name = "Yantok +1" , model = 24872} +models.main[19516] = { name = "Shareeravadi +1" , model = 24871} +models.main[19517] = { name = "Agni's Staff +1" , model = 24881} +models.main[19518] = { name = "Varuna's Staff +1" , model = 24881} +models.main[19519] = { name = "Vayu's Staff +1" , model = 24881} +models.main[19520] = { name = "Kubera's Staff +1" , model = 24881} +models.main[19521] = { name = "Indra's Staff +1" , model = 24881} +models.main[19522] = { name = "Soma's Staff +1" , model = 24881} +models.main[19523] = { name = "Surya's Staff +1" , model = 24881} +models.main[19524] = { name = "Yama's Staff +1" , model = 24881} +models.main[19525] = { name = "Sedikutchi +1" , model = 24879} +models.main[19534] = { name = "Verethragna" , model = 25076} +models.main[19535] = { name = "Twashtar" , model = 25041} +models.main[19536] = { name = "Almace" , model = 25042} +models.main[19537] = { name = "Caladbolg" , model = 25043} +models.main[19538] = { name = "Farsha" , model = 25044} +models.main[19539] = { name = "Ukonvasara" , model = 25045} +models.main[19540] = { name = "Redemption" , model = 25046} +models.main[19541] = { name = "Rhongomiant" , model = 25088} +models.main[19542] = { name = "Kannagi" , model = 25089} +models.main[19543] = { name = "Masamune" , model = 25090} +models.main[19544] = { name = "Gambanteinn" , model = 25091} +models.main[19545] = { name = "Hvergelmir" , model = 25092} +models.main[19548] = { name = "Revenant Fists +2" , model = 25085} +models.main[19549] = { name = "Ursine Claws +2" , model = 24695} +models.main[19550] = { name = "Taipan Fangs +2" , model = 24701} +models.main[19551] = { name = "Barracudas +2" , model = 24716} +models.main[19552] = { name = "Daka +2" , model = 24955} +models.main[19553] = { name = "Parazonium +2" , model = 24752} +models.main[19554] = { name = "Kila +2" , model = 24756} +models.main[19555] = { name = "Fusetto +2" , model = 24744} +models.main[19556] = { name = "Badelaire +2" , model = 24853} +models.main[19557] = { name = "Khanda +2" , model = 24859} +models.main[19558] = { name = "Shamshir +2" , model = 24829} +models.main[19559] = { name = "Machaera +2" , model = 24957} +models.main[19560] = { name = "Espafut +2" , model = 24646} +models.main[19561] = { name = "Prestelame +2" , model = 24650} +models.main[19562] = { name = "Sombrelame +2" , model = 24641} +models.main[19563] = { name = "Kalavejs +2" , model = 24644} +models.main[19564] = { name = "Alard's Axe +2" , model = 24658} +models.main[19565] = { name = "Richard. Axe +2" , model = 24664} +models.main[19566] = { name = "Guichard's Axe +2" , model = 24654} +models.main[19567] = { name = "Renaud's Axe +2" , model = 24654} +models.main[19568] = { name = "Maschu +2" , model = 24669} +models.main[19569] = { name = "Kunlun +2" , model = 24674} +models.main[19570] = { name = "Atlas +2" , model = 24924} +models.main[19571] = { name = "Sumeru +2" , model = 24672} +models.main[19572] = { name = "Penitence +2" , model = 24770} +models.main[19573] = { name = "Maleficence +2" , model = 24926} +models.main[19574] = { name = "Absolution +2" , model = 24898} +models.main[19575] = { name = "Reckoning +2" , model = 24942} +models.main[19576] = { name = "Cerastes +2" , model = 24785} +models.main[19577] = { name = "Corsesca +2" , model = 24925} +models.main[19578] = { name = "Langdebeve +2" , model = 24789} +models.main[19579] = { name = "Stingray +2" , model = 24954} +models.main[19580] = { name = "Tobi +2" , model = 24889} +models.main[19581] = { name = "Enchu +2" , model = 24943} +models.main[19582] = { name = "Sekka +2" , model = 24888} +models.main[19583] = { name = "Uzura +2" , model = 24886} +models.main[19584] = { name = "Hiradennotachi +2" , model = 24899} +models.main[19585] = { name = "Kokushitsu +2" , model = 24724} +models.main[19586] = { name = "Hyogugusari +2" , model = 24723} +models.main[19587] = { name = "Keitonotachi +2" , model = 24721} +models.main[19588] = { name = "Canne de Cbt. +2" , model = 24692} +models.main[19589] = { name = "Naboot +2" , model = 24679} +models.main[19590] = { name = "Hoeroa +2" , model = 24820} +models.main[19591] = { name = "Makhila +2" , model = 24687} +models.main[19592] = { name = "Taiaha +2" , model = 24874} +models.main[19593] = { name = "Yantok +2" , model = 24872} +models.main[19594] = { name = "Shareeravadi +2" , model = 24871} +models.main[19595] = { name = "Agni's Staff +2" , model = 24881} +models.main[19596] = { name = "Varuna's Staff +2" , model = 24881} +models.main[19597] = { name = "Vayu's Staff +2" , model = 24881} +models.main[19598] = { name = "Kubera's Staff +2" , model = 24881} +models.main[19599] = { name = "Indra's Staff +2" , model = 24881} +models.main[19600] = { name = "Soma's Staff +2" , model = 24881} +models.main[19601] = { name = "Surya's Staff +2" , model = 24881} +models.main[19602] = { name = "Yama's Staff +2" , model = 24881} +models.main[19603] = { name = "Sedikutchi +2" , model = 24879} +models.main[19612] = { name = "Conqueror" , model = 24990} +models.main[19613] = { name = "Glanzfaust" , model = 25078} +models.main[19614] = { name = "Yagrush" , model = 24991} +models.main[19615] = { name = "Laevateinn" , model = 24992} +models.main[19616] = { name = "Murgleis" , model = 24996} +models.main[19617] = { name = "Vajra" , model = 24998} +models.main[19618] = { name = "Burtgang" , model = 25002} +models.main[19619] = { name = "Liberator" , model = 25001} +models.main[19620] = { name = "Aymur" , model = 24989} +models.main[19621] = { name = "Carnwenhan" , model = 25003} +models.main[19623] = { name = "Kogarasumaru" , model = 25000} +models.main[19624] = { name = "Nagi" , model = 24997} +models.main[19625] = { name = "Ryunohige" , model = 24999} +models.main[19626] = { name = "Nirvana" , model = 24993} +models.main[19627] = { name = "Tizona" , model = 24995} +models.main[19629] = { name = "Kenkonken" , model = 25079} +models.main[19630] = { name = "Terpsichore" , model = 25004} +models.main[19631] = { name = "Tupsimati" , model = 25005} +models.main[19632] = { name = "Verethragna" , model = 25076} +models.main[19633] = { name = "Twashtar" , model = 25041} +models.main[19634] = { name = "Almace" , model = 25042} +models.main[19635] = { name = "Caladbolg" , model = 25043} +models.main[19636] = { name = "Farsha" , model = 25044} +models.main[19637] = { name = "Ukonvasara" , model = 25045} +models.main[19638] = { name = "Redemption" , model = 25046} +models.main[19639] = { name = "Rhongomiant" , model = 25088} +models.main[19640] = { name = "Kannagi" , model = 25089} +models.main[19641] = { name = "Masamune" , model = 25090} +models.main[19642] = { name = "Gambanteinn" , model = 25091} +models.main[19643] = { name = "Hvergelmir" , model = 25092} +models.main[19646] = { name = "Revenant Fists +3" , model = 25085} +models.main[19647] = { name = "Ursine Claws +3" , model = 24695} +models.main[19648] = { name = "Taipan Fangs +3" , model = 24701} +models.main[19649] = { name = "Barracudas +3" , model = 24716} +models.main[19650] = { name = "Daka +3" , model = 24955} +models.main[19651] = { name = "Parazonium +3" , model = 24752} +models.main[19652] = { name = "Kila +3" , model = 24756} +models.main[19653] = { name = "Fusetto +3" , model = 24744} +models.main[19654] = { name = "Badelaire +3" , model = 24853} +models.main[19655] = { name = "Khanda +3" , model = 24859} +models.main[19656] = { name = "Shamshir +3" , model = 24829} +models.main[19657] = { name = "Machaera +3" , model = 24957} +models.main[19658] = { name = "Espafut +3" , model = 24646} +models.main[19659] = { name = "Prestelame +3" , model = 24650} +models.main[19660] = { name = "Sombrelame +3" , model = 24641} +models.main[19661] = { name = "Kalavejs +3" , model = 24644} +models.main[19662] = { name = "Alard's Axe +3" , model = 24658} +models.main[19663] = { name = "Richard. Axe +3" , model = 24664} +models.main[19664] = { name = "Guichard's Axe +3" , model = 24654} +models.main[19665] = { name = "Renaud's Axe +3" , model = 24654} +models.main[19666] = { name = "Maschu +3" , model = 24669} +models.main[19667] = { name = "Kunlun +3" , model = 24674} +models.main[19668] = { name = "Atlas +3" , model = 24924} +models.main[19669] = { name = "Sumeru +3" , model = 24672} +models.main[19670] = { name = "Penitence +3" , model = 24770} +models.main[19671] = { name = "Maleficence +3" , model = 24926} +models.main[19672] = { name = "Absolution +3" , model = 24898} +models.main[19673] = { name = "Reckoning +3" , model = 24942} +models.main[19674] = { name = "Cerastes +3" , model = 24785} +models.main[19675] = { name = "Corsesca +3" , model = 24925} +models.main[19676] = { name = "Langdebeve +3" , model = 24789} +models.main[19677] = { name = "Stingray +3" , model = 24954} +models.main[19678] = { name = "Tobi +3" , model = 24889} +models.main[19679] = { name = "Enchu +3" , model = 24943} +models.main[19680] = { name = "Sekka +3" , model = 24888} +models.main[19681] = { name = "Uzura +3" , model = 24886} +models.main[19682] = { name = "Hiradennotachi +3" , model = 24899} +models.main[19683] = { name = "Kokushitsu +3" , model = 24724} +models.main[19684] = { name = "Hyogugusari +3" , model = 24723} +models.main[19685] = { name = "Keitonotachi +3" , model = 24721} +models.main[19686] = { name = "Canne de Cbt. +3" , model = 24692} +models.main[19687] = { name = "Naboot +3" , model = 24679} +models.main[19688] = { name = "Hoeroa +3" , model = 24820} +models.main[19689] = { name = "Makhila +3" , model = 24687} +models.main[19690] = { name = "Taiaha +3" , model = 24874} +models.main[19691] = { name = "Yantok +3" , model = 24872} +models.main[19692] = { name = "Shareeravadi +3" , model = 24871} +models.main[19693] = { name = "Agni's Staff +3" , model = 24881} +models.main[19694] = { name = "Varuna's Staff +3" , model = 24881} +models.main[19695] = { name = "Vayu's Staff +3" , model = 24881} +models.main[19696] = { name = "Kubera's Staff +3" , model = 24881} +models.main[19697] = { name = "Indra's Staff +3" , model = 24881} +models.main[19698] = { name = "Soma's Staff +3" , model = 24881} +models.main[19699] = { name = "Surya's Staff +3" , model = 24881} +models.main[19700] = { name = "Yama's Staff +3" , model = 24881} +models.main[19701] = { name = "Sedikutchi +3" , model = 24879} +models.main[19710] = { name = "Conqueror" , model = 24990} +models.main[19711] = { name = "Glanzfaust" , model = 25078} +models.main[19712] = { name = "Yagrush" , model = 24991} +models.main[19713] = { name = "Laevateinn" , model = 24992} +models.main[19714] = { name = "Murgleis" , model = 24996} +models.main[19715] = { name = "Vajra" , model = 24998} +models.main[19716] = { name = "Burtgang" , model = 25002} +models.main[19717] = { name = "Liberator" , model = 25001} +models.main[19718] = { name = "Aymur" , model = 24989} +models.main[19719] = { name = "Carnwenhan" , model = 25003} +models.main[19721] = { name = "Kogarasumaru" , model = 25000} +models.main[19722] = { name = "Nagi" , model = 24997} +models.main[19723] = { name = "Ryunohige" , model = 24999} +models.main[19724] = { name = "Nirvana" , model = 24993} +models.main[19725] = { name = "Tizona" , model = 24995} +models.main[19727] = { name = "Kenkonken" , model = 25079} +models.main[19728] = { name = "Terpsichore" , model = 25004} +models.main[19729] = { name = "Tupsimati" , model = 25005} +models.main[19746] = { name = "Spharai" , model = 25087} +models.main[19747] = { name = "Mandau" , model = 24910} +models.main[19748] = { name = "Excalibur" , model = 24896} +models.main[19749] = { name = "Ragnarok" , model = 24895} +models.main[19750] = { name = "Guttler" , model = 24923} +models.main[19751] = { name = "Bravura" , model = 24915} +models.main[19752] = { name = "Gungnir" , model = 24793} +models.main[19753] = { name = "Apocalypse" , model = 24914} +models.main[19754] = { name = "Kikoku" , model = 24920} +models.main[19755] = { name = "Amanomurakumo" , model = 24916} +models.main[19756] = { name = "Mjollnir" , model = 24883} +models.main[19757] = { name = "Claustrum" , model = 24918} +models.main[19788] = { name = "Gorkhali Kukri" , model = 24748} +models.main[19789] = { name = "Mahakali's Kukri" , model = 24748} +models.main[19790] = { name = "Oneiros Lance" , model = 24785} +models.main[19791] = { name = "Draca Couse" , model = 24925} +models.main[19792] = { name = "Drachenstich" , model = 24786} +models.main[19793] = { name = "Patientia Lance" , model = 24789} +models.main[19794] = { name = "Delphinius" , model = 25166} +models.main[19795] = { name = "Ereptor Lance" , model = 25012} +models.main[19796] = { name = "Rosschinder" , model = 24781} +models.main[19797] = { name = "Rosschinder +1" , model = 24781} +models.main[19798] = { name = "Drakaina Lance" , model = 25029} +models.main[19799] = { name = "Herja's Fork" , model = 24981} +models.main[19805] = { name = "Verethragna" , model = 25076} +models.main[19806] = { name = "Twashtar" , model = 25041} +models.main[19807] = { name = "Almace" , model = 25042} +models.main[19808] = { name = "Caladbolg" , model = 25043} +models.main[19809] = { name = "Farsha" , model = 25044} +models.main[19810] = { name = "Ukonvasara" , model = 25045} +models.main[19811] = { name = "Redemption" , model = 25046} +models.main[19812] = { name = "Rhongomiant" , model = 25088} +models.main[19813] = { name = "Kannagi" , model = 25089} +models.main[19814] = { name = "Masamune" , model = 25090} +models.main[19815] = { name = "Gambanteinn" , model = 25091} +models.main[19816] = { name = "Hvergelmir" , model = 25092} +models.main[19819] = { name = "Conqueror" , model = 24990} +models.main[19820] = { name = "Glanzfaust" , model = 25078} +models.main[19821] = { name = "Yagrush" , model = 24991} +models.main[19822] = { name = "Laevateinn" , model = 24992} +models.main[19823] = { name = "Murgleis" , model = 24996} +models.main[19824] = { name = "Vajra" , model = 24998} +models.main[19825] = { name = "Burtgang" , model = 25002} +models.main[19826] = { name = "Liberator" , model = 25001} +models.main[19827] = { name = "Aymur" , model = 24989} +models.main[19828] = { name = "Carnwenhan" , model = 25003} +models.main[19830] = { name = "Kogarasumaru" , model = 25000} +models.main[19831] = { name = "Nagi" , model = 24997} +models.main[19832] = { name = "Ryunohige" , model = 24999} +models.main[19833] = { name = "Nirvana" , model = 24993} +models.main[19834] = { name = "Tizona" , model = 24995} +models.main[19836] = { name = "Kenkonken" , model = 25079} +models.main[19837] = { name = "Terpsichore" , model = 25004} +models.main[19838] = { name = "Tupsimati" , model = 25005} +models.main[19839] = { name = "Spharai" , model = 25073} +models.main[19840] = { name = "Mandau" , model = 25120} +models.main[19841] = { name = "Excalibur" , model = 25121} +models.main[19842] = { name = "Ragnarok" , model = 25122} +models.main[19843] = { name = "Guttler" , model = 25123} +models.main[19844] = { name = "Bravura" , model = 25124} +models.main[19845] = { name = "Gungnir" , model = 25125} +models.main[19846] = { name = "Apocalypse" , model = 25126} +models.main[19847] = { name = "Kikoku" , model = 25127} +models.main[19848] = { name = "Amanomurakumo" , model = 25128} +models.main[19849] = { name = "Mjollnir" , model = 25129} +models.main[19850] = { name = "Claustrum" , model = 25130} +models.main[19853] = { name = "Verethragna" , model = 25070} +models.main[19854] = { name = "Twashtar" , model = 25147} +models.main[19855] = { name = "Almace" , model = 25148} +models.main[19856] = { name = "Caladbolg" , model = 25149} +models.main[19857] = { name = "Farsha" , model = 25150} +models.main[19858] = { name = "Ukonvasara" , model = 25151} +models.main[19859] = { name = "Redemption" , model = 25152} +models.main[19860] = { name = "Rhongomiant" , model = 25153} +models.main[19861] = { name = "Kannagi" , model = 25154} +models.main[19862] = { name = "Masamune" , model = 25155} +models.main[19863] = { name = "Gambanteinn" , model = 25156} +models.main[19864] = { name = "Hvergelmir" , model = 25157} +models.main[19867] = { name = "Dumuzis" , model = 25084} +models.main[19868] = { name = "Ursa Majors" , model = 24694} +models.main[19869] = { name = "Oxyuranis" , model = 24698} +models.main[19870] = { name = "Sphyras" , model = 24717} +models.main[19871] = { name = "Khandroma" , model = 24974} +models.main[19872] = { name = "Praxidikai" , model = 24751} +models.main[19873] = { name = "Thokcha" , model = 24756} +models.main[19874] = { name = "Centovente" , model = 24744} +models.main[19875] = { name = "Brunello" , model = 24851} +models.main[19876] = { name = "Khadga" , model = 24859} +models.main[19877] = { name = "Shikargar" , model = 24826} +models.main[19878] = { name = "Thibron" , model = 24957} +models.main[19879] = { name = "Xiphias" , model = 24645} +models.main[19880] = { name = "Fulgurante" , model = 24649} +models.main[19881] = { name = "Tenebreuse" , model = 24640} +models.main[19882] = { name = "Kauriraris" , model = 24644} +models.main[19883] = { name = "Sacripante" , model = 24657} +models.main[19884] = { name = "Ganelon" , model = 24663} +models.main[19885] = { name = "Astolfo" , model = 24660} +models.main[19886] = { name = "Fernagu" , model = 24654} +models.main[19887] = { name = "Shamash" , model = 24668} +models.main[19888] = { name = "Liushi Shan" , model = 24673} +models.main[19889] = { name = "Telamon" , model = 24940} +models.main[19890] = { name = "Tavatimsa" , model = 24672} +models.main[19891] = { name = "Umiliati" , model = 24770} +models.main[19892] = { name = "Ogresse" , model = 24926} +models.main[19893] = { name = "Cloacina" , model = 24898} +models.main[19894] = { name = "Basanizo" , model = 24942} +models.main[19895] = { name = "Daboya" , model = 24785} +models.main[19896] = { name = "Chauve-Souris" , model = 24925} +models.main[19897] = { name = "Nahvalr" , model = 24788} +models.main[19898] = { name = "Sixgill" , model = 24964} +models.main[19899] = { name = "Kasasagi" , model = 24947} +models.main[19900] = { name = "Majimun" , model = 24943} +models.main[19901] = { name = "Arisui" , model = 24888} +models.main[19902] = { name = "Hitaki" , model = 24886} +models.main[19903] = { name = "Torigashira" , model = 24899} +models.main[19904] = { name = "Kawatsutsumi" , model = 24724} +models.main[19905] = { name = "Kabutsuchi" , model = 24720} +models.main[19906] = { name = "Kantonotachi" , model = 24927} +models.main[19907] = { name = "Rose Couverte" , model = 24690} +models.main[19908] = { name = "Tahtib" , model = 24678} +models.main[19909] = { name = "Tutunui" , model = 24824} +models.main[19910] = { name = "Ukaldi" , model = 24686} +models.main[19911] = { name = "Paikea" , model = 24878} +models.main[19912] = { name = "Urduja" , model = 24872} +models.main[19913] = { name = "Tuahjebat" , model = 24870} +models.main[19914] = { name = "Atar I" , model = 24881} +models.main[19915] = { name = "Atar II" , model = 24881} +models.main[19916] = { name = "Atar III" , model = 24881} +models.main[19917] = { name = "Vourukasha I" , model = 24881} +models.main[19918] = { name = "Vourukasha II" , model = 24881} +models.main[19919] = { name = "Vourukasha III" , model = 24881} +models.main[19920] = { name = "Vayuvata I" , model = 24881} +models.main[19921] = { name = "Vayuvata II" , model = 24881} +models.main[19922] = { name = "Vayuvata III" , model = 24881} +models.main[19923] = { name = "Vishrava I" , model = 24881} +models.main[19924] = { name = "Vishrava II" , model = 24881} +models.main[19925] = { name = "Vishrava III" , model = 24881} +models.main[19926] = { name = "Apamajas I" , model = 24881} +models.main[19927] = { name = "Apamajas II" , model = 24881} +models.main[19928] = { name = "Apamajas III" , model = 24881} +models.main[19929] = { name = "Haoma I" , model = 24881} +models.main[19930] = { name = "Haoma II" , model = 24881} +models.main[19931] = { name = "Haoma III" , model = 24881} +models.main[19932] = { name = "Arka I" , model = 24881} +models.main[19933] = { name = "Arka II" , model = 24881} +models.main[19934] = { name = "Arka III" , model = 24881} +models.main[19935] = { name = "Arka IV" , model = 24881} +models.main[19936] = { name = "Xsaeta I" , model = 24881} +models.main[19937] = { name = "Xsaeta II" , model = 24881} +models.main[19938] = { name = "Xsaeta III" , model = 24881} +models.main[19939] = { name = "Muruga" , model = 24879} +models.main[19948] = { name = "Conqueror" , model = 25131} +models.main[19949] = { name = "Glanzfaust" , model = 25072} +models.main[19950] = { name = "Yagrush" , model = 25132} +models.main[19951] = { name = "Laevateinn" , model = 25133} +models.main[19952] = { name = "Murgleis" , model = 25134} +models.main[19953] = { name = "Vajra" , model = 25135} +models.main[19954] = { name = "Burtgang" , model = 25136} +models.main[19955] = { name = "Liberator" , model = 25137} +models.main[19956] = { name = "Aymur" , model = 25138} +models.main[19957] = { name = "Carnwenhan" , model = 25139} +models.main[19959] = { name = "Kogarasumaru" , model = 25140} +models.main[19960] = { name = "Nagi" , model = 25141} +models.main[19961] = { name = "Ryunohige" , model = 25142} +models.main[19962] = { name = "Nirvana" , model = 25143} +models.main[19963] = { name = "Tizona" , model = 25144} +models.main[19965] = { name = "Kenkonken" , model = 25071} +models.main[19966] = { name = "Terpsichore" , model = 25145} +models.main[19967] = { name = "Tupsimati" , model = 25146} +models.main[20480] = { name = "Spharai" , model = 25087} +models.main[20481] = { name = "Spharai" , model = 25073} +models.main[20482] = { name = "Glanzfaust" , model = 25078} +models.main[20483] = { name = "Glanzfaust" , model = 25072} +models.main[20484] = { name = "Kenkonken" , model = 25079} +models.main[20485] = { name = "Kenkonken" , model = 25071} +models.main[20486] = { name = "Verethragna" , model = 25076} +models.main[20487] = { name = "Verethragna" , model = 25070} +models.main[20505] = { name = "Condemners" , model = 25086} +models.main[20506] = { name = "Suwaiyas" , model = 25075} +models.main[20507] = { name = "Comeuppances" , model = 25077} +models.main[20508] = { name = "Comeuppances +1" , model = 25077} +models.main[20509] = { name = "Spharai" , model = 25073} +models.main[20510] = { name = "Glanzfaust" , model = 25072} +models.main[20511] = { name = "Kenkonken" , model = 25071} +models.main[20512] = { name = "Verethragna" , model = 25070} +models.main[20514] = { name = "Aphelion Knuckles" , model = 25059} +models.main[20515] = { name = "Godhands" , model = 25060} +models.main[20516] = { name = "Denouements" , model = 25061} +models.main[20517] = { name = "Fleshcarvers" , model = 24716} +models.main[20518] = { name = "Eshus" , model = 25069} +models.main[20519] = { name = "Hammerfists" , model = 25077} +models.main[20520] = { name = "Midnights" , model = 25081} +models.main[20521] = { name = "Emeici" , model = 24693} +models.main[20522] = { name = "Emeici +1" , model = 24693} +models.main[20523] = { name = "Chastisers" , model = 25074} +models.main[20524] = { name = "Nibiru Sainti" , model = 25063} +models.main[20525] = { name = "Blurred Claws" , model = 25062} +models.main[20526] = { name = "Blurred Claws +1" , model = 25062} +models.main[20527] = { name = "Fists of Fury" , model = 24705} +models.main[20528] = { name = "Fists of Fury +1" , model = 24705} +models.main[20529] = { name = "Calved Claws" , model = 24701} +models.main[20530] = { name = "Ohrmazd" , model = 25082} +models.main[20531] = { name = "Homestead Cesti" , model = 25067} +models.main[20532] = { name = "Worm Feelers" , model = 25065} +models.main[20533] = { name = "Worm Feelers +1" , model = 25065} +models.main[20534] = { name = "Nyepel" , model = 25077} +models.main[20535] = { name = "Ohtas" , model = 25081} +models.main[20536] = { name = "Tinhaspa" , model = 24710} +models.main[20537] = { name = "Bhakazi Sainti" , model = 25080} +models.main[20538] = { name = "Bhakazi Sainti +1" , model = 25080} +models.main[20539] = { name = "Ninzas +2" , model = 25083} +models.main[20540] = { name = "Em. Baghnakhs" , model = 24718} +models.main[20541] = { name = "Pinion Cesti" , model = 24703} +models.main[20542] = { name = "Gnafron's Adargas" , model = 25086} +models.main[20543] = { name = "Maochinoli" , model = 25068} +models.main[20544] = { name = "Dumuzis -1" , model = 25084} +models.main[20545] = { name = "Cama. Knuckles" , model = 24705} +models.main[20546] = { name = "Ninzas +1" , model = 25083} +models.main[20547] = { name = "Forefront Cesti" , model = 25067} +models.main[20548] = { name = "Oatixur" , model = 25068} +models.main[20549] = { name = "Rigor Baghnakhs" , model = 24719} +models.main[20550] = { name = "Vineslash Cesti" , model = 24703} +models.main[20551] = { name = "Akua Sainti" , model = 25084} +models.main[20552] = { name = "Akua Sainti +1" , model = 25084} +models.main[20553] = { name = "Ninzas" , model = 25083} +models.main[20554] = { name = "Tlalpoloani" , model = 25068} +models.main[20555] = { name = "Mandau" , model = 24910} +models.main[20556] = { name = "Mandau" , model = 25120} +models.main[20557] = { name = "Terpsichore" , model = 25004} +models.main[20558] = { name = "Terpsichore" , model = 25145} +models.main[20559] = { name = "Vajra" , model = 24998} +models.main[20560] = { name = "Vajra" , model = 25135} +models.main[20561] = { name = "Carnwenhan" , model = 25003} +models.main[20562] = { name = "Carnwenhan" , model = 25139} +models.main[20563] = { name = "Twashtar" , model = 25041} +models.main[20564] = { name = "Twashtar" , model = 25147} +models.main[20573] = { name = "Aern Dagger" , model = 25402} +models.main[20576] = { name = "Qutrub Knife" , model = 25407} +models.main[20577] = { name = "Chicken Knife II" , model = 25360} +models.main[20579] = { name = "Skinflayer" , model = 25006} +models.main[20580] = { name = "Kustawi" , model = 24733} +models.main[20581] = { name = "Kustawi +1" , model = 24733} +models.main[20583] = { name = "Mandau" , model = 25120} +models.main[20584] = { name = "Terpsichore" , model = 25145} +models.main[20585] = { name = "Vajra" , model = 25135} +models.main[20586] = { name = "Carnwenhan" , model = 25139} +models.main[20587] = { name = "Twashtar" , model = 25147} +models.main[20592] = { name = "Sangoma" , model = 25334} +models.main[20594] = { name = "Aeneas" , model = 25336} +models.main[20595] = { name = "Malevolence" , model = 25117} +models.main[20596] = { name = "Taming Sari" , model = 25204} +models.main[20597] = { name = "Enchufla" , model = 25026} +models.main[20598] = { name = "Shijo" , model = 24972} +models.main[20599] = { name = "Kali" , model = 25093} +models.main[20600] = { name = "Nibiru Knife" , model = 25308} +models.main[20601] = { name = "Blurred Knife" , model = 25035} +models.main[20602] = { name = "Blurred Knife +1" , model = 25035} +models.main[20603] = { name = "Ternion Dagger" , model = 24744} +models.main[20604] = { name = "Ternion Dagger +1" , model = 24744} +models.main[20605] = { name = "Odium" , model = 25307} +models.main[20606] = { name = "Anathema Harpe" , model = 25109} +models.main[20607] = { name = "Anathema Harpe +1" , model = 25109} +models.main[20608] = { name = "Jugo Kukri" , model = 24747} +models.main[20609] = { name = "Jugo Kukri +1" , model = 24747} +models.main[20610] = { name = "Rhadamanthus" , model = 25300} +models.main[20611] = { name = "Sangarius" , model = 24863} +models.main[20612] = { name = "Sangarius +1" , model = 24863} +models.main[20613] = { name = "Pukulatmuj" , model = 24844} +models.main[20614] = { name = "Pukulatmuj +1" , model = 24844} +models.main[20615] = { name = "Levante Dagger" , model = 24742} +models.main[20616] = { name = "Ipetam" , model = 25286} +models.main[20617] = { name = "Homestead Dagger" , model = 24742} +models.main[20618] = { name = "Sandung" , model = 25173} +models.main[20619] = { name = "Polyhymnia" , model = 25026} +models.main[20620] = { name = "Sabebus" , model = 24752} +models.main[20621] = { name = "Nanti Knife" , model = 24756} +models.main[20622] = { name = "Nanti Knife +1" , model = 24756} +models.main[20623] = { name = "Leisilonu +2" , model = 24755} +models.main[20624] = { name = "Eminent Dagger" , model = 24739} +models.main[20625] = { name = "Secespita" , model = 24751} +models.main[20626] = { name = "Blitto Needle" , model = 24739} +models.main[20627] = { name = "Surcouf's Jambiya" , model = 24955} +models.main[20628] = { name = "Mindmeld Kris" , model = 24922} +models.main[20629] = { name = "Legato Dagger" , model = 25117} +models.main[20630] = { name = "Atoyac" , model = 25191} +models.main[20631] = { name = "Khandroma -1" , model = 24974} +models.main[20632] = { name = "Vanir Knife" , model = 24734} +models.main[20633] = { name = "Cama. Dagger" , model = 25204} +models.main[20634] = { name = "Leisilonu +1" , model = 24755} +models.main[20635] = { name = "Forefront Dagger" , model = 24742} +models.main[20636] = { name = "Izhiikoh" , model = 25191} +models.main[20637] = { name = "Aphotic Kukri" , model = 24747} +models.main[20638] = { name = "Coalition Dirk" , model = 25182} +models.main[20639] = { name = "Oxidant Baselard" , model = 24746} +models.main[20640] = { name = "Nitric Baselard" , model = 24746} +models.main[20641] = { name = "Leisilonu" , model = 24755} +models.main[20642] = { name = "Tzustes Knife +1" , model = 24736} +models.main[20643] = { name = "Macoquetza" , model = 25191} +models.main[20644] = { name = "Tzustes Knife" , model = 24736} +models.main[20645] = { name = "Excalibur" , model = 24896} +models.main[20646] = { name = "Excalibur" , model = 25121} +models.main[20647] = { name = "Murgleis" , model = 24996} +models.main[20648] = { name = "Murgleis" , model = 25134} +models.main[20649] = { name = "Burtgang" , model = 25002} +models.main[20650] = { name = "Burtgang" , model = 25136} +models.main[20651] = { name = "Tizona" , model = 24995} +models.main[20652] = { name = "Tizona" , model = 25144} +models.main[20653] = { name = "Almace" , model = 25042} +models.main[20654] = { name = "Almace" , model = 25148} +models.main[20665] = { name = "Kam'lanaut's Sword" , model = 25383} +models.main[20666] = { name = "Blizzard Brand" , model = 25358} +models.main[20667] = { name = "Blizzard Brand +1" , model = 25358} +models.main[20668] = { name = "Firetongue" , model = 25359} +models.main[20669] = { name = "Firetongue +1" , model = 25359} +models.main[20674] = { name = "Aern Sword" , model = 25401} +models.main[20677] = { name = "Colada" , model = 24966} +models.main[20678] = { name = "Firangi" , model = 25021} +models.main[20679] = { name = "Tanmogayi" , model = 24934} +models.main[20680] = { name = "Tanmogayi +1" , model = 24934} +models.main[20681] = { name = "Flyssa" , model = 24975} +models.main[20682] = { name = "Flyssa +1" , model = 24975} +models.main[20683] = { name = "Zantetsuken" , model = 24980} +models.main[20685] = { name = "Excalibur" , model = 25121} +models.main[20686] = { name = "Murgleis" , model = 25134} +models.main[20687] = { name = "Burtgang" , model = 25136} +models.main[20688] = { name = "Tizona" , model = 25144} +models.main[20689] = { name = "Almace" , model = 25148} +models.main[20690] = { name = "Reikiko" , model = 25347} +models.main[20694] = { name = "Fermion Sword" , model = 25332} +models.main[20695] = { name = "Sequence" , model = 25337} +models.main[20696] = { name = "Combuster" , model = 24854} +models.main[20697] = { name = "Combuster +1" , model = 24854} +models.main[20698] = { name = "Fettering Blade" , model = 25333} +models.main[20699] = { name = "Koboto" , model = 24835} +models.main[20700] = { name = "Nixxer" , model = 24975} +models.main[20701] = { name = "Iris" , model = 25007} +models.main[20702] = { name = "Emissary" , model = 24826} +models.main[20703] = { name = "Deacon Saber" , model = 25160} +models.main[20704] = { name = "Deacon Sword" , model = 25161} +models.main[20705] = { name = "Brilliance" , model = 25326} +models.main[20706] = { name = "Vampirism" , model = 25328} +models.main[20707] = { name = "Medeina Kilij" , model = 24978} +models.main[20708] = { name = "Demersal Degen" , model = 24761} +models.main[20709] = { name = "Demers. Degen +1" , model = 24761} +models.main[20710] = { name = "Nibiru Blade" , model = 25309} +models.main[20711] = { name = "Blurred Sword" , model = 25036} +models.main[20712] = { name = "Blurred Sword +1" , model = 25036} +models.main[20713] = { name = "Excalipoor" , model = 25305} +models.main[20714] = { name = "Excalipoor II" , model = 25305} +models.main[20715] = { name = "Acclimator" , model = 25301} +models.main[20716] = { name = "Perfervid Sword" , model = 24831} +models.main[20717] = { name = "Arendsi Fleuret" , model = 24768} +models.main[20718] = { name = "Claidheamh Soluis" , model = 25287} +models.main[20719] = { name = "Homestead Blade" , model = 24838} +models.main[20720] = { name = "Egeking" , model = 24830} +models.main[20721] = { name = "Mimesis" , model = 24858} +models.main[20722] = { name = "Usonmunku" , model = 24843} +models.main[20723] = { name = "Dija Sword" , model = 24843} +models.main[20724] = { name = "Dija Sword +1" , model = 24843} +models.main[20725] = { name = "Iztaasu +2" , model = 25094} +models.main[20726] = { name = "Eminent Scimitar" , model = 24834} +models.main[20727] = { name = "Tabahi Fleuret" , model = 24768} +models.main[20728] = { name = "Kheshig Blade" , model = 24857} +models.main[20729] = { name = "Vivifiante" , model = 24862} +models.main[20730] = { name = "Predatrice" , model = 24960} +models.main[20731] = { name = "Xiutleato" , model = 25192} +models.main[20732] = { name = "Brunello -1" , model = 24851} +models.main[20733] = { name = "Anahera Saber" , model = 25160} +models.main[20734] = { name = "Anahera Sword" , model = 25161} +models.main[20735] = { name = "Cama. Blade" , model = 25205} +models.main[20736] = { name = "Iztaasu +1" , model = 25094} +models.main[20737] = { name = "Forefront Blade" , model = 24838} +models.main[20738] = { name = "Buramenk'ah" , model = 25192} +models.main[20739] = { name = "Halachuinic Sword" , model = 24860} +models.main[20740] = { name = "Camatlatia" , model = 25192} +models.main[20741] = { name = "Coalition Blade" , model = 25183} +models.main[20742] = { name = "Iztaasu" , model = 25094} +models.main[20743] = { name = "Bihkah Sword +1" , model = 24846} +models.main[20744] = { name = "Bihkah Sword" , model = 24846} +models.main[20745] = { name = "Ragnarok" , model = 24895} +models.main[20746] = { name = "Ragnarok" , model = 25122} +models.main[20747] = { name = "Caladbolg" , model = 25043} +models.main[20748] = { name = "Caladbolg" , model = 25149} +models.main[20749] = { name = "Trial Blade" , model = 25184} +models.main[20750] = { name = "Lexeme Blade" , model = 25184} +models.main[20751] = { name = "Lexeme Blade" , model = 25184} +models.main[20752] = { name = "Lexeme Blade" , model = 25184} +models.main[20753] = { name = "Epeolatry" , model = 25282} +models.main[20754] = { name = "Malfeasance" , model = 25306} +models.main[20755] = { name = "Malfeasance +1" , model = 25306} +models.main[20756] = { name = "Soulcleaver" , model = 24983} +models.main[20757] = { name = "Foreshock Sword" , model = 25174} +models.main[20758] = { name = "Mekosuchus Blade" , model = 25202} +models.main[20759] = { name = "Macbain" , model = 25288} +models.main[20760] = { name = "Home. Claymore" , model = 24642} +models.main[20761] = { name = "Aettir" , model = 25281} +models.main[20762] = { name = "Ukudyoni" , model = 25214} +models.main[20763] = { name = "Kbiroj" , model = 24641} +models.main[20764] = { name = "Crobaci +2" , model = 25008} +models.main[20765] = { name = "Tunglmyrkvi" , model = 24983} +models.main[20766] = { name = "Eminent Sword" , model = 24641} +models.main[20767] = { name = "Medicor Sword" , model = 24640} +models.main[20768] = { name = "Kaquljaan" , model = 25214} +models.main[20769] = { name = "Xiphias -1" , model = 24645} +models.main[20770] = { name = "Mes'yohi Sword" , model = 24647} +models.main[20771] = { name = "Cama. Claymore" , model = 25206} +models.main[20772] = { name = "Voay Sword -1" , model = 25202} +models.main[20773] = { name = "Voay Sword" , model = 25202} +models.main[20774] = { name = "Voay Sword +1" , model = 25202} +models.main[20775] = { name = "Crobaci +1" , model = 25008} +models.main[20776] = { name = "Beorc Sword" , model = 25184} +models.main[20777] = { name = "F.front Claymore" , model = 24642} +models.main[20778] = { name = "Bereaver" , model = 24644} +models.main[20779] = { name = "Senbaak Nagan" , model = 24649} +models.main[20780] = { name = "Senbaak Nagan +1" , model = 24649} +models.main[20781] = { name = "Sowilo Claymore" , model = 24644} +models.main[20782] = { name = "Coalition Sword" , model = 25184} +models.main[20783] = { name = "Uruz Blade" , model = 24648} +models.main[20784] = { name = "Uruz Blade +1" , model = 24648} +models.main[20785] = { name = "Thurisaz Blade" , model = 24643} +models.main[20786] = { name = "Thurisaz Blade +1" , model = 24643} +models.main[20787] = { name = "Crobaci" , model = 25008} +models.main[20788] = { name = "Hatzoaar Sword +1" , model = 24642} +models.main[20789] = { name = "Hatzoaar Sword" , model = 24642} +models.main[20790] = { name = "Guttler" , model = 24923} +models.main[20791] = { name = "Guttler" , model = 25123} +models.main[20792] = { name = "Aymur" , model = 24989} +models.main[20793] = { name = "Aymur" , model = 25138} +models.main[20794] = { name = "Farsha" , model = 25044} +models.main[20795] = { name = "Farsha" , model = 25150} +models.main[20796] = { name = "Purgation" , model = 24963} +models.main[20797] = { name = "Skullrender" , model = 25167} +models.main[20798] = { name = "Deacon Tabar" , model = 25163} +models.main[20799] = { name = "Mdomo Axe" , model = 24929} +models.main[20800] = { name = "Mdomo Axe +1" , model = 24929} +models.main[20801] = { name = "Nibiru Tabar" , model = 25311} +models.main[20802] = { name = "Blurred Axe" , model = 25319} +models.main[20803] = { name = "Blurred Axe +1" , model = 25319} +models.main[20804] = { name = "Perun" , model = 24667} +models.main[20805] = { name = "Perun +1" , model = 24667} +models.main[20806] = { name = "Buramgh" , model = 24659} +models.main[20807] = { name = "Buramgh +1" , model = 24659} +models.main[20808] = { name = "Tramontane Axe" , model = 24657} +models.main[20809] = { name = "Kumbhakarna" , model = 25289} +models.main[20810] = { name = "Homestead Axe" , model = 24659} +models.main[20811] = { name = "Arktoi" , model = 25176} +models.main[20812] = { name = "Izizoeksi" , model = 25197} +models.main[20813] = { name = "Emxgha" , model = 24663} +models.main[20814] = { name = "Budliqa" , model = 24666} +models.main[20815] = { name = "Budliqa +1" , model = 24666} +models.main[20816] = { name = "Faizzeer +2" , model = 24963} +models.main[20817] = { name = "Eminent Axe" , model = 24658} +models.main[20818] = { name = "Hurlbat" , model = 24667} +models.main[20819] = { name = "Antican Axe" , model = 24658} +models.main[20820] = { name = "Hatxiik" , model = 25193} +models.main[20821] = { name = "Sacripante -1" , model = 24657} +models.main[20822] = { name = "Anahera Tabar" , model = 25163} +models.main[20823] = { name = "Cama. Axe" , model = 25207} +models.main[20824] = { name = "Faizzeer +1" , model = 24963} +models.main[20825] = { name = "Forefront Axe" , model = 24659} +models.main[20826] = { name = "Hunahpu" , model = 25197} +models.main[20827] = { name = "Kerehcatl" , model = 25193} +models.main[20828] = { name = "Brethren Axe" , model = 24667} +models.main[20829] = { name = "Icoyoca" , model = 25193} +models.main[20830] = { name = "Coalition Axe" , model = 25185} +models.main[20831] = { name = "Aalak' Axe" , model = 24660} +models.main[20832] = { name = "Aalak' Axe +1" , model = 24660} +models.main[20833] = { name = "Faizzeer" , model = 24963} +models.main[20835] = { name = "Bravura" , model = 24915} +models.main[20836] = { name = "Bravura" , model = 25124} +models.main[20837] = { name = "Conqueror" , model = 24990} +models.main[20838] = { name = "Conqueror" , model = 25131} +models.main[20839] = { name = "Ukonvasara" , model = 25045} +models.main[20840] = { name = "Ukonvasara" , model = 25151} +models.main[20842] = { name = "Reikiono" , model = 25348} +models.main[20843] = { name = "Chango" , model = 25340} +models.main[20844] = { name = "Ferocity" , model = 25096} +models.main[20845] = { name = "Instigator" , model = 24939} +models.main[20846] = { name = "Jokushuono" , model = 24674} +models.main[20847] = { name = "Router" , model = 25179} +models.main[20848] = { name = "Nibiru Chopper" , model = 24940} +models.main[20849] = { name = "Blurred Cleaver" , model = 25320} +models.main[20850] = { name = "Blurred Cleaver +1" , model = 25320} +models.main[20851] = { name = "Aizkora" , model = 24915} +models.main[20852] = { name = "Aizkora +1" , model = 24915} +models.main[20853] = { name = "Beheader" , model = 24669} +models.main[20854] = { name = "Beheader +1" , model = 24669} +models.main[20855] = { name = "Devivifier" , model = 25298} +models.main[20856] = { name = "Phreatic Axe" , model = 25027} +models.main[20857] = { name = "Svarga" , model = 25290} +models.main[20858] = { name = "Lightreaver" , model = 24674} +models.main[20859] = { name = "Home. Labrys" , model = 25190} +models.main[20860] = { name = "Minos" , model = 24911} +models.main[20861] = { name = "Qalgwer" , model = 25199} +models.main[20862] = { name = "Lekboza" , model = 24915} +models.main[20863] = { name = "Iclamar +2" , model = 25024} +models.main[20864] = { name = "Castigation" , model = 25024} +models.main[20865] = { name = "Eminent Voulge" , model = 24941} +models.main[20866] = { name = "Parashu" , model = 24671} +models.main[20867] = { name = "Shamash -1" , model = 24668} +models.main[20869] = { name = "Cama. Reaver" , model = 24669} +models.main[20870] = { name = "Iclamar +1" , model = 25024} +models.main[20871] = { name = "Forefront Labrys" , model = 25190} +models.main[20872] = { name = "Ixtab" , model = 25199} +models.main[20873] = { name = "Bloodbath Axe" , model = 24668} +models.main[20874] = { name = "Razorfury" , model = 24924} +models.main[20875] = { name = "Razorfury +1" , model = 24924} +models.main[20876] = { name = "Trunkcleaver" , model = 24673} +models.main[20877] = { name = "Iclamar" , model = 25024} +models.main[20878] = { name = "Nohkux Axe" , model = 24669} +models.main[20879] = { name = "Nohkux Axe +1" , model = 24669} +models.main[20880] = { name = "Apocalypse" , model = 24914} +models.main[20881] = { name = "Apocalypse" , model = 25126} +models.main[20882] = { name = "Liberator" , model = 25011} +models.main[20883] = { name = "Liberator" , model = 25137} +models.main[20884] = { name = "Redemption" , model = 25046} +models.main[20885] = { name = "Redemption" , model = 25152} +models.main[20887] = { name = "Dacnomania" , model = 25349} +models.main[20889] = { name = "Misanthropy" , model = 25335} +models.main[20890] = { name = "Anguta" , model = 25341} +models.main[20891] = { name = "Brutality" , model = 24898} +models.main[20892] = { name = "Deathbane" , model = 24777} +models.main[20893] = { name = "Shukuyu's Scythe" , model = 24773} +models.main[20894] = { name = "Deacon Scythe" , model = 25162} +models.main[20895] = { name = "Nibiru Sickle" , model = 25313} +models.main[20896] = { name = "Blurred Scythe" , model = 25321} +models.main[20897] = { name = "Blurred Scythe +1" , model = 25321} +models.main[20898] = { name = "Triska Scythe" , model = 24777} +models.main[20899] = { name = "Triska Scythe +1" , model = 24777} +models.main[20900] = { name = "Meekculler" , model = 24777} +models.main[20901] = { name = "Inanna" , model = 25291} +models.main[20903] = { name = "Home. Scythe" , model = 25196} +models.main[20904] = { name = "Cronus" , model = 25011} +models.main[20905] = { name = "Tajabit" , model = 25198} +models.main[20906] = { name = "Vunetshelo" , model = 24777} +models.main[20907] = { name = "Iizamal +2" , model = 25097} +models.main[20908] = { name = "Eminent Sickle" , model = 24969} +models.main[20909] = { name = "Hoe" , model = 25215} +models.main[20910] = { name = "Anaimatos Scythe" , model = 24777} +models.main[20911] = { name = "Last Rest" , model = 24942} +models.main[20912] = { name = "Umiliati -1" , model = 24770} +models.main[20913] = { name = "Anahera Scythe" , model = 25162} +models.main[20914] = { name = "Cama. Scythe" , model = 24770} +models.main[20915] = { name = "Iizamal +1" , model = 25097} +models.main[20916] = { name = "Forefront Scythe" , model = 25196} +models.main[20917] = { name = "Xbalanque" , model = 25198} +models.main[20918] = { name = "Dimmet Scythe" , model = 24772} +models.main[20919] = { name = "Lacryma Sickle" , model = 24942} +models.main[20920] = { name = "Lacryma Sickle +1" , model = 24942} +models.main[20921] = { name = "Fieldrazer Scythe" , model = 24948} +models.main[20922] = { name = "Aak'ab Scythe" , model = 24777} +models.main[20923] = { name = "Aak'ab Scythe +1" , model = 24777} +models.main[20924] = { name = "Iizamal" , model = 25097} +models.main[20925] = { name = "Gungnir" , model = 24793} +models.main[20926] = { name = "Gungnir" , model = 25125} +models.main[20927] = { name = "Ryunohige" , model = 24999} +models.main[20928] = { name = "Ryunohige" , model = 25142} +models.main[20929] = { name = "Rhongomiant" , model = 25088} +models.main[20930] = { name = "Rhongomiant" , model = 25153} +models.main[20932] = { name = "Habile Mazrak" , model = 24964} +models.main[20933] = { name = "Hotengeki" , model = 25435} +models.main[20935] = { name = "Trishula" , model = 25342} +models.main[20936] = { name = "Koresuke" , model = 25020} +models.main[20937] = { name = "Rhomphaia" , model = 24984} +models.main[20938] = { name = "Annealed Lance" , model = 25166} +models.main[20939] = { name = "Nibiru Lance" , model = 25314} +models.main[20940] = { name = "Blurred Lance" , model = 25037} +models.main[20941] = { name = "Blurred Lance +1" , model = 25037} +models.main[20942] = { name = "Gae Derg" , model = 24785} +models.main[20943] = { name = "Gae Derg +1" , model = 24785} +models.main[20944] = { name = "Pelagos Lance" , model = 24792} +models.main[20945] = { name = "Nativus Halberd" , model = 24778} +models.main[20946] = { name = "Olyndicus" , model = 25292} +models.main[20947] = { name = "Homestead Lance" , model = 24789} +models.main[20948] = { name = "Areadbhar" , model = 24984} +models.main[20949] = { name = "Kumalo" , model = 24946} +models.main[20950] = { name = "Terebrokath" , model = 24788} +models.main[20951] = { name = "Terebrokath +1" , model = 24788} +models.main[20952] = { name = "Qatsunoci +2" , model = 25028} +models.main[20953] = { name = "Escritorio" , model = 25280} +models.main[20954] = { name = "Eminent Lance" , model = 25020} +models.main[20955] = { name = "Aigilis Lance" , model = 24787} +models.main[20956] = { name = "Sibat" , model = 24778} +models.main[20957] = { name = "Concido Course" , model = 24925} +models.main[20958] = { name = "Kuakuakait" , model = 25195} +models.main[20959] = { name = "Daboya -1" , model = 24785} +models.main[20960] = { name = "Cama. Lance" , model = 25208} +models.main[20961] = { name = "Qatsunoci +1" , model = 25028} +models.main[20962] = { name = "Forefront Lance" , model = 24789} +models.main[20963] = { name = "Upukirex" , model = 25195} +models.main[20964] = { name = "Ophidian Trident" , model = 24792} +models.main[20965] = { name = "Tlamini" , model = 25195} +models.main[20966] = { name = "Coalition Lance" , model = 25186} +models.main[20967] = { name = "Qatsunoci" , model = 25028} +models.main[20968] = { name = "Chanar Xyston +1" , model = 24786} +models.main[20969] = { name = "Chanar Xyston" , model = 24786} +models.main[20970] = { name = "Kikoku" , model = 24920} +models.main[20971] = { name = "Kikoku" , model = 25127} +models.main[20972] = { name = "Nagi" , model = 24997} +models.main[20973] = { name = "Nagi" , model = 25141} +models.main[20974] = { name = "Kannagi" , model = 25089} +models.main[20975] = { name = "Kannagi" , model = 25154} +models.main[20977] = { name = "Heishi Shorinken" , model = 25343} +models.main[20978] = { name = "Ochu" , model = 25189} +models.main[20979] = { name = "Aizushintogo" , model = 25015} +models.main[20980] = { name = "Raicho" , model = 24976} +models.main[20981] = { name = "Raicho +1" , model = 24976} +models.main[20982] = { name = "Shuhansadamune" , model = 25098} +models.main[20983] = { name = "Mijin" , model = 25308} +models.main[20984] = { name = "Kujaku" , model = 25322} +models.main[20985] = { name = "Kujaku +1" , model = 25322} +models.main[20986] = { name = "Achiuchikapu" , model = 25303} +models.main[20987] = { name = "Tancho" , model = 24888} +models.main[20988] = { name = "Tancho +1" , model = 24888} +models.main[20989] = { name = "Izuna" , model = 25293} +models.main[20990] = { name = "Jushimatsu" , model = 25285} +models.main[20991] = { name = "Chidori" , model = 24885} +models.main[20992] = { name = "Taikogane" , model = 25285} +models.main[20993] = { name = "Senkutanto" , model = 25189} +models.main[20994] = { name = "Shigi" , model = 25181} +models.main[20995] = { name = "Isuka" , model = 24888} +models.main[20996] = { name = "Kannakiri +2" , model = 25023} +models.main[20997] = { name = "Raimitsukane" , model = 24889} +models.main[20998] = { name = "Kaitsuburi" , model = 24970} +models.main[20999] = { name = "Habukatana" , model = 24886} +models.main[21000] = { name = "Magorokuhocho" , model = 24885} +models.main[21001] = { name = "Kasasagi -1" , model = 24889} +models.main[21003] = { name = "Cama. Katana" , model = 24886} +models.main[21004] = { name = "Kannakiri +1" , model = 25023} +models.main[21005] = { name = "Kiji" , model = 24890} +models.main[21006] = { name = "Pamun" , model = 24943} +models.main[21007] = { name = "Pamun +1" , model = 24943} +models.main[21008] = { name = "Kotekirigo" , model = 24888} +models.main[21009] = { name = "Nakajimarai" , model = 24886} +models.main[21010] = { name = "Nakajimarai +1" , model = 24886} +models.main[21011] = { name = "Enju" , model = 24889} +models.main[21012] = { name = "Enju +1" , model = 24889} +models.main[21013] = { name = "Kannakiri" , model = 25023} +models.main[21014] = { name = "Ichijintanto" , model = 25189} +models.main[21015] = { name = "Amanomurakumo" , model = 24916} +models.main[21016] = { name = "Amanomurakumo" , model = 25128} +models.main[21017] = { name = "Kogarasumaru" , model = 25000} +models.main[21018] = { name = "Kogarasumaru" , model = 25140} +models.main[21019] = { name = "Masamune" , model = 25090} +models.main[21020] = { name = "Masamune" , model = 25155} +models.main[21021] = { name = "Umaru" , model = 25178} +models.main[21022] = { name = "Shishio" , model = 24727} +models.main[21025] = { name = "Dojikiri Yasutsuna" , model = 25344} +models.main[21026] = { name = "Himetsuruichimonji" , model = 25188} +models.main[21027] = { name = "Ichigohitofuri" , model = 25016} +models.main[21028] = { name = "Deacon Blade" , model = 25164} +models.main[21029] = { name = "Norifusa" , model = 24731} +models.main[21030] = { name = "Norifusa +1" , model = 24731} +models.main[21031] = { name = "Sensui" , model = 25316} +models.main[21032] = { name = "Kunitsuna" , model = 25323} +models.main[21033] = { name = "Kunitsuna +1" , model = 25323} +models.main[21034] = { name = "Kunimune" , model = 24722} +models.main[21035] = { name = "Kunimune +1" , model = 24722} +models.main[21036] = { name = "Atakigiri" , model = 25016} +models.main[21037] = { name = "Nenekirimaru" , model = 25294} +models.main[21038] = { name = "Senkuto" , model = 25188} +models.main[21039] = { name = "Kurikaranotachi" , model = 24899} +models.main[21040] = { name = "Shokudaikiri" , model = 24727} +models.main[21041] = { name = "Sukezane" , model = 24720} +models.main[21042] = { name = "Sukezane +1" , model = 24720} +models.main[21043] = { name = "Shichishito +2" , model = 25099} +models.main[21044] = { name = "Ichimonji-Yofusa" , model = 24720} +models.main[21045] = { name = "Bukyoku" , model = 24727} +models.main[21046] = { name = "Kiikanemitsu" , model = 24732} +models.main[21047] = { name = "Azukinagamitsu" , model = 25194} +models.main[21048] = { name = "Torigashira -1" , model = 24968} +models.main[21049] = { name = "Anahera Blade" , model = 25164} +models.main[21050] = { name = "Cama. Tachi" , model = 24723} +models.main[21051] = { name = "Shichishito +1" , model = 25099} +models.main[21052] = { name = "Tsurumaru" , model = 25194} +models.main[21053] = { name = "Uguisumaru" , model = 24732} +models.main[21054] = { name = "Suijingiri KM" , model = 25194} +models.main[21055] = { name = "Kashiwadachi" , model = 24722} +models.main[21056] = { name = "Tomonari" , model = 24968} +models.main[21057] = { name = "Tomonari +1" , model = 24968} +models.main[21058] = { name = "Shichishito" , model = 25099} +models.main[21059] = { name = "Ichijinto" , model = 25188} +models.main[21060] = { name = "Mjollnir" , model = 24883} +models.main[21061] = { name = "Mjollnir" , model = 25129} +models.main[21062] = { name = "Yagrush" , model = 24991} +models.main[21063] = { name = "Yagrush" , model = 25132} +models.main[21064] = { name = "Gambanteinn" , model = 25091} +models.main[21065] = { name = "Gambanteinn" , model = 25156} +models.main[21066] = { name = "Trial Wand" , model = 25209} +models.main[21067] = { name = "Nodal Wand" , model = 25209} +models.main[21068] = { name = "Nodal Wand" , model = 25209} +models.main[21069] = { name = "Nodal Wand" , model = 25209} +models.main[21070] = { name = "Idris" , model = 25283} +models.main[21072] = { name = "Gada" , model = 25013} +models.main[21073] = { name = "Izcalli" , model = 24691} +models.main[21074] = { name = "Kupo Rod" , model = 24950} +models.main[21075] = { name = "Septoptic" , model = 24935} +models.main[21076] = { name = "Septoptic +1" , model = 24935} +models.main[21077] = { name = "Mjollnir" , model = 25129} +models.main[21078] = { name = "Yagrush" , model = 25132} +models.main[21079] = { name = "Gambanteinn" , model = 25156} +models.main[21080] = { name = "Idris" , model = 25283} +models.main[21082] = { name = "Tishtrya" , model = 25345} +models.main[21083] = { name = "Sucellus" , model = 24912} +models.main[21084] = { name = "Queller Rod" , model = 24816} +models.main[21085] = { name = "Solstice" , model = 25175} +models.main[21086] = { name = "Heartstopper" , model = 25331} +models.main[21087] = { name = "Heartstopper +1" , model = 25331} +models.main[21088] = { name = "Divinity" , model = 25327} +models.main[21089] = { name = "Rubicundity" , model = 25329} +models.main[21090] = { name = "Loxotic Mace" , model = 24679} +models.main[21091] = { name = "Loxotic Mace +1" , model = 24679} +models.main[21092] = { name = "Nibiru Cudgel" , model = 25317} +models.main[21093] = { name = "Blurred Rod" , model = 25324} +models.main[21094] = { name = "Blurred Rod +1" , model = 25324} +models.main[21095] = { name = "Heartbeater" , model = 25304} +models.main[21096] = { name = "Heartbeater +1" , model = 25304} +models.main[21097] = { name = "Leafkin Bopper" , model = 25299} +models.main[21098] = { name = "Leafkin Bopper +1" , model = 25299} +models.main[21099] = { name = "Magesmasher" , model = 24689} +models.main[21100] = { name = "Magesmasher +1" , model = 24689} +models.main[21101] = { name = "Herkuleskeule" , model = 24936} +models.main[21102] = { name = "Mafic Cudgel" , model = 24676} +models.main[21103] = { name = "Vadose Rod" , model = 24797} +models.main[21104] = { name = "Eosuchus Club" , model = 24686} +models.main[21105] = { name = "Nehushtan" , model = 25295} +models.main[21107] = { name = "Kyuka Uchiwa" , model = 25284} +models.main[21108] = { name = "Kyuka Uchiwa +1" , model = 25284} +models.main[21109] = { name = "Homestead Wand" , model = 24808} +models.main[21110] = { name = "Sindri" , model = 24688} +models.main[21111] = { name = "Bolelabunga" , model = 25203} +models.main[21112] = { name = "Gabaxorea" , model = 24802} +models.main[21113] = { name = "P. Sprig. Club" , model = 25213} +models.main[21114] = { name = "R. Sprig. Club" , model = 25211} +models.main[21115] = { name = "Aedold +2" , model = 25022} +models.main[21116] = { name = "Cagliostro's Rod" , model = 24816} +models.main[21117] = { name = "Hagoita" , model = 24973} +models.main[21118] = { name = "G. Spriggan Club" , model = 25212} +models.main[21119] = { name = "Eminent Wand" , model = 24804} +models.main[21120] = { name = "Patriarch Cane" , model = 24817} +models.main[21121] = { name = "Rose Couverte -1" , model = 24690} +models.main[21122] = { name = "Mes'yohi Rod" , model = 24796} +models.main[21123] = { name = "Cama. Wand" , model = 25187} +models.main[21124] = { name = "Dowser's Wand" , model = 24824} +models.main[21125] = { name = "Tamaxchi" , model = 25203} +models.main[21126] = { name = "Aedold +1" , model = 25022} +models.main[21127] = { name = "Forefront Wand" , model = 24808} +models.main[21128] = { name = "Mondaha Cudgel" , model = 24677} +models.main[21129] = { name = "Sharur" , model = 24936} +models.main[21130] = { name = "Sharur +1" , model = 24936} +models.main[21131] = { name = "Coalition Rod" , model = 25187} +models.main[21132] = { name = "Aedold" , model = 25022} +models.main[21133] = { name = "Sasah Wand +1" , model = 24955} +models.main[21134] = { name = "Sasah Wand" , model = 24955} +models.main[21135] = { name = "Claustrum" , model = 24918} +models.main[21136] = { name = "Claustrum" , model = 25130} +models.main[21137] = { name = "Tupsimati" , model = 25005} +models.main[21138] = { name = "Tupsimati" , model = 25146} +models.main[21139] = { name = "Laevateinn" , model = 24992} +models.main[21140] = { name = "Laevateinn" , model = 25133} +models.main[21141] = { name = "Nirvana" , model = 24993} +models.main[21142] = { name = "Nirvana" , model = 25143} +models.main[21143] = { name = "Hvergelmir" , model = 25092} +models.main[21144] = { name = "Hvergelmir" , model = 25157} +models.main[21145] = { name = "Exemplar" , model = 25346} +models.main[21147] = { name = "Khatvanga" , model = 25346} +models.main[21148] = { name = "Serenity" , model = 24865} +models.main[21149] = { name = "Espiritus" , model = 25018} +models.main[21150] = { name = "Akademos" , model = 25014} +models.main[21151] = { name = "Lathi" , model = 24881} +models.main[21152] = { name = "Reikikon" , model = 24878} +models.main[21153] = { name = "Malice Masher" , model = 25330} +models.main[21154] = { name = "Malice Masher +1" , model = 25330} +models.main[21155] = { name = "Marquetry Staff" , model = 24878} +models.main[21156] = { name = "Nibiru Staff" , model = 25318} +models.main[21157] = { name = "Blurred Staff" , model = 25038} +models.main[21158] = { name = "Blurred Staff +1" , model = 25038} +models.main[21159] = { name = "Marin Staff" , model = 24902} +models.main[21160] = { name = "Marin Staff +1" , model = 24902} +models.main[21161] = { name = "Mindmelter" , model = 25302} +models.main[21162] = { name = "Pouwhenua" , model = 24875} +models.main[21163] = { name = "Pouwhenua +1" , model = 24875} +models.main[21164] = { name = "Ababinili" , model = 24868} +models.main[21165] = { name = "Ababinili +1" , model = 24868} +models.main[21166] = { name = "Staccato Staff" , model = 24865} +models.main[21167] = { name = "Frazil Staff" , model = 24903} +models.main[21168] = { name = "Ungeri Staff" , model = 25201} +models.main[21169] = { name = "Keraunos" , model = 25296} +models.main[21170] = { name = "Nilgal Pole" , model = 25106} +models.main[21171] = { name = "Homestead Staff" , model = 24871} +models.main[21172] = { name = "Home. Scepter" , model = 25201} +models.main[21173] = { name = "Kaladanda" , model = 25180} +models.main[21174] = { name = "Gridarvor" , model = 24882} +models.main[21175] = { name = "Coeus" , model = 24881} +models.main[21176] = { name = "Ngqoqwanb" , model = 25210} +models.main[21177] = { name = "Twebuliij" , model = 24868} +models.main[21178] = { name = "Tumafyrig" , model = 24870} +models.main[21179] = { name = "Lehbrailg +2" , model = 25014} +models.main[21180] = { name = "Uffrat +2" , model = 25018} +models.main[21181] = { name = "Venabulum" , model = 25014} +models.main[21182] = { name = "Eminent Staff" , model = 24917} +models.main[21183] = { name = "Eminent Pole" , model = 24917} +models.main[21184] = { name = "Surma Staff" , model = 24937} +models.main[21185] = { name = "Boonwell Staff" , model = 24870} +models.main[21186] = { name = "Baqil Staff" , model = 25038} +models.main[21187] = { name = "Paikea -1" , model = 24878} +models.main[21188] = { name = "Cama. Staff" , model = 24869} +models.main[21189] = { name = "Cama. Pole" , model = 24871} +models.main[21191] = { name = "Voay Staff -1" , model = 25159} +models.main[21192] = { name = "Voay Staff" , model = 25159} +models.main[21193] = { name = "Voay Staff +1" , model = 25159} +models.main[21194] = { name = "Lehbrailg +1" , model = 25014} +models.main[21195] = { name = "Uffrat +1" , model = 25018} +models.main[21196] = { name = "Forefront Staff" , model = 24871} +models.main[21197] = { name = "Forefront Scepter" , model = 25201} +models.main[21198] = { name = "Soothsayer Staff" , model = 24907} +models.main[21199] = { name = "Yaskomo's Pole" , model = 24874} +models.main[21200] = { name = "Atinian Staff" , model = 24865} +models.main[21201] = { name = "Atinian Staff +1" , model = 24865} +models.main[21202] = { name = "Balsam Staff" , model = 24869} +models.main[21203] = { name = "Astralwatcher" , model = 24869} +models.main[21204] = { name = "Sortilevel Staff" , model = 24900} +models.main[21205] = { name = "Avitap Pole" , model = 24878} +models.main[21206] = { name = "Hemolele Staff" , model = 24865} +models.main[21207] = { name = "Hemolele Staff +1" , model = 24865} +models.main[21208] = { name = "Lehbrailg" , model = 25014} +models.main[21209] = { name = "Uffrat" , model = 25018} +models.main[21504] = { name = "Arasy Sainti" , model = 25082} +models.main[21505] = { name = "Arasy Sainti +1" , model = 25082} +models.main[21506] = { name = "Jolt Counter" , model = 24705} +models.main[21507] = { name = "Jolt Counter +1" , model = 24705} +models.main[21509] = { name = "Premium Mogti" , model = 25057} +models.main[21510] = { name = "Voluspa Knuckles" , model = 24705} +models.main[21511] = { name = "Hep. Baghnakhs" , model = 24717} +models.main[21512] = { name = "Hep. Baghnakhs +1" , model = 24717} +models.main[21513] = { name = "Raetic Baghnakhs" , model = 24719} +models.main[21514] = { name = "Rae. Baghnakhs +1" , model = 24719} +models.main[21515] = { name = "Tokko Knuckles" , model = 24705} +models.main[21516] = { name = "Ajja Knuckles" , model = 24711} +models.main[21517] = { name = "Eletta Knuckles" , model = 24710} +models.main[21518] = { name = "Kaja Knuckles" , model = 25055} +models.main[21519] = { name = "Karambit" , model = 25054} +models.main[21521] = { name = "Melee Fists" , model = 24697} +models.main[21522] = { name = "Hes. Fists" , model = 24697} +models.main[21523] = { name = "Sagitta" , model = 25056} +models.main[21524] = { name = "Pantin Fists" , model = 24697} +models.main[21525] = { name = "Pitre Fists" , model = 24697} +models.main[21526] = { name = "Xiucoatl" , model = 25056} +models.main[21554] = { name = "Arasy Knife" , model = 24733} +models.main[21555] = { name = "Arasy Knife +1" , model = 24733} +models.main[21556] = { name = "Beryllium Kris" , model = 24922} +models.main[21557] = { name = "Beryllium Kris +1" , model = 24922} +models.main[21558] = { name = "Rune Kris" , model = 24922} +models.main[21559] = { name = "Raetic Kris" , model = 24922} +models.main[21560] = { name = "Raetic Kris +1" , model = 24922} +models.main[21561] = { name = "Tokko Knife" , model = 24734} +models.main[21562] = { name = "Ajja Knife" , model = 24733} +models.main[21563] = { name = "Eletta Knife" , model = 25300} +models.main[21564] = { name = "Kaja Knife" , model = 25412} +models.main[21565] = { name = "Tauret" , model = 25423} +models.main[21566] = { name = "Voluspa Knife" , model = 24734} +models.main[21573] = { name = "Assassin's Knife" , model = 24733} +models.main[21574] = { name = "Plun. Knife" , model = 24733} +models.main[21575] = { name = "Gandring" , model = 25390} +models.main[21576] = { name = "Bard's Knife" , model = 24733} +models.main[21577] = { name = "Bihu Knife" , model = 24733} +models.main[21578] = { name = "Barfawc" , model = 25390} +models.main[21579] = { name = "Comm. Knife" , model = 24733} +models.main[21580] = { name = "Lanun Knife" , model = 24733} +models.main[21581] = { name = "Rostam" , model = 25390} +models.main[21582] = { name = "Etoile Knife" , model = 24733} +models.main[21583] = { name = "Horos Knife" , model = 24733} +models.main[21584] = { name = "Setan Kober" , model = 25390} +models.main[21604] = { name = "Arasy Sword" , model = 24854} +models.main[21605] = { name = "Arasy Sword +1" , model = 24854} +models.main[21606] = { name = "Enriching Sword" , model = 24826} +models.main[21607] = { name = "Enr. Sword +1" , model = 24826} +models.main[21608] = { name = "Onion Sword II" , model = 25363} +models.main[21609] = { name = "Save the Queen II" , model = 25366} +models.main[21610] = { name = "Hepatizon Rapier" , model = 24763} +models.main[21611] = { name = "Hep. Rapier +1" , model = 24763} +models.main[21612] = { name = "Raetic Blade" , model = 24830} +models.main[21613] = { name = "Raetic Blade +1" , model = 24830} +models.main[21614] = { name = "Hepatizon Sapara" , model = 24831} +models.main[21615] = { name = "Hep. Sapara +1" , model = 24831} +models.main[21617] = { name = "Tokko Sword" , model = 24843} +models.main[21618] = { name = "Ajja Sword" , model = 24848} +models.main[21619] = { name = "Eletta Sword" , model = 24864} +models.main[21620] = { name = "Kaja Sword" , model = 25413} +models.main[21621] = { name = "Naegling" , model = 25424} +models.main[21622] = { name = "Voluspa Sword" , model = 24851} +models.main[21625] = { name = "Duelist's Sword" , model = 24854} +models.main[21626] = { name = "Vitiation Sword" , model = 24854} +models.main[21627] = { name = "Crocea Mors" , model = 25395} +models.main[21628] = { name = "Valor Sword" , model = 24854} +models.main[21629] = { name = "Cabal. Sword" , model = 24854} +models.main[21630] = { name = "Moralltach" , model = 25395} +models.main[21631] = { name = "Mirage Sword" , model = 24854} +models.main[21632] = { name = "Luhlaza Sword" , model = 24854} +models.main[21633] = { name = "Zomorrodnegar" , model = 25395} +models.main[21635] = { name = "Malignance Sword" , model = 24856} +models.main[21654] = { name = "Arasy Claymore" , model = 24645} +models.main[21655] = { name = "Arasy Claymore +1" , model = 24645} +models.main[21656] = { name = "Dyrnwyn" , model = 24897} +models.main[21657] = { name = "Dyrnwyn +1" , model = 24897} +models.main[21658] = { name = "Brave Blade II" , model = 25368} +models.main[21659] = { name = "Beryllium Sword" , model = 24641} +models.main[21660] = { name = "Bery. Sword +1" , model = 24641} +models.main[21661] = { name = "Rune Algol" , model = 24962} +models.main[21662] = { name = "Raetic Algol" , model = 24962} +models.main[21663] = { name = "Raetic Algol +1" , model = 24962} +models.main[21665] = { name = "Voluspa Blade" , model = 24650} +models.main[21667] = { name = "Futhark Claymore" , model = 24640} +models.main[21668] = { name = "Peord Claymore" , model = 24640} +models.main[21669] = { name = "Morgelai" , model = 25386} +models.main[21670] = { name = "Tokko Claymore" , model = 24646} +models.main[21671] = { name = "Ajja Claymore" , model = 24645} +models.main[21672] = { name = "Eletta Claymore" , model = 25118} +models.main[21673] = { name = "Kaja Claymore" , model = 25414} +models.main[21674] = { name = "Nandaka" , model = 25425} +models.main[21682] = { name = "Lament" , model = 25384} +models.main[21683] = { name = "Ragnarok" , model = 25122} +models.main[21684] = { name = "Caladbolg" , model = 25149} +models.main[21685] = { name = "Epeolatry" , model = 25282} +models.main[21686] = { name = "Zulfiqar" , model = 25105} +models.main[21687] = { name = "Takoba" , model = 25118} +models.main[21688] = { name = "Montante" , model = 24953} +models.main[21689] = { name = "Montante +1" , model = 24953} +models.main[21690] = { name = "Ushenzi" , model = 24643} +models.main[21691] = { name = "Ushenzi +1" , model = 24643} +models.main[21693] = { name = "Irradiance Blade" , model = 25352} +models.main[21694] = { name = "Lionheart" , model = 25338} +models.main[21695] = { name = "Nullis" , model = 24650} +models.main[21696] = { name = "Nullis +1" , model = 24650} +models.main[21697] = { name = "Humility" , model = 25206} +models.main[21698] = { name = "Bidenhander" , model = 25281} +models.main[21699] = { name = "Nibiru Faussar" , model = 25310} +models.main[21700] = { name = "Blurred Claymore" , model = 25039} +models.main[21701] = { name = "Blurred Clay. +1" , model = 25039} +models.main[21702] = { name = "Kladenets" , model = 24650} +models.main[21703] = { name = "Kladenets +1" , model = 24650} +models.main[21704] = { name = "Arasy Tabar" , model = 24657} +models.main[21705] = { name = "Arasy Tabar +1" , model = 24657} +models.main[21706] = { name = "Barbarity" , model = 24667} +models.main[21707] = { name = "Barbarity +1" , model = 24667} +models.main[21708] = { name = "Beryllium Pick" , model = 24663} +models.main[21709] = { name = "Beryllium Pick +1" , model = 24663} +models.main[21710] = { name = "Raetic Axe" , model = 24661} +models.main[21711] = { name = "Raetic Axe +1" , model = 24661} +models.main[21712] = { name = "Voluspa Axe" , model = 24663} +models.main[21715] = { name = "Monster Axe" , model = 24657} +models.main[21716] = { name = "Ankusa Axe" , model = 24657} +models.main[21717] = { name = "Pangu" , model = 25387} +models.main[21718] = { name = "Tokko Axe" , model = 24658} +models.main[21719] = { name = "Ajja Axe" , model = 24657} +models.main[21720] = { name = "Eletta Axe" , model = 25167} +models.main[21721] = { name = "Kaja Axe" , model = 25426} +models.main[21722] = { name = "Dolichenus" , model = 25426} +models.main[21741] = { name = "Demonic Axe" , model = 25369} +models.main[21742] = { name = "Aern Axe" , model = 25403} +models.main[21744] = { name = "Gramk's Axe" , model = 25406} +models.main[21746] = { name = "Digirbalag" , model = 24658} +models.main[21747] = { name = "Freydis" , model = 25095} +models.main[21748] = { name = "Habilitator" , model = 24963} +models.main[21749] = { name = "Habilitator +1" , model = 24963} +models.main[21750] = { name = "Guttler" , model = 25123} +models.main[21751] = { name = "Aymur" , model = 25138} +models.main[21752] = { name = "Farsha" , model = 25150} +models.main[21753] = { name = "Tri-edge" , model = 25339} +models.main[21754] = { name = "Aganoshe" , model = 25027} +models.main[21755] = { name = "Hodadenon" , model = 25096} +models.main[21756] = { name = "Bravura" , model = 25124} +models.main[21757] = { name = "Conqueror" , model = 25131} +models.main[21758] = { name = "Ukonvasara" , model = 25151} +models.main[21761] = { name = "Za'Dha Chopper" , model = 24675} +models.main[21762] = { name = "Arasy Axe" , model = 24668} +models.main[21763] = { name = "Arasy Axe +1" , model = 24668} +models.main[21765] = { name = "Hepatizon Axe" , model = 24669} +models.main[21766] = { name = "Hepatizon Axe +1" , model = 24669} +models.main[21767] = { name = "Raetic Chopper" , model = 24911} +models.main[21768] = { name = "Raetic Chopper +1" , model = 24911} +models.main[21769] = { name = "Voluspa Chopper" , model = 24939} +models.main[21772] = { name = "War. Chopper" , model = 24668} +models.main[21773] = { name = "Agoge Chopper" , model = 24668} +models.main[21774] = { name = "Labraunda" , model = 25388} +models.main[21775] = { name = "Tokko Chopper" , model = 24674} +models.main[21776] = { name = "Ajja Chopper" , model = 24673} +models.main[21777] = { name = "Eletta Chopper" , model = 25096} +models.main[21778] = { name = "Kaja Chopper" , model = 25179} +models.main[21779] = { name = "Lycurgos" , model = 25179} +models.main[21804] = { name = "Obschine" , model = 24969} +models.main[21805] = { name = "Pixquizpan" , model = 24942} +models.main[21806] = { name = "Pixquizpan +1" , model = 24942} +models.main[21808] = { name = "Apocalypse" , model = 25126} +models.main[21809] = { name = "Liberator" , model = 25137} +models.main[21810] = { name = "Redemption" , model = 25152} +models.main[21812] = { name = "Arasy Scythe" , model = 24770} +models.main[21813] = { name = "Arasy Scythe +1" , model = 24770} +models.main[21815] = { name = "Maliya Sickle" , model = 24969} +models.main[21816] = { name = "Maliya Sickle +1" , model = 24969} +models.main[21817] = { name = "Rune Scythe" , model = 25097} +models.main[21818] = { name = "Raetic Scythe" , model = 25097} +models.main[21819] = { name = "Raetic Scythe +1" , model = 25097} +models.main[21820] = { name = "Lost Sickle" , model = 25371} +models.main[21821] = { name = "Lost Sickle +1" , model = 25371} +models.main[21822] = { name = "Voluspa Scythe" , model = 24770} +models.main[21823] = { name = "Abyss Scythe" , model = 24948} +models.main[21824] = { name = "Fallen's Scythe" , model = 24948} +models.main[21825] = { name = "Father Time" , model = 25391} +models.main[21826] = { name = "Tokko Scythe" , model = 24770} +models.main[21827] = { name = "Ajja Scythe" , model = 24770} +models.main[21828] = { name = "Eletta Scythe" , model = 24777} +models.main[21829] = { name = "Kaja Scythe" , model = 25418} +models.main[21830] = { name = "Drepanum" , model = 25418} +models.main[21854] = { name = "Reienkyo" , model = 24967} +models.main[21855] = { name = "Lembing" , model = 24790} +models.main[21857] = { name = "Gungnir" , model = 25125} +models.main[21858] = { name = "Ryunohige" , model = 25142} +models.main[21859] = { name = "Rhongomiant" , model = 25153} +models.main[21860] = { name = "Aern Spear" , model = 25404} +models.main[21862] = { name = "Mizukage Naginata" , model = 25375} +models.main[21863] = { name = "Tzee Xicu's Blade" , model = 25397} +models.main[21864] = { name = "Voluspa Lance" , model = 24785} +models.main[21865] = { name = "Arasy Lance" , model = 24946} +models.main[21866] = { name = "Arasy Lance +1" , model = 24946} +models.main[21869] = { name = "Exalted Spear" , model = 24782} +models.main[21870] = { name = "Exalted Spear +1" , model = 24782} +models.main[21871] = { name = "Raetic Halberd" , model = 24913} +models.main[21872] = { name = "Raetic Halberd +1" , model = 24913} +models.main[21876] = { name = "Wyrm Lance" , model = 24946} +models.main[21877] = { name = "Pteroslaver Lance" , model = 24946} +models.main[21878] = { name = "Aram" , model = 25393} +models.main[21879] = { name = "Tokko Lance" , model = 24925} +models.main[21880] = { name = "Ajja Lance" , model = 24967} +models.main[21881] = { name = "Eletta Lance" , model = 25029} +models.main[21882] = { name = "Kaja Lance" , model = 25417} +models.main[21883] = { name = "Shining One" , model = 25417} +models.main[21904] = { name = "Kanaria" , model = 24947} +models.main[21905] = { name = "Taka" , model = 25181} +models.main[21906] = { name = "Kikoku" , model = 25127} +models.main[21907] = { name = "Nagi" , model = 25141} +models.main[21908] = { name = "Kannagi" , model = 25154} +models.main[21909] = { name = "Yoshikiri" , model = 24976} +models.main[21910] = { name = "Yoshikiri +1" , model = 24976} +models.main[21912] = { name = "Voluspa Katana" , model = 24889} +models.main[21915] = { name = "Koga Shin." , model = 24889} +models.main[21916] = { name = "Mochi. Shin." , model = 24889} +models.main[21917] = { name = "Fudo Masamune" , model = 25392} +models.main[21918] = { name = "Tokko Katana" , model = 24889} +models.main[21919] = { name = "Ajja Katana" , model = 24885} +models.main[21920] = { name = "Eletta Katana" , model = 24976} +models.main[21921] = { name = "Kaja Katana" , model = 25419} +models.main[21922] = { name = "Gokotai" , model = 25419} +models.main[21923] = { name = "Debahocho" , model = 24888} +models.main[21924] = { name = "Debahocho +1" , model = 24888} +models.main[21954] = { name = "Amanomurakumo" , model = 25128} +models.main[21955] = { name = "Kogarasumaru" , model = 25140} +models.main[21956] = { name = "Masamune" , model = 25155} +models.main[21960] = { name = "Ashijiro no Tachi" , model = 24730} +models.main[21961] = { name = "Ashi. no Tachi +1" , model = 24730} +models.main[21963] = { name = "Beryllium Tachi" , model = 24730} +models.main[21964] = { name = "Beryllium Tachi +1" , model = 24730} +models.main[21965] = { name = "Zanmato" , model = 25364} +models.main[21966] = { name = "Zanmato +1" , model = 25364} +models.main[21967] = { name = "Melon Slicer" , model = 24944} +models.main[21968] = { name = "Saotome-no-Tachi" , model = 24724} +models.main[21969] = { name = "Sakonji-no-Tachi" , model = 24724} +models.main[21970] = { name = "Fusenaikyo" , model = 25389} +models.main[21971] = { name = "Tokko Tachi" , model = 24730} +models.main[21972] = { name = "Ajja Tachi" , model = 24732} +models.main[21973] = { name = "Eletta Tachi" , model = 24731} +models.main[21974] = { name = "Kaja Tachi" , model = 25420} +models.main[21975] = { name = "Hachimonji" , model = 25420} +models.main[21976] = { name = "Voluspa Tachi" , model = 24730} +models.main[22004] = { name = "Soulflayer's Wand" , model = 25399} +models.main[22006] = { name = "Voluspa Hammer" , model = 24688} +models.main[22015] = { name = "Arasy Rod" , model = 24794} +models.main[22016] = { name = "Arasy Rod +1" , model = 24794} +models.main[22017] = { name = "Seika Uchiwa" , model = 25374} +models.main[22018] = { name = "Seika Uchiwa +1" , model = 25374} +models.main[22019] = { name = "Jingly Rod" , model = 25377} +models.main[22020] = { name = "Jingly Rod +1" , model = 25377} +models.main[22021] = { name = "Ames" , model = 24805} +models.main[22022] = { name = "Ames +1" , model = 24805} +models.main[22023] = { name = "Beryllium Mace" , model = 24679} +models.main[22024] = { name = "Beryllium Mace +1" , model = 24679} +models.main[22025] = { name = "Raetic Rod" , model = 24912} +models.main[22026] = { name = "Raetic Rod +1" , model = 24912} +models.main[22027] = { name = "Tokko Rod" , model = 24795} +models.main[22028] = { name = "Ajja Rod" , model = 24794} +models.main[22029] = { name = "Eletta Rod" , model = 24816} +models.main[22030] = { name = "Kaja Rod" , model = 25421} +models.main[22031] = { name = "Maxentius" , model = 25421} +models.main[22033] = { name = "Cleric's Wand" , model = 24794} +models.main[22034] = { name = "Piety Wand" , model = 24794} +models.main[22035] = { name = "Asclepius" , model = 25394} +models.main[22036] = { name = "Bagua Wand" , model = 24794} +models.main[22037] = { name = "Sifang Wand" , model = 24794} +models.main[22038] = { name = "Bhima" , model = 25394} +models.main[22039] = { name = "Floral Hagoita" , model = 25411} +models.main[22054] = { name = "Grioavolr" , model = 25177} +models.main[22055] = { name = "Oranyan" , model = 24882} +models.main[22056] = { name = "Gozuki Mezuki" , model = 24937} +models.main[22057] = { name = "Contemplator" , model = 25018} +models.main[22058] = { name = "Contemplator +1" , model = 25018} +models.main[22060] = { name = "Claustrum" , model = 25130} +models.main[22061] = { name = "Tupsimati" , model = 25146} +models.main[22062] = { name = "Laevateinn" , model = 25133} +models.main[22063] = { name = "Nirvana" , model = 25143} +models.main[22064] = { name = "Hvergelmir" , model = 25157} +models.main[22065] = { name = "Aern Staff" , model = 25405} +models.main[22069] = { name = "Hapy Staff" , model = 25382} +models.main[22072] = { name = "Lamia Staff" , model = 25408} +models.main[22074] = { name = "Arasy Staff" , model = 24868} +models.main[22075] = { name = "Arasy Staff +1" , model = 24868} +models.main[22076] = { name = "Was" , model = 24882} +models.main[22077] = { name = "Was +1" , model = 24882} +models.main[22078] = { name = "Exalted Staff" , model = 24937} +models.main[22079] = { name = "Exalted Staff +1" , model = 24937} +models.main[22080] = { name = "Raetic Staff" , model = 24881} +models.main[22081] = { name = "Raetic Staff +1" , model = 24881} +models.main[22082] = { name = "Tokko Staff" , model = 24867} +models.main[22083] = { name = "Ajja Staff" , model = 24869} +models.main[22084] = { name = "Eletta Staff" , model = 24881} +models.main[22085] = { name = "Kaja Staff" , model = 25422} +models.main[22086] = { name = "Xoanon" , model = 25422} +models.main[22088] = { name = "Voluspa Pole" , model = 24874} +models.main[22091] = { name = "Sorcerer's Staff" , model = 24902} +models.main[22092] = { name = "Archmage's Staff" , model = 24902} +models.main[22093] = { name = "Kaumodaki" , model = 25396} +models.main[22094] = { name = "Summoner's Staff" , model = 24902} +models.main[22095] = { name = "Glyphic Staff" , model = 24902} +models.main[22096] = { name = "Draumstafir" , model = 25396} +models.main[22097] = { name = "Argute Staff" , model = 24902} +models.main[22098] = { name = "Pedagogy Staff" , model = 24902} +models.main[22099] = { name = "Musa" , model = 25396} \ No newline at end of file diff --git a/addons/DressUp/ranged.lua b/addons/DressUp/ranged.lua new file mode 100644 index 0000000000..a0072daa0e --- /dev/null +++ b/addons/DressUp/ranged.lua @@ -0,0 +1,656 @@ +-- Copyright © 2013, 2022 Cairthenn +-- 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 DressUp 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 Cairthenn 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. + + +models.ranged = {} + +models.ranged["None"] = { name = "empty" , enl = "empty", model = 32768 } + +models.ranged[17011] = { name="Ebisu Fishing Rod" , model = 32768} +models.ranged[17012] = { name="Judge's Rod" , model = 32768} +models.ranged[17013] = { name="Goldfish Basket" , model = 32768} +models.ranged[17014] = { name="Hume Fishing Rod" , model = 32768} +models.ranged[17015] = { name="Halcyon Rod" , model = 32768} +models.ranged[17152] = { name="Shortbow" , model = 32768} +models.ranged[17153] = { name="Self Bow" , model = 32768} +models.ranged[17154] = { name="Wrapped Bow" , model = 32768} +models.ranged[17155] = { name="Composite Bow" , model = 32768} +models.ranged[17156] = { name="Kaman" , model = 32768} +models.ranged[17157] = { name="Rapid Bow" , model = 32768} +models.ranged[17158] = { name="Rune Bow" , model = 32768} +models.ranged[17159] = { name="Freesword's Bow" , model = 32768} +models.ranged[17160] = { name="Longbow" , model = 32768} +models.ranged[17161] = { name="Power Bow" , model = 32768} +models.ranged[17162] = { name="Great Bow" , model = 32768} +models.ranged[17163] = { name="Battle Bow" , model = 32768} +models.ranged[17164] = { name="War Bow" , model = 32768} +models.ranged[17165] = { name="Arco de Velocidad" , model = 32768} +models.ranged[17166] = { name="Lamian Kaman" , model = 32768} +models.ranged[17167] = { name="Ryl.Arc. Longbow" , model = 32768} +models.ranged[17170] = { name="Speed Bow" , model = 32768} +models.ranged[17172] = { name="Wrapped Bow +1" , model = 32768} +models.ranged[17173] = { name="War Bow +1" , model = 32768} +models.ranged[17174] = { name="Judge's Bow" , model = 32768} +models.ranged[17175] = { name="Shortbow +1" , model = 32768} +models.ranged[17176] = { name="Self Bow +1" , model = 32768} +models.ranged[17177] = { name="Longbow +1" , model = 32768} +models.ranged[17178] = { name="Power Bow +1" , model = 32768} +models.ranged[17179] = { name="Composite Bow +1" , model = 32768} +models.ranged[17180] = { name="Great Bow +1" , model = 32768} +models.ranged[17181] = { name="Battle Bow +1" , model = 32768} +models.ranged[17182] = { name="Kaman +1" , model = 32768} +models.ranged[17183] = { name="Hunter's Longbow" , model = 32768} +models.ranged[17184] = { name="Assassin's Bow" , model = 32768} +models.ranged[17185] = { name="Siege Bow" , model = 32768} +models.ranged[17186] = { name="Sagittarius' Bow" , model = 32768} +models.ranged[17187] = { name="Eurytos' Bow" , model = 32768} +models.ranged[17188] = { name="Sniping Bow" , model = 32768} +models.ranged[17189] = { name="Rapid Bow +1" , model = 32768} +models.ranged[17190] = { name="Sarnga" , model = 32768} +models.ranged[17191] = { name="Pharaoh's Bow" , model = 32768} +models.ranged[17192] = { name="Ifrit's Bow" , model = 32768} +models.ranged[17193] = { name="Shadow Bow" , model = 32768} +models.ranged[17194] = { name="Shadow Bow +1" , model = 32768} +models.ranged[17195] = { name="Windurstian Bow" , model = 32768} +models.ranged[17196] = { name="Federation Bow" , model = 32768} +models.ranged[17197] = { name="San d'Orian Bow" , model = 32768} +models.ranged[17198] = { name="Kingdom Bow" , model = 32768} +models.ranged[17199] = { name="Loxley Bow" , model = 32768} +models.ranged[17200] = { name="Rosenbogen" , model = 32768} +models.ranged[17201] = { name="Rosenbogen +1" , model = 32768} +models.ranged[17202] = { name="Platoon Bow" , model = 32768} +models.ranged[17203] = { name="Shikar Bow" , model = 32768} +models.ranged[17204] = { name="Mighty Bow" , model = 32768} +models.ranged[17205] = { name="Gendawa" , model = 32768} +models.ranged[17206] = { name="Gendawa +1" , model = 32768} +models.ranged[17207] = { name="Expunger" , model = 32768} +models.ranged[17208] = { name="Hamayumi" , model = 32768} +models.ranged[17209] = { name="Martial Bow" , model = 32768} +models.ranged[17210] = { name="Martial Gun" , model = 32768} +models.ranged[17211] = { name="Almogavar Bow" , model = 32768} +models.ranged[17212] = { name="Selene's Bow" , model = 32768} +models.ranged[17213] = { name="Staurobow" , model = 32768} +models.ranged[17214] = { name="Staurobow +1" , model = 32768} +models.ranged[17215] = { name="Thug's Zamburak" , model = 32768} +models.ranged[17216] = { name="Light Crossbow" , model = 32768} +models.ranged[17217] = { name="Crossbow" , model = 32768} +models.ranged[17218] = { name="Zamburak" , model = 32768} +models.ranged[17219] = { name="Arbalest" , model = 32768} +models.ranged[17220] = { name="Heavy Crossbow" , model = 32768} +models.ranged[17221] = { name="Rpt. Crossbow" , model = 32768} +models.ranged[17222] = { name="Hexagun" , model = 32768} +models.ranged[17223] = { name="Lgn. Crossbow" , model = 32768} +models.ranged[17224] = { name="Killer Crossbow" , model = 32768} +models.ranged[17225] = { name="Crossbow +1" , model = 32768} +models.ranged[17226] = { name="Arbalest +1" , model = 32768} +models.ranged[17227] = { name="Heavy Crossbow+1" , model = 32768} +models.ranged[17228] = { name="Light Crossbow +1" , model = 32768} +models.ranged[17229] = { name="Zamburak +1" , model = 32768} +models.ranged[17230] = { name="Power Crossbow" , model = 32768} +models.ranged[17231] = { name="Tell's Crossbow" , model = 32768} +models.ranged[17232] = { name="Lion Crossbow" , model = 32768} +models.ranged[17233] = { name="Machine Crossbow" , model = 32768} +models.ranged[17234] = { name="Flagel. Crossbow" , model = 32768} +models.ranged[17235] = { name="Armbrust" , model = 32768} +models.ranged[17236] = { name="Leo Crossbow" , model = 32768} +models.ranged[17237] = { name="Leo Crossbow +1" , model = 32768} +models.ranged[17238] = { name="Bas. Crossbow" , model = 32768} +models.ranged[17239] = { name="Rep. Crossbow" , model = 32768} +models.ranged[17240] = { name="Lightning Bow" , model = 32768} +models.ranged[17241] = { name="Lightning Bow +1" , model = 32768} +models.ranged[17242] = { name="Velocity Bow" , model = 32768} +models.ranged[17243] = { name="Velocity Bow +1" , model = 32768} +models.ranged[17244] = { name="Othinus' Bow" , model = 32768} +models.ranged[17245] = { name="Grosveneur's Bow" , model = 32768} +models.ranged[17246] = { name="Ziska's Crossbow" , model = 32768} +models.ranged[17247] = { name="Rikonodo" , model = 32768} +models.ranged[17248] = { name="Arquebus" , model = 32768} +models.ranged[17249] = { name="Magoichi's Gun" , model = 32768} +models.ranged[17250] = { name="Matchlock Gun" , model = 32768} +models.ranged[17251] = { name="Hellfire" , model = 32768} +models.ranged[17252] = { name="Culverin" , model = 32768} +models.ranged[17253] = { name="Musketeer Gun" , model = 32768} +models.ranged[17254] = { name="Arquebus +1" , model = 32768} +models.ranged[17255] = { name="Hakenbuechse" , model = 32768} +models.ranged[17256] = { name="Serpentine Gun" , model = 32768} +models.ranged[17257] = { name="Bandit's Gun" , model = 32768} +models.ranged[17258] = { name="Bandit's Gun +1" , model = 32768} +models.ranged[17259] = { name="Pirate's Gun" , model = 32768} +models.ranged[17260] = { name="Pirate's Gun +1" , model = 32768} +models.ranged[17261] = { name="Matchlock Gun +1" , model = 32768} +models.ranged[17262] = { name="Corsair's Gun" , model = 32768} +models.ranged[17263] = { name="Corsair's Gun +1" , model = 32768} +models.ranged[17264] = { name="Hellfire +1" , model = 32768} +models.ranged[17265] = { name="Tanegashima" , model = 32768} +models.ranged[17266] = { name="Tanegashima +1" , model = 32768} +models.ranged[17267] = { name="Negoroshiki" , model = 32768} +models.ranged[17268] = { name="Negoroshiki +1" , model = 32768} +models.ranged[17269] = { name="Musketeer Gun +1" , model = 32768} +models.ranged[17270] = { name="Musketeer Gun +2" , model = 32768} +models.ranged[17271] = { name="Platoon Gun" , model = 32768} +models.ranged[17272] = { name="Military Gun" , model = 32768} +models.ranged[17273] = { name="Phineus' Gun" , model = 32768} +models.ranged[17274] = { name="Deluxe Carbine" , model = 32768} +models.ranged[17275] = { name="Coffinmaker" , model = 32768} +models.ranged[17279] = { name="Moonring Blade +1" , model = 32768} +models.ranged[17280] = { name="Boomerang" , model = 32768} +models.ranged[17281] = { name="Wingedge" , model = 32768} +models.ranged[17282] = { name="Cmb.Cst. B'merang" , model = 32768} +models.ranged[17283] = { name="Jr.Msk. Chakram" , model = 32768} +models.ranged[17284] = { name="Chakram" , model = 32768} +models.ranged[17285] = { name="Moonring Blade" , model = 32768} +models.ranged[17286] = { name="Rising Sun" , model = 32768} +models.ranged[17287] = { name="Boomerang +1" , model = 32768} +models.ranged[17288] = { name="Wingedge +1" , model = 32768} +models.ranged[17289] = { name="Chakram +1" , model = 32768} +models.ranged[17290] = { name="Coarse Boomerang" , model = 32768} +models.ranged[17291] = { name="Flame Boomerang" , model = 32768} +models.ranged[17292] = { name="Long Boomerang" , model = 32768} +models.ranged[17293] = { name="Yagudo Freezer" , model = 32768} +models.ranged[17294] = { name="Comet Tail" , model = 32768} +models.ranged[17295] = { name="Rising Sun +1" , model = 32768} +models.ranged[17344] = { name="Cornette" , model = 32768} +models.ranged[17345] = { name="Flute" , model = 32768} +models.ranged[17346] = { name="Siren Flute" , model = 32768} +models.ranged[17347] = { name="Piccolo" , model = 32768} +models.ranged[17348] = { name="Traversiere" , model = 32768} +models.ranged[17349] = { name="Faerie Piccolo" , model = 32768} +models.ranged[17350] = { name="Angel's Flute" , model = 32768} +models.ranged[17351] = { name="Gemshorn" , model = 32768} +models.ranged[17352] = { name="Horn" , model = 32768} +models.ranged[17353] = { name="Maple Harp" , model = 32768} +models.ranged[17354] = { name="Harp" , model = 32768} +models.ranged[17355] = { name="Rose Harp" , model = 32768} +models.ranged[17356] = { name="Lamia Harp" , model = 32768} +models.ranged[17357] = { name="Ebony Harp" , model = 32768} +models.ranged[17358] = { name="Oneiros Harp" , model = 32768} +models.ranged[17359] = { name="Mythic Harp" , model = 32768} +models.ranged[17360] = { name="Langeleik" , model = 32768} +models.ranged[17361] = { name="Crumhorn" , model = 32768} +models.ranged[17362] = { name="Shofar" , model = 32768} +models.ranged[17363] = { name="Mass Chalemie" , model = 32768} +models.ranged[17364] = { name="Cythara Anglica" , model = 32768} +models.ranged[17365] = { name="Frenzy Fife" , model = 32768} +models.ranged[17366] = { name="Mary's Horn" , model = 32768} +models.ranged[17367] = { name="Ryl.Spr. Horn" , model = 32768} +models.ranged[17368] = { name="Piccolo +1" , model = 32768} +models.ranged[17369] = { name="Cornette +1" , model = 32768} +models.ranged[17370] = { name="Gemshorn +1" , model = 32768} +models.ranged[17371] = { name="Horn +1" , model = 32768} +models.ranged[17372] = { name="Flute +1" , model = 32768} +models.ranged[17373] = { name="Maple Harp +1" , model = 32768} +models.ranged[17374] = { name="Harp +1" , model = 32768} +models.ranged[17375] = { name="Traversiere +1" , model = 32768} +models.ranged[17376] = { name="Rose Harp +1" , model = 32768} +models.ranged[17377] = { name="Crumhorn +1" , model = 32768} +models.ranged[17378] = { name="Angel's Flute +1" , model = 32768} +models.ranged[17379] = { name="Hamelin Flute" , model = 32768} +models.ranged[17380] = { name="Mithran Fish. Rod" , model = 32768} +models.ranged[17381] = { name="Comp. Fishing Rod" , model = 32768} +models.ranged[17382] = { name="S.H. Fishing Rod" , model = 32768} +models.ranged[17383] = { name="Clothespole" , model = 32768} +models.ranged[17384] = { name="Carbon Fish. Rod" , model = 32768} +models.ranged[17385] = { name="Glass Fiber F. Rod" , model = 32768} +models.ranged[17386] = { name="Lu Shang's F. Rod" , model = 32768} +models.ranged[17387] = { name="Tarutaru F. Rod" , model = 32768} +models.ranged[17388] = { name="Fastwater F. Rod" , model = 32768} +models.ranged[17389] = { name="Bamboo Fish. Rod" , model = 32768} +models.ranged[17390] = { name="Yew Fishing Rod" , model = 32768} +models.ranged[17391] = { name="Willow Fish. Rod" , model = 32768} +models.ranged[17832] = { name="Shofar +1" , model = 32768} +models.ranged[17833] = { name="Ebony Harp +1" , model = 32768} +models.ranged[17834] = { name="Mythic Harp +1" , model = 32768} +models.ranged[17835] = { name="San d'Orian Horn" , model = 32768} +models.ranged[17836] = { name="Kingdom Horn" , model = 32768} +models.ranged[17837] = { name="Cyt. Anglica +1" , model = 32768} +models.ranged[17838] = { name="Harlequin's Horn" , model = 32768} +models.ranged[17839] = { name="Military Harp" , model = 32768} +models.ranged[17840] = { name="Angel Lyre" , model = 32768} +models.ranged[17841] = { name="Nursemaid's Harp" , model = 32768} +models.ranged[17842] = { name="Sorrowful Harp" , model = 32768} +models.ranged[17843] = { name="Oliphant" , model = 32768} +models.ranged[17844] = { name="Flute +2" , model = 32768} +models.ranged[17845] = { name="Traversiere +2" , model = 32768} +models.ranged[17846] = { name="Cornette +2" , model = 32768} +models.ranged[17847] = { name="Crumhorn +2" , model = 32768} +models.ranged[17848] = { name="Ebony Harp +2" , model = 32768} +models.ranged[17849] = { name="Hellish Bugle" , model = 32768} +models.ranged[17850] = { name="Hellish Bugle +1" , model = 32768} +models.ranged[17851] = { name="Storm Fife" , model = 32768} +models.ranged[17852] = { name="Requiem Flute" , model = 32768} +models.ranged[17853] = { name="Iron Ram Horn" , model = 32768} +models.ranged[17854] = { name="Cradle Horn" , model = 32768} +models.ranged[17855] = { name="Ney" , model = 32768} +models.ranged[17856] = { name="Syrinx" , model = 32768} +models.ranged[17857] = { name="Animator +1" , model = 32768} +models.ranged[17858] = { name="Turbo Animator" , model = 32768} +models.ranged[17859] = { name="Animator" , model = 32768} +models.ranged[17923] = { name="Deluxe Animator" , model = 32768} +models.ranged[18132] = { name="Cmb.Cst.Bmrng +1" , model = 32768} +models.ranged[18133] = { name="Cmb.Cst.Bmrng +2" , model = 32768} +models.ranged[18134] = { name="Jr.Msk.Chakram +1" , model = 32768} +models.ranged[18135] = { name="Jr.Msk.Chakram +2" , model = 32768} +models.ranged[18141] = { name="Ungur Boomerang" , model = 32768} +models.ranged[18142] = { name="Shigeto Bow" , model = 32768} +models.ranged[18143] = { name="Shigeto Bow +1" , model = 32768} +models.ranged[18144] = { name="Bow of Trials" , model = 32768} +models.ranged[18145] = { name="Mst.Cst. Bow" , model = 32768} +models.ranged[18146] = { name="Gun of Trials" , model = 32768} +models.ranged[18147] = { name="Culverin +1" , model = 32768} +models.ranged[18170] = { name="Platoon Edge" , model = 32768} +models.ranged[18171] = { name="Platoon Disc" , model = 32768} +models.ranged[18172] = { name="Light Boomerang" , model = 32768} +models.ranged[18231] = { name="Death Chakram" , model = 32768} +models.ranged[18245] = { name="Aureole" , model = 32768} +models.ranged[18246] = { name="Rogetsurin" , model = 32768} +models.ranged[18332] = { name="Relic Gun" , model = 32768} +models.ranged[18333] = { name="Marksman Gun" , model = 32768} +models.ranged[18334] = { name="Dynamis Gun" , model = 32768} +models.ranged[18335] = { name="Ferdinand" , model = 32768} +models.ranged[18336] = { name="Annihilator" , model = 32768} +models.ranged[18337] = { name="Annihilator" , model = 32768} +models.ranged[18338] = { name="Relic Horn" , model = 32768} +models.ranged[18339] = { name="Pyrrhic Horn" , model = 32768} +models.ranged[18340] = { name="Dynamis horn" , model = 32768} +models.ranged[18341] = { name="Millennium Horn" , model = 32768} +models.ranged[18342] = { name="Gjallarhorn" , model = 32768} +models.ranged[18343] = { name="Pan's Horn" , model = 32768} +models.ranged[18344] = { name="Relic Bow" , model = 32768} +models.ranged[18345] = { name="Wolver Bow" , model = 32768} +models.ranged[18346] = { name="Dynamis Bow" , model = 32768} +models.ranged[18347] = { name="Futatokoroto" , model = 32768} +models.ranged[18348] = { name="Yoichinoyumi" , model = 32768} +models.ranged[18349] = { name="Yoichinoyumi" , model = 32768} +models.ranged[18571] = { name="Daurdabla" , model = 32768} +models.ranged[18572] = { name="Gjallarhorn" , model = 32768} +models.ranged[18573] = { name="Pyf Harp" , model = 32768} +models.ranged[18574] = { name="Daurdabla" , model = 32768} +models.ranged[18575] = { name="Daurdabla" , model = 32768} +models.ranged[18576] = { name="Daurdabla" , model = 32768} +models.ranged[18577] = { name="Gjallarhorn" , model = 32768} +models.ranged[18578] = { name="Gjallarhorn" , model = 32768} +models.ranged[18579] = { name="Gjallarhorn" , model = 32768} +models.ranged[18580] = { name="Gjallarhorn" , model = 32768} +models.ranged[18649] = { name="Annihilator" , model = 32768} +models.ranged[18650] = { name="Yoichinoyumi" , model = 32768} +models.ranged[18663] = { name="Annihilator" , model = 32768} +models.ranged[18664] = { name="Yoichinoyumi" , model = 32768} +models.ranged[18677] = { name="Annihilator" , model = 32768} +models.ranged[18678] = { name="Yoichinoyumi" , model = 32768} +models.ranged[18679] = { name="Soulgauger SGR-1" , model = 32768} +models.ranged[18682] = { name="Lamian Kaman +1" , model = 32768} +models.ranged[18683] = { name="Imperial Bow" , model = 32768} +models.ranged[18684] = { name="Storm Zamburak" , model = 32768} +models.ranged[18685] = { name="Imperial Kaman" , model = 32768} +models.ranged[18686] = { name="Imperial Gun" , model = 32768} +models.ranged[18687] = { name="Hexagun +1" , model = 32768} +models.ranged[18688] = { name="Lamian Kaman -1" , model = 32768} +models.ranged[18692] = { name="Mamoolbane" , model = 32768} +models.ranged[18693] = { name="Lamiabane" , model = 32768} +models.ranged[18694] = { name="Trollbane" , model = 32768} +models.ranged[18695] = { name="Cerberus Bow" , model = 32768} +models.ranged[18701] = { name="Cerberus Bow +1" , model = 32768} +models.ranged[18702] = { name="Trump Gun" , model = 32768} +models.ranged[18703] = { name="Shark Gun" , model = 32768} +models.ranged[18704] = { name="Darksteel Hexagun" , model = 32768} +models.ranged[18705] = { name="Dst. Hexagun +1" , model = 32768} +models.ranged[18706] = { name="Peacemaker" , model = 32768} +models.ranged[18708] = { name="Snakeeye" , model = 32768} +models.ranged[18709] = { name="Snakeeye +1" , model = 32768} +models.ranged[18710] = { name="Seadog Gun" , model = 32768} +models.ranged[18711] = { name="Seadog Gun +1" , model = 32768} +models.ranged[18714] = { name="Vali's Bow" , model = 32768} +models.ranged[18715] = { name="Mars's Hexagun" , model = 32768} +models.ranged[18716] = { name="Mars's Hexagun +1" , model = 32768} +models.ranged[18717] = { name="Perdu Bow" , model = 32768} +models.ranged[18718] = { name="Perdu Crossbow" , model = 32768} +models.ranged[18719] = { name="Killer Bow" , model = 32768} +models.ranged[18720] = { name="Quicksilver" , model = 32768} +models.ranged[18721] = { name="Soultrapper" , model = 32768} +models.ranged[18724] = { name="Soultrapper 2000" , model = 32768} +models.ranged[18727] = { name="Fourth Gun" , model = 32768} +models.ranged[18728] = { name="Cobra Bow" , model = 32768} +models.ranged[18736] = { name="Fay Gendawa" , model = 32768} +models.ranged[18737] = { name="Fane Hexagun" , model = 32768} +models.ranged[18831] = { name="Crooner's Cithara" , model = 32768} +models.ranged[18832] = { name="Apollo's Flute" , model = 32768} +models.ranged[18833] = { name="Cantabank's Horn" , model = 32768} +models.ranged[18834] = { name="Vihuela" , model = 32768} +models.ranged[18839] = { name="Daurdabla" , model = 32768} +models.ranged[18840] = { name="Gjallarhorn" , model = 32768} +models.ranged[18933] = { name="Harrier" , model = 32768} +models.ranged[18934] = { name="Condor" , model = 32768} +models.ranged[18935] = { name="Bateleur" , model = 32768} +models.ranged[18936] = { name="Sparrowhawk" , model = 32768} +models.ranged[18937] = { name="Bedlam" , model = 32768} +models.ranged[18938] = { name="Spitfire" , model = 32768} +models.ranged[18939] = { name="Mayhem" , model = 32768} +models.ranged[18940] = { name="Anarchy" , model = 32768} +models.ranged[18981] = { name="Gastraphetes" , model = 32768} +models.ranged[18987] = { name="Death Penalty" , model = 32768} +models.ranged[19001] = { name="Gastraphetes" , model = 32768} +models.ranged[19007] = { name="Death Penalty" , model = 32768} +models.ranged[19070] = { name="Gastraphetes" , model = 32768} +models.ranged[19076] = { name="Death Penalty" , model = 32768} +models.ranged[19090] = { name="Gastraphetes" , model = 32768} +models.ranged[19096] = { name="Death Penalty" , model = 32768} +models.ranged[19187] = { name="Murti Bow" , model = 32768} +models.ranged[19188] = { name="Killer Shortbow" , model = 32768} +models.ranged[19189] = { name="Virtus Crossbow" , model = 32768} +models.ranged[19190] = { name="Fluid Crossbow" , model = 32768} +models.ranged[19191] = { name="Exequy Gun" , model = 32768} +models.ranged[19192] = { name="Awilda's Gun" , model = 32768} +models.ranged[19203] = { name="War Hoop" , model = 32768} +models.ranged[19204] = { name="Fiendtrapper" , model = 32768} +models.ranged[19206] = { name="Silver Cassandra" , model = 32768} +models.ranged[19207] = { name="Great Cassandra" , model = 32768} +models.ranged[19208] = { name="Grand Crossbow" , model = 32768} +models.ranged[19209] = { name="Molybdosis" , model = 32768} +models.ranged[19215] = { name="Amanokakoyumi" , model = 32768} +models.ranged[19216] = { name="Failnaught" , model = 32768} +models.ranged[19217] = { name="Basilisk" , model = 32768} +models.ranged[19218] = { name="Murderer" , model = 32768} +models.ranged[19221] = { name="Firefly" , model = 32768} +models.ranged[19222] = { name="Wurger" , model = 32768} +models.ranged[19224] = { name="Musketoon" , model = 32768} +models.ranged[19225] = { name="Musketoon +1" , model = 32768} +models.ranged[19226] = { name="Blunderbuss" , model = 32768} +models.ranged[19227] = { name="Blunderbuss +1" , model = 32768} +models.ranged[19230] = { name="Nous Arbalest" , model = 32768} +models.ranged[19231] = { name="Tracker's Bow" , model = 32768} +models.ranged[19232] = { name="Octant" , model = 32768} +models.ranged[19233] = { name="Lyft Crossbow" , model = 32768} +models.ranged[19234] = { name="Lyft Hexagun" , model = 32768} +models.ranged[19235] = { name="Veuglaire" , model = 32768} +models.ranged[19241] = { name="Tracker's Bow +1" , model = 32768} +models.ranged[19260] = { name="Raider's Bmrng." , model = 32768} +models.ranged[19261] = { name="Jinx Discus" , model = 32768} +models.ranged[19263] = { name="Amazon Bow" , model = 32768} +models.ranged[19264] = { name="Amazon Bow +1" , model = 32768} +models.ranged[19265] = { name="Darkwing" , model = 32768} +models.ranged[19266] = { name="Darkwing +1" , model = 32768} +models.ranged[19267] = { name="Ribauldequin" , model = 32768} +models.ranged[19268] = { name="Ribauldequin +1" , model = 32768} +models.ranged[19319] = { name="MMM Fishing Rod" , model = 32768} +models.ranged[19320] = { name="Lu Sh. F. Rod +1" , model = 32768} +models.ranged[19321] = { name="Ebisu F. Rod +1" , model = 32768} +models.ranged[19387] = { name="Sparrow" , model = 32768} +models.ranged[19388] = { name="Kestrel" , model = 32768} +models.ranged[19389] = { name="Astrild" , model = 32768} +models.ranged[19390] = { name="Goshawk" , model = 32768} +models.ranged[19391] = { name="Gyrfalcon" , model = 32768} +models.ranged[19392] = { name="Thunderstick" , model = 32768} +models.ranged[19393] = { name="Blue Steel" , model = 32768} +models.ranged[19394] = { name="Magnatus" , model = 32768} +models.ranged[19395] = { name="Dragonmaw" , model = 32768} +models.ranged[19396] = { name="Huracan" , model = 32768} +models.ranged[19409] = { name="Gandiva" , model = 32768} +models.ranged[19410] = { name="Armageddon" , model = 32768} +models.ranged[19468] = { name="Gandiva" , model = 32768} +models.ranged[19469] = { name="Armageddon" , model = 32768} +models.ranged[19526] = { name="Harrier +1" , model = 32768} +models.ranged[19527] = { name="Condor +1" , model = 32768} +models.ranged[19528] = { name="Bateleur +1" , model = 32768} +models.ranged[19529] = { name="Sparrowhawk +1" , model = 32768} +models.ranged[19530] = { name="Bedlam +1" , model = 32768} +models.ranged[19531] = { name="Spitfire +1" , model = 32768} +models.ranged[19532] = { name="Mayhem +1" , model = 32768} +models.ranged[19533] = { name="Anarchy +1" , model = 32768} +models.ranged[19546] = { name="Gandiva" , model = 32768} +models.ranged[19547] = { name="Armageddon" , model = 32768} +models.ranged[19604] = { name="Harrier +2" , model = 32768} +models.ranged[19605] = { name="Condor +2" , model = 32768} +models.ranged[19606] = { name="Bateleur +2" , model = 32768} +models.ranged[19607] = { name="Sparrowhawk +2" , model = 32768} +models.ranged[19608] = { name="Bedlam +2" , model = 32768} +models.ranged[19609] = { name="Spitfire +2" , model = 32768} +models.ranged[19610] = { name="Mayhem +2" , model = 32768} +models.ranged[19611] = { name="Anarchy +2" , model = 32768} +models.ranged[19622] = { name="Gastraphetes" , model = 32768} +models.ranged[19628] = { name="Death Penalty" , model = 32768} +models.ranged[19644] = { name="Gandiva" , model = 32768} +models.ranged[19645] = { name="Armageddon" , model = 32768} +models.ranged[19702] = { name="Harrier +3" , model = 32768} +models.ranged[19703] = { name="Condor +3" , model = 32768} +models.ranged[19704] = { name="Bateleur +3" , model = 32768} +models.ranged[19705] = { name="Sparrowhawk +3" , model = 32768} +models.ranged[19706] = { name="Bedlam +3" , model = 32768} +models.ranged[19707] = { name="Spitfire +3" , model = 32768} +models.ranged[19708] = { name="Mayhem +3" , model = 32768} +models.ranged[19709] = { name="Anarchy +3" , model = 32768} +models.ranged[19720] = { name="Gastraphetes" , model = 32768} +models.ranged[19726] = { name="Death Penalty" , model = 32768} +models.ranged[19730] = { name="Vision Bow" , model = 32768} +models.ranged[19731] = { name="Suppressor Gun" , model = 32768} +models.ranged[19732] = { name="Miramar Gun" , model = 32768} +models.ranged[19733] = { name="Beursault Bow" , model = 32768} +models.ranged[19734] = { name="Beursault Bow +1" , model = 32768} +models.ranged[19735] = { name="Cecchino's Fucile" , model = 32768} +models.ranged[19736] = { name="Cecchin. Fucile +1" , model = 32768} +models.ranged[19737] = { name="Percept Bow" , model = 32768} +models.ranged[19738] = { name="Aife's Bow" , model = 32768} +models.ranged[19739] = { name="Moros Crossbow" , model = 32768} +models.ranged[19740] = { name="Stoertebeker" , model = 32768} +models.ranged[19741] = { name="Handgonne" , model = 32768} +models.ranged[19742] = { name="Handgonne +1" , model = 32768} +models.ranged[19743] = { name="Opprimo" , model = 32768} +models.ranged[19744] = { name="Opprimo +1" , model = 32768} +models.ranged[19758] = { name="Annihilator" , model = 32768} +models.ranged[19759] = { name="Yoichinoyumi" , model = 32768} +models.ranged[19770] = { name="Aliyat Chakram" , model = 32768} +models.ranged[19784] = { name="Lanner Bow" , model = 32768} +models.ranged[19785] = { name="Lanner Bow +1" , model = 32768} +models.ranged[19786] = { name="Nurigomeyumi" , model = 32768} +models.ranged[19787] = { name="Nurigomeyumi +1" , model = 32768} +models.ranged[19817] = { name="Gandiva" , model = 32768} +models.ranged[19818] = { name="Armageddon" , model = 32768} +models.ranged[19829] = { name="Gastraphetes" , model = 32768} +models.ranged[19835] = { name="Death Penalty" , model = 32768} +models.ranged[19851] = { name="Annihilator" , model = 32768} +models.ranged[19852] = { name="Yoichinoyumi" , model = 32768} +models.ranged[19865] = { name="Gandiva" , model = 32768} +models.ranged[19866] = { name="Armageddon" , model = 32768} +models.ranged[19940] = { name="Circinae" , model = 32768} +models.ranged[19941] = { name="Gymnogyps" , model = 32768} +models.ranged[19942] = { name="Terathopus" , model = 32768} +models.ranged[19943] = { name="Accipiter" , model = 32768} +models.ranged[19944] = { name="Mollfrith" , model = 32768} +models.ranged[19945] = { name="Aithon" , model = 32768} +models.ranged[19946] = { name="Erra" , model = 32768} +models.ranged[19947] = { name="Ataktos" , model = 32768} +models.ranged[19958] = { name="Gastraphetes" , model = 32768} +models.ranged[19964] = { name="Death Penalty" , model = 32768} +models.ranged[21210] = { name="Yoichinoyumi" , model = 32768} +models.ranged[21211] = { name="Yoichinoyumi" , model = 32768} +models.ranged[21212] = { name="Gandiva" , model = 32768} +models.ranged[21213] = { name="Gandiva" , model = 32768} +models.ranged[21214] = { name="Nobility" , model = 32768} +models.ranged[21215] = { name="Vijaya Bow" , model = 32768} +models.ranged[21216] = { name="Nibiru Bow" , model = 32768} +models.ranged[21217] = { name="Blurred Bow" , model = 32768} +models.ranged[21218] = { name="Blurred Bow +1" , model = 32768} +models.ranged[21219] = { name="Paloma Bow" , model = 32768} +models.ranged[21220] = { name="Paloma Bow +1" , model = 32768} +models.ranged[21221] = { name="Brahmastra" , model = 32768} +models.ranged[21222] = { name="Mengado" , model = 32768} +models.ranged[21223] = { name="Mengado +1" , model = 32768} +models.ranged[21224] = { name="Phaosphaelia" , model = 32768} +models.ranged[21226] = { name="Homestead Bow" , model = 32768} +models.ranged[21227] = { name="Hangaku-no-Yumi" , model = 32768} +models.ranged[21228] = { name="Falubeza" , model = 32768} +models.ranged[21229] = { name="Cibitshavore" , model = 32768} +models.ranged[21230] = { name="Bocluamni +2" , model = 32768} +models.ranged[21231] = { name="Eminent Bow" , model = 32768} +models.ranged[21232] = { name="Phulax Bow" , model = 32768} +models.ranged[21233] = { name="Ajjub Bow" , model = 32768} +models.ranged[21234] = { name="Circinae -1" , model = 32768} +models.ranged[21235] = { name="Cama. Bow" , model = 32768} +models.ranged[21236] = { name="Bocluamni +1" , model = 32768} +models.ranged[21237] = { name="Forefront Bow" , model = 32768} +models.ranged[21238] = { name="Speleogen Bow" , model = 32768} +models.ranged[21239] = { name="Echidna's Bow" , model = 32768} +models.ranged[21240] = { name="Echidna's Bow +1" , model = 32768} +models.ranged[21241] = { name="Coalition Bow" , model = 32768} +models.ranged[21242] = { name="Bocluamni" , model = 32768} +models.ranged[21243] = { name="Ahkormaar Bow" , model = 32768} +models.ranged[21244] = { name="Ahkormaar Bow +1" , model = 32768} +models.ranged[21245] = { name="Guglielmo's Bow" , model = 32768} +models.ranged[21246] = { name="Gastraphetes" , model = 32768} +models.ranged[21247] = { name="Gastraphetes" , model = 32768} +models.ranged[21248] = { name="Home. Bowgun" , model = 32768} +models.ranged[21249] = { name="Iqonde Crossbow" , model = 32768} +models.ranged[21250] = { name="Iqonde Cross. +1" , model = 32768} +models.ranged[21251] = { name="Em. Crossbow" , model = 32768} +models.ranged[21252] = { name="One-eyed" , model = 32768} +models.ranged[21253] = { name="Atetepeyorg" , model = 32768} +models.ranged[21254] = { name="Cama. Bowgun" , model = 32768} +models.ranged[21255] = { name="Forefront Bowgun" , model = 32768} +models.ranged[21256] = { name="Illapa" , model = 32768} +models.ranged[21257] = { name="Zoquittihuitz" , model = 32768} +models.ranged[21258] = { name="Malayo Crossbow" , model = 32768} +models.ranged[21259] = { name="Malayo Crossbow +1" , model = 32768} +models.ranged[21260] = { name="Annihilator" , model = 32768} +models.ranged[21261] = { name="Annihilator" , model = 32768} +models.ranged[21262] = { name="Death Penalty" , model = 32768} +models.ranged[21263] = { name="Death Penalty" , model = 32768} +models.ranged[21264] = { name="Armageddon" , model = 32768} +models.ranged[21265] = { name="Armageddon" , model = 32768} +models.ranged[21266] = { name="Gastraphetes" , model = 32768} +models.ranged[21267] = { name="Annihilator" , model = 32768} +models.ranged[21268] = { name="Death Penalty" , model = 32768} +models.ranged[21269] = { name="Armageddon" , model = 32768} +models.ranged[21272] = { name="Troll Gun" , model = 32768} +models.ranged[21273] = { name="Nibiru Gun" , model = 32768} +models.ranged[21274] = { name="Donar Gun" , model = 32768} +models.ranged[21275] = { name="Homestead Gun" , model = 32768} +models.ranged[21276] = { name="Pulfanxa" , model = 32768} +models.ranged[21277] = { name="Lionsquall" , model = 32768} +models.ranged[21278] = { name="Deathlocke" , model = 32768} +models.ranged[21279] = { name="Hgafircian +2" , model = 32768} +models.ranged[21280] = { name="Decazoom Mk-XI" , model = 32768} +models.ranged[21281] = { name="Eminent Gun" , model = 32768} +models.ranged[21282] = { name="Qasama Hexagun" , model = 32768} +models.ranged[21283] = { name="Mollfrith -1" , model = 32768} +models.ranged[21284] = { name="Vanir Gun" , model = 32768} +models.ranged[21285] = { name="Cama. Gun" , model = 32768} +models.ranged[21286] = { name="Hgafircian +1" , model = 32768} +models.ranged[21287] = { name="Forefront Gun" , model = 32768} +models.ranged[21288] = { name="Surefire Arquebus" , model = 32768} +models.ranged[21289] = { name="Donderbuss" , model = 32768} +models.ranged[21290] = { name="Donderbuss +1" , model = 32768} +models.ranged[21291] = { name="Shadeshot Gun" , model = 32768} +models.ranged[21292] = { name="Bandeiras Gun" , model = 32768} +models.ranged[21293] = { name="Bandeiras Gun +1" , model = 32768} +models.ranged[21294] = { name="Hgafircian" , model = 32768} +models.ranged[21340] = { name="Halakaala" , model = 32768} +models.ranged[21348] = { name="Narmar Boomerang" , model = 32768} +models.ranged[21349] = { name="Wingcutter" , model = 32768} +models.ranged[21350] = { name="Wingcutter +1" , model = 32768} +models.ranged[21368] = { name="Bestas Bane" , model = 32768} +models.ranged[21372] = { name="Dunna" , model = 32768} +models.ranged[21375] = { name="Magneto" , model = 32768} +models.ranged[21390] = { name="Albin Bane" , model = 32768} +models.ranged[21392] = { name="Animator Z" , model = 32768} +models.ranged[21398] = { name="Marsyas" , model = 32768} +models.ranged[21399] = { name="Nibiru Harp" , model = 32768} +models.ranged[21400] = { name="Blurred Harp" , model = 32768} +models.ranged[21401] = { name="Blurred Harp +1" , model = 32768} +models.ranged[21402] = { name="Damani Horn" , model = 32768} +models.ranged[21403] = { name="Damani Horn +1" , model = 32768} +models.ranged[21404] = { name="Linos" , model = 32768} +models.ranged[21405] = { name="Eminent Flute" , model = 32768} +models.ranged[21406] = { name="Homestead Flute" , model = 32768} +models.ranged[21407] = { name="Terpander" , model = 32768} +models.ranged[21408] = { name="Cama. Harp" , model = 32768} +models.ranged[21409] = { name="Forefront Flute" , model = 32768} +models.ranged[21452] = { name="Divinator" , model = 32768} +models.ranged[21453] = { name="Em. Animator" , model = 32768} +models.ranged[21454] = { name="F. Animator" , model = 32768} +models.ranged[21455] = { name="Alternator" , model = 32768} +models.ranged[21456] = { name="Animator P" , model = 32768} +models.ranged[21457] = { name="Animator P +1" , model = 32768} +models.ranged[21458] = { name="Animator P II" , model = 32768} +models.ranged[21459] = { name="Animator P II +1" , model = 32768} +models.ranged[21460] = { name="Matre Bell" , model = 32768} +models.ranged[21461] = { name="Filiae Bell" , model = 32768} +models.ranged[21462] = { name="Eminent Bell" , model = 32768} +models.ranged[21463] = { name="Nepote Bell" , model = 32768} +models.ranged[21476] = { name="Doomsday" , model = 32768} +models.ranged[21477] = { name="Atalanta" , model = 32768} +models.ranged[21478] = { name="Moros Cross. +1" , model = 32768} +models.ranged[21479] = { name="Tsoa. Crossbow" , model = 32768} +models.ranged[21480] = { name="Blurred Crossbow" , model = 32768} +models.ranged[21481] = { name="Blurred Cross. +1" , model = 32768} +models.ranged[21482] = { name="Compensator" , model = 32768} +models.ranged[21483] = { name="Malison" , model = 32768} +models.ranged[21484] = { name="Malison +1" , model = 32768} +models.ranged[21485] = { name="Fomalhaut" , model = 32768} +models.ranged[22107] = { name="Ullr" , model = 32768} +models.ranged[22108] = { name="Tokko Bow" , model = 32768} +models.ranged[22109] = { name="Ajja Bow" , model = 32768} +models.ranged[22110] = { name="Eletta Bow" , model = 32768} +models.ranged[22111] = { name="Kaja Bow" , model = 32768} +models.ranged[22112] = { name="Mizukage-no-Yumi" , model = 32768} +models.ranged[22113] = { name="Teller" , model = 32768} +models.ranged[22114] = { name="Steinthor" , model = 32768} +models.ranged[22115] = { name="Yoichinoyumi" , model = 32768} +models.ranged[22116] = { name="Gandiva" , model = 32768} +models.ranged[22117] = { name="Fail-Not" , model = 32768} +models.ranged[22118] = { name="Venery Bow" , model = 32768} +models.ranged[22119] = { name="Wochowsen" , model = 32768} +models.ranged[22120] = { name="Imati" , model = 32768} +models.ranged[22121] = { name="Imati +1" , model = 32768} +models.ranged[22122] = { name="Arasy Bow" , model = 32768} +models.ranged[22123] = { name="Arasy Bow +1" , model = 32768} +models.ranged[22124] = { name="Artemis's Bow" , model = 32768} +models.ranged[22125] = { name="Exalted Bow" , model = 32768} +models.ranged[22126] = { name="Exalted Bow +1" , model = 32768} +models.ranged[22127] = { name="Raetic Bow" , model = 32768} +models.ranged[22128] = { name="Raetic Bow +1" , model = 32768} +models.ranged[22129] = { name="Yoichinoyumi" , model = 32768} +models.ranged[22130] = { name="Gandiva" , model = 32768} +models.ranged[22131] = { name="Fail-Not" , model = 32768} +models.ranged[22132] = { name="Artemis's Bow +1" , model = 32768} +models.ranged[22133] = { name="Voluspa Bow" , model = 32768} +models.ranged[22134] = { name="Holliday" , model = 32768} +models.ranged[22135] = { name="Arasy Gun" , model = 32768} +models.ranged[22136] = { name="Arasy Gun +1" , model = 32768} +models.ranged[22137] = { name="Exalted C.bow" , model = 32768} +models.ranged[22138] = { name="Exalted C.bow +1" , model = 32768} +models.ranged[22139] = { name="Gastraphetes" , model = 32768} +models.ranged[22140] = { name="Annihilator" , model = 32768} +models.ranged[22141] = { name="Death Penalty" , model = 32768} +models.ranged[22142] = { name="Armageddon" , model = 32768} +models.ranged[22143] = { name="Fomalhaut" , model = 32768} +models.ranged[22144] = { name="Voluspa Gun" , model = 32768} +models.ranged[22147] = { name="Scout's Crossbow" , model = 32768} +models.ranged[22148] = { name="Arke Crossbow" , model = 32768} +models.ranged[22149] = { name="Sharanga" , model = 32768} +models.ranged[22260] = { name="E. Animator II" , model = 32768} +models.ranged[22261] = { name="Divinator II" , model = 32768} +models.ranged[22266] = { name="Antitail" , model = 32768} +models.ranged[22267] = { name="Antitail +1" , model = 32768} +models.ranged[22283] = { name="Marvelous Cheer" , model = 32768} \ No newline at end of file diff --git a/addons/DressUp/sub.lua b/addons/DressUp/sub.lua new file mode 100644 index 0000000000..11f3f21427 --- /dev/null +++ b/addons/DressUp/sub.lua @@ -0,0 +1,1729 @@ +-- Copyright © 2013, 2022 Cairthenn +-- 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 DressUp 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 Cairthenn 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. + + +models.sub = {} + +models.sub["None"] = { name = "empty" , enl = "empty", model = 28672 } + +models.sub[16447] = { name = "Rusty Dagger" , model = 28836} +models.sub[16448] = { name = "Bronze Dagger" , model = 28836} +models.sub[16449] = { name = "Brass Dagger" , model = 28837} +models.sub[16450] = { name = "Dagger" , model = 28838} +models.sub[16451] = { name = "Mythril Dagger" , model = 28839} +models.sub[16452] = { name = "Misericorde" , model = 28835} +models.sub[16453] = { name = "Orichalcum Dagger" , model = 28851} +models.sub[16454] = { name = "Blind Dagger" , model = 28836} +models.sub[16455] = { name = "Baselard" , model = 28841} +models.sub[16456] = { name = "Mythril Baselard" , model = 28842} +models.sub[16457] = { name = "Dst. Baselard" , model = 28840} +models.sub[16458] = { name = "Poison Baselard" , model = 28841} +models.sub[16459] = { name = "Acid Baselard" , model = 28842} +models.sub[16460] = { name = "Kris" , model = 28850} +models.sub[16461] = { name = "Adaman Kris" , model = 28849} +models.sub[16463] = { name = "Cmb.Cst. Dagger" , model = 28849} +models.sub[16465] = { name = "Bronze Knife" , model = 28831} +models.sub[16466] = { name = "Knife" , model = 28832} +models.sub[16467] = { name = "Mythril Knife" , model = 28833} +models.sub[16468] = { name = "Darksteel Knife" , model = 28830} +models.sub[16469] = { name = "Cermet Knife" , model = 28834} +models.sub[16470] = { name = "Gully" , model = 28829} +models.sub[16471] = { name = "Blind Knife" , model = 28831} +models.sub[16472] = { name = "Poison Knife" , model = 28832} +models.sub[16473] = { name = "Kukri" , model = 28844} +models.sub[16475] = { name = "Mythril Kukri" , model = 28845} +models.sub[16476] = { name = "Darksteel Kukri" , model = 28843} +models.sub[16477] = { name = "Cermet Kukri" , model = 28846} +models.sub[16478] = { name = "Poison Kukri" , model = 28844} +models.sub[16479] = { name = "Acid Kukri" , model = 28845} +models.sub[16480] = { name = "Thief's Knife" , model = 28848} +models.sub[16481] = { name = "Yataghan +1" , model = 29070} +models.sub[16482] = { name = "Onion Dagger" , model = 28836} +models.sub[16483] = { name = "Onion Knife" , model = 28831} +models.sub[16484] = { name = "Burglar's Dagger" , model = 28838} +models.sub[16485] = { name = "Yataghan" , model = 29070} +models.sub[16486] = { name = "Beestinger" , model = 28839} +models.sub[16487] = { name = "Minstrel's Dagger" , model = 28836} +models.sub[16488] = { name = "Nguul" , model = 28829} +models.sub[16489] = { name = "Poison Kukri +1" , model = 28844} +models.sub[16490] = { name = "Blind Knife +1" , model = 28831} +models.sub[16491] = { name = "Bronze Knife +1" , model = 28831} +models.sub[16492] = { name = "Bronze Dagger +1" , model = 28836} +models.sub[16493] = { name = "Blind Dagger +1" , model = 28836} +models.sub[16494] = { name = "Corrosive Kukri" , model = 28845} +models.sub[16495] = { name = "Silence Dagger" , model = 28837} +models.sub[16496] = { name = "Poison Dagger" , model = 28838} +models.sub[16497] = { name = "Sleep Dagger" , model = 28839} +models.sub[16498] = { name = "Carabineer Dagger" , model = 28851} +models.sub[16499] = { name = "Venom Kris" , model = 28850} +models.sub[16500] = { name = "Aluh Jambiya" , model = 29081} +models.sub[16501] = { name = "Acid Knife" , model = 28833} +models.sub[16502] = { name = "Venom Knife" , model = 28830} +models.sub[16503] = { name = "Stun Knife" , model = 28834} +models.sub[16504] = { name = "Oynos Knife" , model = 28834} +models.sub[16505] = { name = "Venom Kukri" , model = 28843} +models.sub[16506] = { name = "Stun Kukri" , model = 28846} +models.sub[16507] = { name = "Venom Baselard" , model = 28840} +models.sub[16508] = { name = "Silence Dagger +1" , model = 28837} +models.sub[16509] = { name = "Aspir Knife" , model = 28831} +models.sub[16510] = { name = "Vnm. Baselard +1" , model = 28840} +models.sub[16511] = { name = "Burnite Shell" , model = 28852} +models.sub[16512] = { name = "Bilbo" , model = 28855} +models.sub[16513] = { name = "Tuck" , model = 28856} +models.sub[16514] = { name = "Mailbreaker" , model = 28859} +models.sub[16515] = { name = "Colichemarde" , model = 28853} +models.sub[16516] = { name = "Jr.Msk. Tuck" , model = 28856} +models.sub[16517] = { name = "Degen" , model = 28860} +models.sub[16518] = { name = "Mythril Degen" , model = 28861} +models.sub[16519] = { name = "Schlaeger" , model = 28858} +models.sub[16520] = { name = "Verdun" , model = 28857} +models.sub[16521] = { name = "Rapier" , model = 28859} +models.sub[16522] = { name = "Flame Degen" , model = 28860} +models.sub[16523] = { name = "Holy Degen" , model = 28861} +models.sub[16524] = { name = "Fleuret" , model = 28863} +models.sub[16525] = { name = "Hornet Fleuret" , model = 28865} +models.sub[16526] = { name = "Schwert" , model = 28864} +models.sub[16527] = { name = "Epee" , model = 28862} +models.sub[16528] = { name = "Bloody Rapier" , model = 28860} +models.sub[16529] = { name = "Musketeer's Sword" , model = 28860} +models.sub[16530] = { name = "Xiphos" , model = 28936} +models.sub[16531] = { name = "Brass Xiphos" , model = 28937} +models.sub[16532] = { name = "Gladius" , model = 28938} +models.sub[16533] = { name = "Ancient Sword" , model = 28955} +models.sub[16534] = { name = "Onion Sword" , model = 28937} +models.sub[16535] = { name = "Bronze Sword" , model = 28940} +models.sub[16536] = { name = "Iron Sword" , model = 28942} +models.sub[16537] = { name = "Mythril Sword" , model = 28943} +models.sub[16538] = { name = "Darksteel Sword" , model = 28939} +models.sub[16539] = { name = "Cermet Sword" , model = 28945} +models.sub[16540] = { name = "Tyrfing" , model = 29190} +models.sub[16541] = { name = "Jagdplaute" , model = 28941} +models.sub[16542] = { name = "Wing Sword" , model = 28960} +models.sub[16543] = { name = "Fire Sword" , model = 28940} +models.sub[16544] = { name = "Ryl.Arc. Sword" , model = 28923} +models.sub[16545] = { name = "Broadsword" , model = 28948} +models.sub[16546] = { name = "Katzbalger" , model = 28947} +models.sub[16547] = { name = "Anelace" , model = 28946} +models.sub[16548] = { name = "Coral Sword" , model = 28949} +models.sub[16549] = { name = "Divine Sword" , model = 28948} +models.sub[16550] = { name = "Hallowed Sword" , model = 28948} +models.sub[16551] = { name = "Sapara" , model = 28927} +models.sub[16552] = { name = "Scimitar" , model = 28928} +models.sub[16553] = { name = "Tulwar" , model = 28929} +models.sub[16554] = { name = "Hanger" , model = 28930} +models.sub[16555] = { name = "Ridill" , model = 28931} +models.sub[16556] = { name = "Bloody Blade" , model = 28934} +models.sub[16557] = { name = "Msk.Cmd. Falchion" , model = 28934} +models.sub[16558] = { name = "Falchion" , model = 28934} +models.sub[16559] = { name = "Darksteel Falchion" , model = 28932} +models.sub[16560] = { name = "Cutlass" , model = 28935} +models.sub[16562] = { name = "Platinum Cutlass" , model = 28933} +models.sub[16563] = { name = "Rune Blade" , model = 28926} +models.sub[16564] = { name = "Flame Blade" , model = 28934} +models.sub[16565] = { name = "Spatha" , model = 28921} +models.sub[16566] = { name = "Longsword" , model = 28923} +models.sub[16567] = { name = "Knight's Sword" , model = 28924} +models.sub[16568] = { name = "Saber" , model = 28925} +models.sub[16569] = { name = "Gold Sword" , model = 28922} +models.sub[16571] = { name = "T.K. Army Sword" , model = 28923} +models.sub[16572] = { name = "Bee Spatha" , model = 28921} +models.sub[16575] = { name = "Curtana" , model = 28941} +models.sub[16576] = { name = "Hunting Sword" , model = 28952} +models.sub[16577] = { name = "Bastard Sword" , model = 28951} +models.sub[16578] = { name = "Espadon" , model = 28953} +models.sub[16579] = { name = "Kaskara" , model = 28950} +models.sub[16580] = { name = "Bloodsword" , model = 28959} +models.sub[16581] = { name = "Holy Sword" , model = 28958} +models.sub[16582] = { name = "Vetala Sword" , model = 28960} +models.sub[16600] = { name = "Wax Sword" , model = 28940} +models.sub[16604] = { name = "Save the Queen" , model = 28924} +models.sub[16605] = { name = "Enhancing Sword" , model = 28922} +models.sub[16608] = { name = "Gladiator" , model = 28938} +models.sub[16609] = { name = "Bloody Sword" , model = 28939} +models.sub[16610] = { name = "Wax Sword +1" , model = 28940} +models.sub[16611] = { name = "Bee Spatha +1" , model = 28921} +models.sub[16612] = { name = "Saber +1" , model = 28925} +models.sub[16613] = { name = "Spirit Sword" , model = 28958} +models.sub[16614] = { name = "Knife +1" , model = 28832} +models.sub[16615] = { name = "Falchion +1" , model = 28934} +models.sub[16617] = { name = "Tuck +1" , model = 28856} +models.sub[16618] = { name = "Mailbreaker +1" , model = 28859} +models.sub[16619] = { name = "Epee +1" , model = 28862} +models.sub[16620] = { name = "Merman's Sword" , model = 28949} +models.sub[16621] = { name = "Flame Sword" , model = 28940} +models.sub[16623] = { name = "Bronze Sword +1" , model = 28940} +models.sub[16624] = { name = "Xiphos +1" , model = 28936} +models.sub[16625] = { name = "Scimitar +1" , model = 28928} +models.sub[16626] = { name = "Iron Sword +1" , model = 28942} +models.sub[16627] = { name = "Spatha +1" , model = 28921} +models.sub[16628] = { name = "Longsword +1" , model = 28923} +models.sub[16629] = { name = "Small Sword" , model = 28854} +models.sub[16630] = { name = "Striker Sword" , model = 28955} +models.sub[16631] = { name = "Kaiser Sword" , model = 28956} +models.sub[16632] = { name = "Bilbo +1" , model = 28855} +models.sub[16633] = { name = "Degen +1" , model = 28860} +models.sub[16634] = { name = "Broadsword +1" , model = 28948} +models.sub[16635] = { name = "Mythril Sword +1" , model = 28943} +models.sub[16636] = { name = "Tulwar +1" , model = 28929} +models.sub[16640] = { name = "Bronze Axe" , model = 28748} +models.sub[16641] = { name = "Brass Axe" , model = 28749} +models.sub[16642] = { name = "Bone Axe" , model = 28752} +models.sub[16643] = { name = "Battleaxe" , model = 28750} +models.sub[16644] = { name = "Mythril Axe" , model = 28751} +models.sub[16645] = { name = "Darksteel Axe" , model = 28756} +models.sub[16646] = { name = "Bronze Axe +1" , model = 28748} +models.sub[16647] = { name = "Rune Axe" , model = 28757} +models.sub[16648] = { name = "Legionnaire's Axe" , model = 28750} +models.sub[16649] = { name = "Bone Pick" , model = 28762} +models.sub[16650] = { name = "War Pick" , model = 28760} +models.sub[16651] = { name = "Mythril Pick" , model = 28761} +models.sub[16652] = { name = "Darksteel Pick" , model = 28759} +models.sub[16653] = { name = "Nadziak" , model = 28758} +models.sub[16654] = { name = "Glyph Axe" , model = 29191} +models.sub[16655] = { name = "Rusty Pick" , model = 28760} +models.sub[16656] = { name = "Orcish Axe" , model = 28763} +models.sub[16657] = { name = "Tabar" , model = 28755} +models.sub[16658] = { name = "Darksteel Tabar" , model = 28754} +models.sub[16659] = { name = "Tabarzin" , model = 28753} +models.sub[16660] = { name = "Doom Tabar" , model = 28753} +models.sub[16661] = { name = "Brass Axe +1" , model = 28749} +models.sub[16662] = { name = "Doom Tabar +1" , model = 28753} +models.sub[16663] = { name = "Battleaxe +1" , model = 28750} +models.sub[16664] = { name = "War Pick +1" , model = 28760} +models.sub[16665] = { name = "Mythril Axe +1" , model = 28751} +models.sub[16666] = { name = "Bone Axe +1" , model = 28752} +models.sub[16667] = { name = "Light Axe" , model = 28750} +models.sub[16668] = { name = "Bone Pick +1" , model = 28762} +models.sub[16669] = { name = "Cmb.Cst. Axe" , model = 28755} +models.sub[16670] = { name = "Mythril Pick +1" , model = 28761} +models.sub[16671] = { name = "Tabar +1" , model = 28755} +models.sub[16672] = { name = "Tigerhunter" , model = 28752} +models.sub[16673] = { name = "Warrior's Axe" , model = 28750} +models.sub[16674] = { name = "Emeth Pick" , model = 28761} +models.sub[16675] = { name = "Storm Axe" , model = 28751} +models.sub[16676] = { name = "Viking Axe" , model = 28756} +models.sub[16677] = { name = "Darksteel Axe +1" , model = 28756} +models.sub[16678] = { name = "Razor Axe" , model = 28750} +models.sub[16679] = { name = "Wrath Tabar" , model = 28754} +models.sub[16680] = { name = "Barbaroi Axe" , model = 28763} +models.sub[16681] = { name = "Gerwitz's Axe" , model = 28755} +models.sub[16682] = { name = "Darksteel Pick +1" , model = 28759} +models.sub[16683] = { name = "Dst. Tabar +1" , model = 28754} +models.sub[16684] = { name = "Kabrakan's Axe" , model = 28763} +models.sub[16685] = { name = "Nadziak +1" , model = 28758} +models.sub[16686] = { name = "Arcanabane" , model = 28762} +models.sub[16687] = { name = "Platoon Axe" , model = 28749} +models.sub[16736] = { name = "Dagger +1" , model = 28838} +models.sub[16737] = { name = "Baselard +1" , model = 28841} +models.sub[16738] = { name = "Mythril Dagger +1" , model = 28839} +models.sub[16739] = { name = "Mythril Knife +1" , model = 28833} +models.sub[16740] = { name = "Brass Dagger +1" , model = 28837} +models.sub[16741] = { name = "Poison Dagger +1" , model = 28838} +models.sub[16742] = { name = "Poison Knife +1" , model = 28832} +models.sub[16743] = { name = "Python Baselard" , model = 28841} +models.sub[16744] = { name = "Ryl.Sqr. Dagger" , model = 28842} +models.sub[16745] = { name = "Decurion's Dagger" , model = 28839} +models.sub[16746] = { name = "Mercenary's Knife" , model = 28832} +models.sub[16747] = { name = "Mrc.Cpt. Kukri" , model = 28844} +models.sub[16748] = { name = "Kukri +1" , model = 28844} +models.sub[16749] = { name = "Kris +1" , model = 28850} +models.sub[16750] = { name = "Mythril Kukri +1" , model = 28845} +models.sub[16751] = { name = "Dst. Knife +1" , model = 28830} +models.sub[16752] = { name = "Fine Baselard" , model = 28839} +models.sub[16753] = { name = "Ceremonial Dagger" , model = 28836} +models.sub[16754] = { name = "Parrying Knife" , model = 28848} +models.sub[16755] = { name = "Archer's Knife" , model = 28833} +models.sub[16756] = { name = "Leste Jambiya" , model = 29051} +models.sub[16757] = { name = "Corsair's Knife" , model = 28843} +models.sub[16758] = { name = "Dst. Baselard +1" , model = 28840} +models.sub[16759] = { name = "Darksteel Kris" , model = 28850} +models.sub[16760] = { name = "Darksteel Kris +1" , model = 28850} +models.sub[16761] = { name = "Venom Kris +1" , model = 28850} +models.sub[16762] = { name = "Venom Knife +1" , model = 28830} +models.sub[16763] = { name = "Darksteel Kukri +1" , model = 28843} +models.sub[16764] = { name = "Marauder's Knife" , model = 28832} +models.sub[16765] = { name = "Lust Dagger" , model = 28837} +models.sub[16766] = { name = "Paper Knife" , model = 28831} +models.sub[16767] = { name = "Triple Dagger" , model = 28851} +models.sub[16800] = { name = "Knight's Sword +1" , model = 28924} +models.sub[16801] = { name = "Sapara +1" , model = 28927} +models.sub[16802] = { name = "Brass Xiphos +1" , model = 28937} +models.sub[16803] = { name = "Fleuret +1" , model = 28863} +models.sub[16804] = { name = "Flame Blade +1" , model = 28934} +models.sub[16805] = { name = "Ryl.Grd. Fleuret" , model = 28865} +models.sub[16806] = { name = "Centurion's Sword" , model = 28943} +models.sub[16807] = { name = "Cmb.Cst. Scimitar" , model = 28929} +models.sub[16808] = { name = "Wis.Wiz. Bilbo" , model = 28854} +models.sub[16809] = { name = "Wis.Wiz. Anelace" , model = 28946} +models.sub[16810] = { name = "Tct.Mag. Espadon" , model = 28952} +models.sub[16811] = { name = "Dst. Sword +1" , model = 28939} +models.sub[16812] = { name = "War Sword" , model = 28952} +models.sub[16813] = { name = "Schlaeger +1" , model = 28858} +models.sub[16814] = { name = "Crescent Sword" , model = 28932} +models.sub[16815] = { name = "Mythril Degen +1" , model = 28861} +models.sub[16816] = { name = "Holy Sword +1" , model = 28958} +models.sub[16817] = { name = "Holy Degen +1" , model = 28861} +models.sub[16818] = { name = "San d'Orian Sword" , model = 28923} +models.sub[16819] = { name = "Mithran Scimitar" , model = 28928} +models.sub[16820] = { name = "Strider Sword" , model = 28942} +models.sub[16821] = { name = "Duel Rapier" , model = 28859} +models.sub[16822] = { name = "Crimson Blade" , model = 28940} +models.sub[16823] = { name = "Flame Degen +1" , model = 28860} +models.sub[16824] = { name = "Carnage Rapier" , model = 28860} +models.sub[16825] = { name = "Cermet Sword +1" , model = 28945} +models.sub[16826] = { name = "Divine Sword +1" , model = 28948} +models.sub[16827] = { name = "Carnage Blade" , model = 28934} +models.sub[16828] = { name = "Bastard Sword +1" , model = 28951} +models.sub[16829] = { name = "Fencing Degen" , model = 28860} +models.sub[16830] = { name = "Gluttony Sword" , model = 28959} +models.sub[16831] = { name = "Greed Scimitar" , model = 28954} +models.sub[16896] = { name = "Kunai" , model = 28987} +models.sub[16897] = { name = "Kageboshi" , model = 28986} +models.sub[16898] = { name = "Cmb.Cst. Kusabi" , model = 28986} +models.sub[16899] = { name = "Hototogisu" , model = 28987} +models.sub[16900] = { name = "Wakizashi" , model = 28982} +models.sub[16901] = { name = "Kodachi" , model = 28983} +models.sub[16902] = { name = "Sakurafubuki" , model = 28984} +models.sub[16903] = { name = "Kabutowari" , model = 28985} +models.sub[16904] = { name = "Fudo" , model = 28981} +models.sub[16905] = { name = "Bokuto" , model = 28982} +models.sub[16906] = { name = "Mokuto" , model = 28982} +models.sub[16907] = { name = "Busuto" , model = 28982} +models.sub[16908] = { name = "Yoto" , model = 28982} +models.sub[16909] = { name = "Kororito" , model = 28982} +models.sub[16910] = { name = "Mamushito" , model = 28982} +models.sub[16911] = { name = "Amanojaku" , model = 28982} +models.sub[16912] = { name = "Kitsutsuki" , model = 28987} +models.sub[16913] = { name = "Shinogi" , model = 28983} +models.sub[16914] = { name = "Kunai +1" , model = 28987} +models.sub[16915] = { name = "Hien" , model = 28987} +models.sub[16916] = { name = "Hien +1" , model = 28987} +models.sub[16917] = { name = "Suzume" , model = 28987} +models.sub[16918] = { name = "Wakizashi +1" , model = 28982} +models.sub[16919] = { name = "Shinobi-Gatana" , model = 28982} +models.sub[16920] = { name = "Shinobi-Gatana +1" , model = 28982} +models.sub[16921] = { name = "Kodachi +1" , model = 28983} +models.sub[16922] = { name = "Sakurafubuki +1" , model = 28984} +models.sub[16923] = { name = "Kabutowari +1" , model = 28985} +models.sub[16924] = { name = "Hocho" , model = 28984} +models.sub[16925] = { name = "Mokuto +1" , model = 28982} +models.sub[16926] = { name = "Bokuto +1" , model = 28982} +models.sub[16927] = { name = "Busuto +1" , model = 28982} +models.sub[17024] = { name = "Ash Club" , model = 28780} +models.sub[17025] = { name = "Chestnut Club" , model = 28781} +models.sub[17026] = { name = "Bone Cudgel" , model = 28773} +models.sub[17027] = { name = "Oak Cudgel" , model = 28772} +models.sub[17028] = { name = "Freesword's Club" , model = 28780} +models.sub[17029] = { name = "Bouncer Club" , model = 28781} +models.sub[17030] = { name = "Great Club" , model = 28783} +models.sub[17031] = { name = "Shell Scepter" , model = 29264} +models.sub[17032] = { name = "Gobbie Gavel" , model = 29265} +models.sub[17033] = { name = "Bone Cudgel +1" , model = 28773} +models.sub[17034] = { name = "Bronze Mace" , model = 28776} +models.sub[17035] = { name = "Mace" , model = 28778} +models.sub[17036] = { name = "Mythril Mace" , model = 28779} +models.sub[17037] = { name = "Darksteel Mace" , model = 28775} +models.sub[17038] = { name = "Buzdygan" , model = 28774} +models.sub[17039] = { name = "Platinum Mace" , model = 28777} +models.sub[17040] = { name = "Warp Cudgel" , model = 28772} +models.sub[17041] = { name = "Holy Mace" , model = 28779} +models.sub[17042] = { name = "Bronze Hammer" , model = 28785} +models.sub[17043] = { name = "Brass Hammer" , model = 28786} +models.sub[17044] = { name = "Warhammer" , model = 28787} +models.sub[17045] = { name = "Maul" , model = 28788} +models.sub[17046] = { name = "Darksteel Maul" , model = 28784} +models.sub[17047] = { name = "Magnus Hammer" , model = 28788} +models.sub[17048] = { name = "Decurion's Hammer" , model = 28787} +models.sub[17049] = { name = "Maple Wand" , model = 28899} +models.sub[17050] = { name = "Willow Wand" , model = 28904} +models.sub[17051] = { name = "Yew Wand" , model = 28898} +models.sub[17052] = { name = "Chestnut Wand" , model = 28903} +models.sub[17053] = { name = "Rose Wand" , model = 28902} +models.sub[17054] = { name = "Ebony Wand" , model = 28897} +models.sub[17056] = { name = "Mythic Wand" , model = 28900} +models.sub[17057] = { name = "Tefnut Wand" , model = 29204} +models.sub[17058] = { name = "Caduceus" , model = 28905} +models.sub[17059] = { name = "Bronze Rod" , model = 28892} +models.sub[17060] = { name = "Rod" , model = 28894} +models.sub[17061] = { name = "Mythril Rod" , model = 28895} +models.sub[17062] = { name = "Bone Rod" , model = 28896} +models.sub[17063] = { name = "Darksteel Rod" , model = 28891} +models.sub[17064] = { name = "Scepter" , model = 28890} +models.sub[17065] = { name = "Platinum Rod" , model = 28893} +models.sub[17066] = { name = "Molva Maul" , model = 28786} +models.sub[17067] = { name = "Ryl. Guard's Rod" , model = 28893} +models.sub[17068] = { name = "Onion Rod" , model = 28892} +models.sub[17069] = { name = "Moepapa Mace" , model = 28779} +models.sub[17070] = { name = "Living Rod" , model = 28893} +models.sub[17071] = { name = "Heat Rod" , model = 28892} +models.sub[17072] = { name = "Lilith's Rod" , model = 28892} +models.sub[17073] = { name = "Mistilteinn" , model = 28901} +models.sub[17074] = { name = "Chocobo Wand" , model = 28908} +models.sub[17075] = { name = "Star Rod" , model = 28912} +models.sub[17076] = { name = "Earth Wand" , model = 28916} +models.sub[17077] = { name = "Beneficus" , model = 28890} +models.sub[17078] = { name = "Siriti" , model = 28905} +models.sub[17079] = { name = "Winged Wand" , model = 28900} +models.sub[17080] = { name = "Holy Maul" , model = 28788} +models.sub[17081] = { name = "Brass Rod" , model = 28893} +models.sub[17082] = { name = "Tct.Mag. Wand" , model = 28903} +models.sub[17083] = { name = "Time Hammer" , model = 28787} +models.sub[17085] = { name = "Holy Wand" , model = 28900} +models.sub[17086] = { name = "Bronze Mace +1" , model = 28776} +models.sub[17087] = { name = "Maple Wand +1" , model = 28899} +models.sub[17111] = { name = "Bronze Rod +1" , model = 28892} +models.sub[17113] = { name = "Owleyes" , model = 29196} +models.sub[17114] = { name = "Holy Maul +1" , model = 28788} +models.sub[17115] = { name = "Warhammer +1" , model = 28787} +models.sub[17121] = { name = "Maul +1" , model = 28788} +models.sub[17136] = { name = "Sloth Wand" , model = 28902} +models.sub[17137] = { name = "Ash Club +1" , model = 28780} +models.sub[17138] = { name = "Willow Wand +1" , model = 28904} +models.sub[17139] = { name = "Solid Club" , model = 28781} +models.sub[17140] = { name = "Yew Wand +1" , model = 28898} +models.sub[17141] = { name = "Solid Wand" , model = 28903} +models.sub[17142] = { name = "Oak Cudgel +1" , model = 28772} +models.sub[17143] = { name = "Rose Wand +1" , model = 28902} +models.sub[17144] = { name = "Bronze Hammer +1" , model = 28785} +models.sub[17145] = { name = "Mace +1" , model = 28778} +models.sub[17146] = { name = "Rod +1" , model = 28894} +models.sub[17147] = { name = "Mythril Mace +1" , model = 28779} +models.sub[17148] = { name = "Brass Rod +1" , model = 28893} +models.sub[17149] = { name = "Brass Hammer +1" , model = 28786} +models.sub[17150] = { name = "Ryl.Sqr. Mace" , model = 28778} +models.sub[17151] = { name = "Msk.Cmd. Rod" , model = 28891} +models.sub[17408] = { name = "Great Club +1" , model = 28783} +models.sub[17409] = { name = "Mythril Rod +1" , model = 28895} +models.sub[17410] = { name = "Bone Rod +1" , model = 28896} +models.sub[17411] = { name = "Holy Mace +1" , model = 28779} +models.sub[17412] = { name = "Wild Cudgel" , model = 28773} +models.sub[17413] = { name = "Hermit's Wand" , model = 28904} +models.sub[17414] = { name = "Pixie Mace" , model = 28779} +models.sub[17415] = { name = "Shellbuster" , model = 28782} +models.sub[17416] = { name = "Arcana Breaker" , model = 28785} +models.sub[17417] = { name = "Rabbit Stick" , model = 28900} +models.sub[17418] = { name = "Moonlight Wand" , model = 28900} +models.sub[17419] = { name = "Artemis's Wand" , model = 28900} +models.sub[17420] = { name = "Selene's Wand" , model = 28900} +models.sub[17421] = { name = "Moonwatch Wand" , model = 28900} +models.sub[17422] = { name = "Blessed Hammer" , model = 28787} +models.sub[17423] = { name = "Casting Wand" , model = 28898} +models.sub[17426] = { name = "Replica Maul" , model = 28788} +models.sub[17427] = { name = "Ebony Wand +1" , model = 28897} +models.sub[17428] = { name = "Darksteel Mace +1" , model = 28775} +models.sub[17429] = { name = "Dominion Mace" , model = 28777} +models.sub[17430] = { name = "Fey Wand" , model = 28920} +models.sub[17431] = { name = "Platinum Mace +1" , model = 28777} +models.sub[17432] = { name = "Darksteel Maul +1" , model = 28784} +models.sub[17433] = { name = "Mythic Wand +1" , model = 28900} +models.sub[17434] = { name = "Holy Wand +1" , model = 28900} +models.sub[17435] = { name = "Darksteel Rod +1" , model = 28891} +models.sub[17436] = { name = "Platinum Rod +1" , model = 28893} +models.sub[17437] = { name = "Curse Wand" , model = 28914} +models.sub[17438] = { name = "Titan's Cudgel" , model = 28772} +models.sub[17439] = { name = "Leviathan's Rod" , model = 28893} +models.sub[17440] = { name = "Kraken Club" , model = 28782} +models.sub[17441] = { name = "Eremite's Wand" , model = 28904} +models.sub[17442] = { name = "Eremite's Wand +1" , model = 28904} +models.sub[17443] = { name = "Thoth's Wand" , model = 28900} +models.sub[17444] = { name = "Windurstian Club" , model = 28780} +models.sub[17445] = { name = "Federation Club" , model = 28780} +models.sub[17446] = { name = "T.M. Wand +1" , model = 28903} +models.sub[17447] = { name = "T.M. Wand +2" , model = 28903} +models.sub[17448] = { name = "San d'Orian Mace" , model = 28778} +models.sub[17449] = { name = "Kingdom Mace" , model = 28778} +models.sub[17450] = { name = "Healing Mace" , model = 28776} +models.sub[17451] = { name = "Morgenstern" , model = 29032} +models.sub[17452] = { name = "Bastokan Hammer" , model = 28787} +models.sub[17453] = { name = "Republic Hammer" , model = 28787} +models.sub[17454] = { name = "Asklepios" , model = 28913} +models.sub[17455] = { name = "Skirnir's Wand" , model = 28915} +models.sub[17456] = { name = "Club of Trials" , model = 28780} +models.sub[17457] = { name = "Snr.Msk. Rod" , model = 28890} +models.sub[17458] = { name = "Rsv.Cpt. Mace" , model = 28777} +models.sub[17459] = { name = "Scepter +1" , model = 28890} +models.sub[17460] = { name = "Buzdygan +1" , model = 28774} +models.sub[17461] = { name = "Rune Rod" , model = 29008} +models.sub[17462] = { name = "Platoon Mace" , model = 28776} +models.sub[17463] = { name = "Sealed Mace" , model = 28778} +models.sub[17464] = { name = "Purgatory Mace" , model = 28775} +models.sub[17465] = { name = "Mighty Cudgel" , model = 28772} +models.sub[17466] = { name = "Dia Wand" , model = 28899} +models.sub[17467] = { name = "Martial Wand" , model = 28914} +models.sub[17468] = { name = "Raise Rod" , model = 28895} +models.sub[17469] = { name = "Raise II Rod" , model = 28895} +models.sub[17470] = { name = "Pealing Buzdygan" , model = 28774} +models.sub[17471] = { name = "Horrent Mace" , model = 28775} +models.sub[17600] = { name = "Stun Knife +1" , model = 28834} +models.sub[17601] = { name = "Demon's Knife" , model = 28852} +models.sub[17602] = { name = "Demon's Knife +1" , model = 28852} +models.sub[17603] = { name = "Cermet Kukri +1" , model = 28846} +models.sub[17604] = { name = "Venom Kukri +1" , model = 28843} +models.sub[17605] = { name = "Acid Dagger" , model = 28839} +models.sub[17606] = { name = "Corrosive Dagger" , model = 28839} +models.sub[17607] = { name = "Corrosive Baselard" , model = 28842} +models.sub[17608] = { name = "Corrosive Knife" , model = 28833} +models.sub[17609] = { name = "Cermet Knife +1" , model = 28834} +models.sub[17610] = { name = "Bone Knife" , model = 28852} +models.sub[17611] = { name = "Bone Knife +1" , model = 28852} +models.sub[17612] = { name = "Beetle Knife" , model = 28852} +models.sub[17613] = { name = "Beetle Knife +1" , model = 28852} +models.sub[17614] = { name = "Stun Kukri +1" , model = 28846} +models.sub[17615] = { name = "Chicken Knife" , model = 28831} +models.sub[17616] = { name = "Dagger of Trials" , model = 28836} +models.sub[17617] = { name = "Mst.Cst. Knife" , model = 28852} +models.sub[17618] = { name = "Kidney Dagger" , model = 28841} +models.sub[17619] = { name = "Daylight Dagger" , model = 28842} +models.sub[17620] = { name = "Misericorde +1" , model = 28835} +models.sub[17621] = { name = "Gully +1" , model = 28829} +models.sub[17622] = { name = "Buccaneer's Knife" , model = 28845} +models.sub[17623] = { name = "Btm. Knife" , model = 28845} +models.sub[17624] = { name = "Anubis's Knife" , model = 28829} +models.sub[17625] = { name = "Ponderous Gully" , model = 28829} +models.sub[17626] = { name = "Auric Dagger" , model = 29189} +models.sub[17627] = { name = "Garuda's Dagger" , model = 28838} +models.sub[17628] = { name = "Behemoth Knife" , model = 28852} +models.sub[17629] = { name = "Behem. Knife +1" , model = 28852} +models.sub[17630] = { name = "Hawker's Knife" , model = 28833} +models.sub[17631] = { name = "Hawker's Knife +1" , model = 28833} +models.sub[17632] = { name = "Colichemarde +1" , model = 28853} +models.sub[17633] = { name = "Rapier +1" , model = 28859} +models.sub[17634] = { name = "Wasp Fleuret" , model = 28865} +models.sub[17635] = { name = "Schwert +1" , model = 28864} +models.sub[17636] = { name = "Jagdplaute +1" , model = 28941} +models.sub[17637] = { name = "Wing Sword +1" , model = 28960} +models.sub[17638] = { name = "Katzbalger +1" , model = 28947} +models.sub[17639] = { name = "Cutlass +1" , model = 28935} +models.sub[17640] = { name = "Ptm. Cutlass +1" , model = 28933} +models.sub[17641] = { name = "Gold Sword +1" , model = 28922} +models.sub[17642] = { name = "Hanger +1" , model = 28930} +models.sub[17643] = { name = "Honor Sword" , model = 28924} +models.sub[17644] = { name = "Judge's Sword" , model = 29062} +models.sub[17645] = { name = "Espadon +1" , model = 28953} +models.sub[17646] = { name = "Carnage Sword" , model = 28939} +models.sub[17647] = { name = "Aramis's Rapier" , model = 28859} +models.sub[17648] = { name = "Dragvandil" , model = 28952} +models.sub[17649] = { name = "Nightmare Sword" , model = 28939} +models.sub[17650] = { name = "Nadrs" , model = 28954} +models.sub[17651] = { name = "Dainslaif" , model = 28944} +models.sub[17652] = { name = "Joyeuse" , model = 28857} +models.sub[17653] = { name = "Hrotti" , model = 28950} +models.sub[17654] = { name = "Sapara of Trials" , model = 28927} +models.sub[17655] = { name = "Snr.Msk. Scimitar" , model = 28933} +models.sub[17656] = { name = "Verdun +1" , model = 28857} +models.sub[17657] = { name = "Anelace +1" , model = 28946} +models.sub[17658] = { name = "Tutelary" , model = 28856} +models.sub[17659] = { name = "Seiryu's Sword" , model = 28931} +models.sub[17660] = { name = "Kilij" , model = 29047} +models.sub[17661] = { name = "Storm Scimitar" , model = 28954} +models.sub[17662] = { name = "Company Sword" , model = 28953} +models.sub[17663] = { name = "Kilij +1" , model = 29047} +models.sub[17664] = { name = "Firmament" , model = 28949} +models.sub[17665] = { name = "Ifrit's Blade" , model = 28927} +models.sub[17666] = { name = "Jr.Msk. Tuck +1" , model = 28856} +models.sub[17667] = { name = "Jr.Msk. Tuck +2" , model = 28856} +models.sub[17668] = { name = "Firmament +1" , model = 28949} +models.sub[17669] = { name = "Sagasinger" , model = 29200} +models.sub[17670] = { name = "T.K. Sword +1" , model = 28923} +models.sub[17671] = { name = "T.K. Sword +2" , model = 28923} +models.sub[17672] = { name = "Bastokan Sword" , model = 28943} +models.sub[17673] = { name = "Republic Sword" , model = 28943} +models.sub[17674] = { name = "Cmb.Cst.Scmtr. +1" , model = 28929} +models.sub[17675] = { name = "Cmb.Cst.Scmtr. +2" , model = 28929} +models.sub[17676] = { name = "T.M. Espadon +1" , model = 28952} +models.sub[17677] = { name = "T.M. Espadon +2" , model = 28952} +models.sub[17678] = { name = "San d'Orian Sword" , model = 28937} +models.sub[17679] = { name = "Kingdom Sword" , model = 28937} +models.sub[17680] = { name = "Msk. Sword +1" , model = 28860} +models.sub[17681] = { name = "Msk. Sword +2" , model = 28860} +models.sub[17682] = { name = "Sacred Sword" , model = 28958} +models.sub[17683] = { name = "Sacred Degen" , model = 28861} +models.sub[17684] = { name = "Griffinclaw" , model = 28922} +models.sub[17685] = { name = "Lex Talionis" , model = 28856} +models.sub[17686] = { name = "Spark Bilbo" , model = 28856} +models.sub[17687] = { name = "Spark Bilbo +1" , model = 28856} +models.sub[17688] = { name = "Spark Degen" , model = 28861} +models.sub[17689] = { name = "Spark Degen +1" , model = 28861} +models.sub[17690] = { name = "Spark Rapier" , model = 28859} +models.sub[17691] = { name = "Spark Rapier +1" , model = 28859} +models.sub[17692] = { name = "Platoon Spatha" , model = 28921} +models.sub[17693] = { name = "Grudge Sword" , model = 28924} +models.sub[17694] = { name = "Guespiere" , model = 28858} +models.sub[17695] = { name = "Bayard's Sword" , model = 28945} +models.sub[17696] = { name = "Buzzard Tuck" , model = 28856} +models.sub[17697] = { name = "Mighty Talwar" , model = 28929} +models.sub[17698] = { name = "Princely Sword" , model = 28950} +models.sub[17699] = { name = "Dissector" , model = 28957} +models.sub[17700] = { name = "Durandal" , model = 28949} +models.sub[17701] = { name = "Shotel" , model = 29030} +models.sub[17702] = { name = "Shotel +1" , model = 29030} +models.sub[17703] = { name = "Pealing Anelace" , model = 28946} +models.sub[17704] = { name = "Vulcan Sword" , model = 28940} +models.sub[17705] = { name = "Vulcan Degen" , model = 28860} +models.sub[17706] = { name = "Vulcan Blade" , model = 28935} +models.sub[17707] = { name = "Martial Anelace" , model = 28946} +models.sub[17708] = { name = "Auriga Xiphos" , model = 28936} +models.sub[17709] = { name = "Swan Bilbo" , model = 28853} +models.sub[17710] = { name = "Justice Sword" , model = 28926} +models.sub[17711] = { name = "Shiva's Shotel" , model = 29030} +models.sub[17712] = { name = "Kaskara +1" , model = 28950} +models.sub[17713] = { name = "Macuahuitl" , model = 29053} +models.sub[17714] = { name = "Macuahuitl +1" , model = 29053} +models.sub[17715] = { name = "Storm Tulwar" , model = 28929} +models.sub[17716] = { name = "Macuahuitl -1" , model = 29053} +models.sub[17717] = { name = "Immortal's Scimitar" , model = 28954} +models.sub[17718] = { name = "Leech Scimitar" , model = 28928} +models.sub[17719] = { name = "Mensur Epee" , model = 28865} +models.sub[17720] = { name = "Company Fleuret" , model = 28863} +models.sub[17721] = { name = "Sanguine Sword" , model = 29062} +models.sub[17722] = { name = "Phantom Fleuret" , model = 28863} +models.sub[17723] = { name = "Singh Kilij" , model = 29047} +models.sub[17724] = { name = "Darksteel Kilij" , model = 29054} +models.sub[17725] = { name = "Darksteel Kilij +1" , model = 29054} +models.sub[17726] = { name = "Immortal's Shotel" , model = 29030} +models.sub[17727] = { name = "Adaman Kilij" , model = 29056} +models.sub[17728] = { name = "Adaman Kilij +1" , model = 29056} +models.sub[17729] = { name = "Vermin Slayer" , model = 29054} +models.sub[17730] = { name = "Insect Slayer" , model = 29054} +models.sub[17731] = { name = "Aquan Slayer" , model = 29054} +models.sub[17732] = { name = "Marine Slayer" , model = 29054} +models.sub[17733] = { name = "Dragon Slayer" , model = 29056} +models.sub[17734] = { name = "Wyrm Slayer" , model = 29056} +models.sub[17735] = { name = "Demon Slayer" , model = 29056} +models.sub[17736] = { name = "Devil Slayer" , model = 29056} +models.sub[17737] = { name = "Corsair's Scimitar" , model = 28928} +models.sub[17738] = { name = "Hauteclaire" , model = 29071} +models.sub[17739] = { name = "Steel Kilij" , model = 29074} +models.sub[17740] = { name = "Steel Kilij +1" , model = 29074} +models.sub[17741] = { name = "Perdu Hanger" , model = 28930} +models.sub[17742] = { name = "Vorpal Sword" , model = 28863} +models.sub[17743] = { name = "Wightslayer" , model = 29047} +models.sub[17744] = { name = "Brave Blade" , model = 28953} +models.sub[17745] = { name = "Hofud" , model = 29076} +models.sub[17746] = { name = "Cermet Kilij" , model = 29074} +models.sub[17747] = { name = "Cermet Kilij +1" , model = 29074} +models.sub[17748] = { name = "Ibushi Shinai" , model = 29084} +models.sub[17749] = { name = "Ibushi Shinai +1" , model = 29084} +models.sub[17750] = { name = "Anthos Xiphos" , model = 28936} +models.sub[17751] = { name = "Fragarach" , model = 29103} +models.sub[17753] = { name = "Organics" , model = 29117} +models.sub[17754] = { name = "Sylphid Epee" , model = 28862} +models.sub[17755] = { name = "Beast Slayer" , model = 29074} +models.sub[17756] = { name = "Sinfender" , model = 28928} +models.sub[17757] = { name = "Merveilleuse" , model = 28922} +models.sub[17758] = { name = "Ruler" , model = 28925} +models.sub[17759] = { name = "Koggelmander" , model = 28938} +models.sub[17760] = { name = "Buc. Scimitar" , model = 28930} +models.sub[17761] = { name = "Oberon's Rapier" , model = 28859} +models.sub[17762] = { name = "Erlking's Sword" , model = 28947} +models.sub[17763] = { name = "Erlking's Blade" , model = 28932} +models.sub[17764] = { name = "Trainee Sword" , model = 28925} +models.sub[17765] = { name = "Concordia" , model = 29132} +models.sub[17766] = { name = "Lyft Scimitar" , model = 28927} +models.sub[17767] = { name = "Chipped Scimitar" , model = 28928} +models.sub[17768] = { name = "Yoto +1" , model = 28982} +models.sub[17769] = { name = "Kororito +1" , model = 28982} +models.sub[17770] = { name = "Mamushito +1" , model = 28982} +models.sub[17771] = { name = "Anju" , model = 28987} +models.sub[17772] = { name = "Zushio" , model = 28983} +models.sub[17773] = { name = "Kodachi of Trials" , model = 28983} +models.sub[17774] = { name = "Shiranui" , model = 28985} +models.sub[17775] = { name = "Fukuro" , model = 28986} +models.sub[17776] = { name = "Hibari" , model = 28987} +models.sub[17777] = { name = "Hibari +1" , model = 28987} +models.sub[17778] = { name = "Muketsu" , model = 28984} +models.sub[17779] = { name = "Muketsu +1" , model = 28984} +models.sub[17780] = { name = "Kyofu" , model = 28982} +models.sub[17781] = { name = "Kyofu +1" , model = 28982} +models.sub[17782] = { name = "Reppu" , model = 28983} +models.sub[17783] = { name = "Reppu +1" , model = 28983} +models.sub[17784] = { name = "Keppu" , model = 28984} +models.sub[17785] = { name = "Keppu +1" , model = 28984} +models.sub[17786] = { name = "Ganko" , model = 28986} +models.sub[17787] = { name = "Ohaguro" , model = 28986} +models.sub[17788] = { name = "Sairen" , model = 28984} +models.sub[17789] = { name = "Unsho" , model = 28984} +models.sub[17790] = { name = "Unji" , model = 28984} +models.sub[17791] = { name = "Rai Kunimitsu" , model = 28983} +models.sub[17792] = { name = "Nikkariaoe" , model = 28984} +models.sub[17793] = { name = "Senjuinrikio" , model = 28985} +models.sub[17794] = { name = "Niokiyotsuna" , model = 28983} +models.sub[17795] = { name = "Sai" , model = 29039} +models.sub[17796] = { name = "Sai +1" , model = 29039} +models.sub[17797] = { name = "Seito" , model = 28982} +models.sub[17798] = { name = "Shamo" , model = 28985} +models.sub[17799] = { name = "Imanotsurugi" , model = 29043} +models.sub[17924] = { name = "Tungi" , model = 28763} +models.sub[17925] = { name = "Fransisca" , model = 28763} +models.sub[17926] = { name = "Acha d'Armas" , model = 28753} +models.sub[17927] = { name = "Lohar" , model = 28758} +models.sub[17928] = { name = "Juggernaut" , model = 28763} +models.sub[17929] = { name = "Bastokan Axe" , model = 28750} +models.sub[17930] = { name = "Republic Axe" , model = 28750} +models.sub[17931] = { name = "Cmb.Cst. Axe +1" , model = 28755} +models.sub[17932] = { name = "Cmb.Cst. Axe +2" , model = 28755} +models.sub[17933] = { name = "Pick of Trials" , model = 28762} +models.sub[17934] = { name = "Rsv.Cpt. Pick" , model = 28758} +models.sub[17935] = { name = "Tabarzin +1" , model = 28753} +models.sub[17936] = { name = "De Saintre's Axe" , model = 28748} +models.sub[17937] = { name = "Leopard Axe" , model = 28749} +models.sub[17938] = { name = "Woodville's Axe" , model = 28755} +models.sub[17939] = { name = "Kriegsbeil" , model = 28763} +models.sub[17940] = { name = "Military Pick" , model = 28760} +models.sub[17941] = { name = "Mighty Pick" , model = 28759} +models.sub[17942] = { name = "Tomahawk" , model = 29025} +models.sub[17943] = { name = "Tomahawk +1" , model = 29025} +models.sub[17944] = { name = "Retributor" , model = 29025} +models.sub[17945] = { name = "Martial Axe" , model = 28748} +models.sub[17946] = { name = "Maneater" , model = 28754} +models.sub[17947] = { name = "Garde Pick" , model = 28761} +models.sub[17948] = { name = "Temperance Axe" , model = 28757} +models.sub[17949] = { name = "Furnace Tabarzin" , model = 28753} +models.sub[17950] = { name = "Marid Ancus" , model = 28758} +models.sub[17951] = { name = "Storm Tabar" , model = 28754} +models.sub[17952] = { name = "Sirius Axe" , model = 29059} +models.sub[17953] = { name = "Zoraal Ja's Axe" , model = 29025} +models.sub[17954] = { name = "Jolt Axe" , model = 28748} +models.sub[17955] = { name = "Plain Pick" , model = 28760} +models.sub[17956] = { name = "Double Axe" , model = 28756} +models.sub[17957] = { name = "Navy Axe" , model = 28751} +models.sub[17958] = { name = "Iron Ram Pick" , model = 28760} +models.sub[17959] = { name = "Viperine Pick" , model = 28760} +models.sub[17960] = { name = "Labrys" , model = 29105} +models.sub[17961] = { name = "Lion Tamer" , model = 28760} +models.sub[17962] = { name = "Fleetwing" , model = 28756} +models.sub[17963] = { name = "Rainmaker" , model = 29025} +models.sub[17964] = { name = "Barkborer" , model = 28762} +models.sub[17965] = { name = "Sirocco Axe" , model = 28751} +models.sub[17966] = { name = "Erlking's Tabar" , model = 28754} +models.sub[17967] = { name = "Felling Axe" , model = 28749} +models.sub[17968] = { name = "Veldt Axe" , model = 28749} +models.sub[17969] = { name = "Fendoir" , model = 28748} +models.sub[17970] = { name = "Lyft Tabar" , model = 28753} +models.sub[17971] = { name = "Tartaglia" , model = 28751} +models.sub[17972] = { name = "San. Dagger" , model = 28839} +models.sub[17973] = { name = "Kingdom Dagger" , model = 28839} +models.sub[17974] = { name = "Bastokan Dagger" , model = 28839} +models.sub[17975] = { name = "Republic Dagger" , model = 28839} +models.sub[17976] = { name = "Windurstian Knife" , model = 28832} +models.sub[17977] = { name = "Federation Knife" , model = 28832} +models.sub[17978] = { name = "Windurstian Kukri" , model = 28844} +models.sub[17979] = { name = "Federation Kukri" , model = 28844} +models.sub[17980] = { name = "Hornetneedle" , model = 28835} +models.sub[17981] = { name = "Bano del Sol" , model = 28849} +models.sub[17982] = { name = "Kard" , model = 28989} +models.sub[17983] = { name = "Valiant Knife" , model = 28829} +models.sub[17984] = { name = "Spark Dagger" , model = 28838} +models.sub[17985] = { name = "Spark Dagger +1" , model = 28838} +models.sub[17986] = { name = "Spark Baselard" , model = 28842} +models.sub[17987] = { name = "Spark Baselard +1" , model = 28842} +models.sub[17988] = { name = "Spark Kris" , model = 28850} +models.sub[17989] = { name = "Spark Kris +1" , model = 28850} +models.sub[17990] = { name = "Cmb.Cst.Dagger +1" , model = 28849} +models.sub[17991] = { name = "Cmb.Cst.Dagger +2" , model = 28849} +models.sub[17992] = { name = "Triton's Dagger" , model = 28851} +models.sub[17993] = { name = "Platoon Dagger" , model = 28837} +models.sub[17994] = { name = "Calveley's Dagger" , model = 29067} +models.sub[17995] = { name = "Jongleur's Dagger" , model = 28836} +models.sub[17996] = { name = "Stylet" , model = 28841} +models.sub[17997] = { name = "Argent Dagger" , model = 29018} +models.sub[17998] = { name = "Thanatos Baselard" , model = 28840} +models.sub[17999] = { name = "Taillefer's Dagger" , model = 28851} +models.sub[18000] = { name = "Mighty Knife" , model = 28830} +models.sub[18001] = { name = "Harpe" , model = 29026} +models.sub[18002] = { name = "Perseus's Harpe" , model = 29026} +models.sub[18003] = { name = "Swordbreaker" , model = 28847} +models.sub[18004] = { name = "Trailer's Kukri" , model = 28846} +models.sub[18005] = { name = "Heart Snatcher" , model = 28847} +models.sub[18006] = { name = "Hoplites Harpe" , model = 29026} +models.sub[18007] = { name = "Chiroptera Dagger" , model = 29018} +models.sub[18008] = { name = "Hushed Dagger" , model = 28837} +models.sub[18009] = { name = "Martial Knife" , model = 28830} +models.sub[18010] = { name = "Melt Dagger" , model = 28839} +models.sub[18011] = { name = "Melt Knife" , model = 28833} +models.sub[18012] = { name = "Melt Baselard" , model = 28842} +models.sub[18013] = { name = "Melt Kukri" , model = 28845} +models.sub[18014] = { name = "Odorous Knife" , model = 28989} +models.sub[18015] = { name = "Blau Dolch" , model = 28835} +models.sub[18016] = { name = "Odorous Knife +1" , model = 28989} +models.sub[18017] = { name = "Asn. Jambiya" , model = 29051} +models.sub[18018] = { name = "Sirocco Kukri" , model = 28843} +models.sub[18019] = { name = "X's Knife" , model = 28852} +models.sub[18020] = { name = "Mercurial Kris" , model = 28850} +models.sub[18021] = { name = "Titan's Baselarde" , model = 28841} +models.sub[18022] = { name = "Adaman Kris +1" , model = 28849} +models.sub[18023] = { name = "Jambiya" , model = 29051} +models.sub[18024] = { name = "Jambiya +1" , model = 29051} +models.sub[18025] = { name = "Khanjar" , model = 28849} +models.sub[18026] = { name = "Magnet Knife" , model = 28830} +models.sub[18027] = { name = "Palladium Dagger" , model = 29067} +models.sub[18028] = { name = "Matron's Knife" , model = 29068} +models.sub[18029] = { name = "Piercing Dagger" , model = 28837} +models.sub[18030] = { name = "Khimaira Jambiya" , model = 29070} +models.sub[18031] = { name = "Amir Jambiya" , model = 29070} +models.sub[18032] = { name = "Adder Jambiya" , model = 29070} +models.sub[18033] = { name = "Adder Jambiya +1" , model = 29070} +models.sub[18034] = { name = "Dancing Dagger" , model = 29018} +models.sub[18035] = { name = "Deathbone Knife" , model = 28852} +models.sub[18266] = { name = "Relic Dagger" , model = 28835} +models.sub[18267] = { name = "Malefic Dagger" , model = 28835} +models.sub[18268] = { name = "Dynamis Dagger" , model = 28835} +models.sub[18269] = { name = "Batardeau" , model = 28835} +models.sub[18270] = { name = "Mandau" , model = 29006} +models.sub[18271] = { name = "Mandau" , model = 29006} +models.sub[18272] = { name = "Relic Sword" , model = 28941} +models.sub[18273] = { name = "Glyptic Sword" , model = 28941} +models.sub[18274] = { name = "Dynamis Sword" , model = 28941} +models.sub[18275] = { name = "Caliburn" , model = 28941} +models.sub[18276] = { name = "Excalibur" , model = 28992} +models.sub[18277] = { name = "Excalibur" , model = 28992} +models.sub[18284] = { name = "Relic Axe" , model = 28763} +models.sub[18285] = { name = "Leonine Axe" , model = 28763} +models.sub[18286] = { name = "Dynamis Axe" , model = 28763} +models.sub[18287] = { name = "Ogre Killer" , model = 28763} +models.sub[18288] = { name = "Guttler" , model = 29019} +models.sub[18289] = { name = "Guttler" , model = 29019} +models.sub[18308] = { name = "Ihintanto" , model = 28981} +models.sub[18309] = { name = "Mimizuku" , model = 28981} +models.sub[18310] = { name = "Rogetsu" , model = 28981} +models.sub[18311] = { name = "Yoshimitsu" , model = 28981} +models.sub[18312] = { name = "Kikoku" , model = 29016} +models.sub[18313] = { name = "Kikoku" , model = 29016} +models.sub[18320] = { name = "Relic Maul" , model = 28786} +models.sub[18321] = { name = "Battering Maul" , model = 28786} +models.sub[18322] = { name = "Dynamis Maul" , model = 28786} +models.sub[18323] = { name = "Gullintani" , model = 28786} +models.sub[18324] = { name = "Mjollnir" , model = 28979} +models.sub[18325] = { name = "Mjollnir" , model = 28979} +models.sub[18390] = { name = "Templar Hammer" , model = 28785} +models.sub[18391] = { name = "Sacred Mace" , model = 28779} +models.sub[18392] = { name = "Sacred Maul" , model = 28788} +models.sub[18393] = { name = "Sacred Wand" , model = 28900} +models.sub[18394] = { name = "Pilgrim's Wand" , model = 28914} +models.sub[18395] = { name = "Seawolf Cudgel" , model = 28772} +models.sub[18396] = { name = "Sea Rob. Cudgel" , model = 28773} +models.sub[18397] = { name = "Prudence Rod" , model = 29008} +models.sub[18398] = { name = "Raphael's Rod" , model = 28912} +models.sub[18399] = { name = "Charm Wand" , model = 29045} +models.sub[18400] = { name = "Charm Wand +1" , model = 29045} +models.sub[18401] = { name = "Moogle Rod" , model = 29046} +models.sub[18402] = { name = "Mana Wand" , model = 28904} +models.sub[18403] = { name = "High Mana Wand" , model = 28903} +models.sub[18404] = { name = "Ramuh's Mace" , model = 29032} +models.sub[18405] = { name = "Jadagna" , model = 29052} +models.sub[18406] = { name = "Jadagna +1" , model = 29052} +models.sub[18407] = { name = "Imperial Wand" , model = 28917} +models.sub[18408] = { name = "Yigit Bulawa" , model = 29032} +models.sub[18409] = { name = "Jadagna -1" , model = 29052} +models.sub[18410] = { name = "Melt Katana" , model = 28982} +models.sub[18411] = { name = "Buboso" , model = 28986} +models.sub[18412] = { name = "Gassan" , model = 28984} +models.sub[18413] = { name = "Hirenjaku" , model = 29043} +models.sub[18414] = { name = "Hirenjaku +1" , model = 29043} +models.sub[18415] = { name = "Tojaku" , model = 29043} +models.sub[18416] = { name = "Karasuageha" , model = 28986} +models.sub[18417] = { name = "Sayosamonji" , model = 28983} +models.sub[18418] = { name = "Otori" , model = 29039} +models.sub[18419] = { name = "Kugui" , model = 29039} +models.sub[18420] = { name = "Hayabusa" , model = 29066} +models.sub[18421] = { name = "Hayabusa +1" , model = 29066} +models.sub[18422] = { name = "Ryumon" , model = 29061} +models.sub[18423] = { name = "Izayoi" , model = 29072} +models.sub[18424] = { name = "Izayoi +1" , model = 29072} +models.sub[18425] = { name = "Perdu Blade" , model = 29066} +models.sub[18426] = { name = "Sasuke Katana" , model = 29061} +models.sub[18427] = { name = "Hanafubuki" , model = 28984} +models.sub[18428] = { name = "Kogitsunemaru" , model = 29072} +models.sub[18429] = { name = "Shusui" , model = 29111} +models.sub[18430] = { name = "Oninohocho" , model = 29119} +models.sub[18531] = { name = "Veldt Axe +1" , model = 28749} +models.sub[18532] = { name = "Cleofun Axe" , model = 28763} +models.sub[18533] = { name = "Magnus Axe" , model = 28753} +models.sub[18534] = { name = "Charmer's Merlin" , model = 28753} +models.sub[18535] = { name = "Carabinier's Axe" , model = 28750} +models.sub[18536] = { name = "Artio's Axe" , model = 28750} +models.sub[18537] = { name = "Maiden Tabar" , model = 28754} +models.sub[18538] = { name = "Maiden Tabar +1" , model = 28754} +models.sub[18539] = { name = "Tonatiuh Axe" , model = 29263} +models.sub[18540] = { name = "Barbican Axe" , model = 28761} +models.sub[18541] = { name = "Tjukurrpa Axe" , model = 28754} +models.sub[18542] = { name = "Aytanri" , model = 29263} +models.sub[18543] = { name = "Breidox" , model = 28754} +models.sub[18544] = { name = "Breidox +1" , model = 28754} +models.sub[18545] = { name = "Ark Tabar" , model = 29259} +models.sub[18546] = { name = "Gibbous Axe" , model = 29203} +models.sub[18547] = { name = "Ravana's Axe" , model = 29272} +models.sub[18638] = { name = "Mandau" , model = 29006} +models.sub[18639] = { name = "Excalibur" , model = 28992} +models.sub[18641] = { name = "Guttler" , model = 29019} +models.sub[18645] = { name = "Kikoku" , model = 29016} +models.sub[18647] = { name = "Mjollnir" , model = 28979} +models.sub[18652] = { name = "Mandau" , model = 29006} +models.sub[18653] = { name = "Excalibur" , model = 28992} +models.sub[18655] = { name = "Guttler" , model = 29019} +models.sub[18659] = { name = "Kikoku" , model = 29006} +models.sub[18661] = { name = "Mjollnir" , model = 28979} +models.sub[18666] = { name = "Mandau" , model = 29006} +models.sub[18667] = { name = "Excalibur" , model = 28992} +models.sub[18669] = { name = "Guttler" , model = 29019} +models.sub[18673] = { name = "Kikoku" , model = 29016} +models.sub[18675] = { name = "Mjollnir" , model = 28979} +models.sub[18827] = { name = "Oxossi Facon" , model = 29269} +models.sub[18828] = { name = "Oxossi Facon +1" , model = 29269} +models.sub[18829] = { name = "Blustery Dagger" , model = 28847} +models.sub[18830] = { name = "Gusterion" , model = 28847} +models.sub[18841] = { name = "Templar Mace" , model = 28777} +models.sub[18842] = { name = "Nmd. Moogle Rod" , model = 29055} +models.sub[18843] = { name = "Flan Smasher" , model = 28775} +models.sub[18844] = { name = "Miracle Wand" , model = 29045} +models.sub[18845] = { name = "Miracle Wand +1" , model = 29045} +models.sub[18846] = { name = "Battledore" , model = 29069} +models.sub[18847] = { name = "Seveneyes" , model = 29031} +models.sub[18848] = { name = "Brass Jadagna" , model = 29073} +models.sub[18849] = { name = "Brass Jadagna +1" , model = 29073} +models.sub[18850] = { name = "Perdu Wand" , model = 28900} +models.sub[18851] = { name = "Werebuster" , model = 28783} +models.sub[18852] = { name = "Octave Club" , model = 28782} +models.sub[18853] = { name = "Spirit Maul" , model = 28788} +models.sub[18854] = { name = "Fourth Mace" , model = 28777} +models.sub[18855] = { name = "Trainee Hammer" , model = 28787} +models.sub[18856] = { name = "Deae Gratia" , model = 28774} +models.sub[18857] = { name = "Antares" , model = 29109} +models.sub[18858] = { name = "Flanged Mace" , model = 29118} +models.sub[18859] = { name = "Kerykeion" , model = 28905} +models.sub[18860] = { name = "Flanged Mace +1" , model = 29118} +models.sub[18861] = { name = "Grandeur" , model = 28913} +models.sub[18862] = { name = "Clearpath" , model = 28895} +models.sub[18863] = { name = "Dream Bell" , model = 29121} +models.sub[18864] = { name = "Dream Bell +1" , model = 29121} +models.sub[18865] = { name = "Zonure" , model = 29032} +models.sub[18866] = { name = "Club Hammer" , model = 29126} +models.sub[18867] = { name = "Daedalus Hammer" , model = 28785} +models.sub[18868] = { name = "Lady Bell" , model = 29128} +models.sub[18869] = { name = "Lady Bell +1" , model = 29128} +models.sub[18870] = { name = "Dweomer Maul" , model = 28784} +models.sub[18871] = { name = "Kitty Rod" , model = 28912} +models.sub[18872] = { name = "Lyft Ferule" , model = 28900} +models.sub[18873] = { name = "Brise-os" , model = 29073} +models.sub[18874] = { name = "Brise-os +1" , model = 29073} +models.sub[18875] = { name = "Vodun Mace" , model = 28775} +models.sub[18876] = { name = "Vodun Mace +1" , model = 28775} +models.sub[18877] = { name = "Robur Mace" , model = 28775} +models.sub[18878] = { name = "Robur Mace +1" , model = 28775} +models.sub[18879] = { name = "Rounsey Wand" , model = 29207} +models.sub[18880] = { name = "Maestro's Baton" , model = 29211} +models.sub[18881] = { name = "Melomane Mallet" , model = 29212} +models.sub[18882] = { name = "Beaivi's Scepter" , model = 28893} +models.sub[18883] = { name = "Luckitoo" , model = 29032} +models.sub[18884] = { name = "Vejovis Wand" , model = 28897} +models.sub[18885] = { name = "Vejovis Wand +1" , model = 28897} +models.sub[18886] = { name = "Dhyana Rod" , model = 29267} +models.sub[18887] = { name = "Dukkha" , model = 29267} +models.sub[18888] = { name = "Ankylosis Wand" , model = 29271} +models.sub[18891] = { name = "Hannibal's Sword" , model = 28957} +models.sub[18892] = { name = "Corbenic Sword" , model = 28941} +models.sub[18893] = { name = "Magnus Sword" , model = 28945} +models.sub[18894] = { name = "Accolade Sword" , model = 28953} +models.sub[18895] = { name = "Chimeric Fleuret" , model = 28865} +models.sub[18896] = { name = "Honorbound" , model = 29062} +models.sub[18897] = { name = "Isador" , model = 29074} +models.sub[18898] = { name = "Mageblade" , model = 28939} +models.sub[18899] = { name = "Runic Anelace" , model = 28946} +models.sub[18900] = { name = "Skeld Sword" , model = 28953} +models.sub[18901] = { name = "Falcata" , model = 28941} +models.sub[18902] = { name = "Falcata +1" , model = 28941} +models.sub[18903] = { name = "Talekeeper" , model = 29200} +models.sub[18904] = { name = "Ephemeron" , model = 29210} +models.sub[18905] = { name = "Swiftwing" , model = 28960} +models.sub[18906] = { name = "Galenus" , model = 28938} +models.sub[18907] = { name = "Devourer" , model = 28959} +models.sub[18908] = { name = "Dhampyr Sword" , model = 28947} +models.sub[18909] = { name = "Sanus Ensis" , model = 29254} +models.sub[18910] = { name = "Apaisante" , model = 28938} +models.sub[18911] = { name = "Apaisante +1" , model = 28938} +models.sub[18912] = { name = "Ark Saber" , model = 29256} +models.sub[18913] = { name = "Ark Sword" , model = 29257} +models.sub[18914] = { name = "Killer's Kilij" , model = 29056} +models.sub[18915] = { name = "Eradicator's Kilij" , model = 29056} +models.sub[18916] = { name = "Heimdall's Doom" , model = 29076} +models.sub[18969] = { name = "Terpsichore" , model = 29100} +models.sub[18973] = { name = "Yagrush" , model = 29087} +models.sub[18975] = { name = "Murgleis" , model = 29092} +models.sub[18976] = { name = "Vajra" , model = 29094} +models.sub[18977] = { name = "Burtgang" , model = 29098} +models.sub[18979] = { name = "Aymur" , model = 29085} +models.sub[18980] = { name = "Carnwenhan" , model = 29099} +models.sub[18983] = { name = "Nagi" , model = 29093} +models.sub[18986] = { name = "Tizona" , model = 29091} +models.sub[18989] = { name = "Terpsichore" , model = 29100} +models.sub[18993] = { name = "Yagrush" , model = 29087} +models.sub[18995] = { name = "Murgleis" , model = 29092} +models.sub[18996] = { name = "Vajra" , model = 29094} +models.sub[18997] = { name = "Burtgang" , model = 29098} +models.sub[18999] = { name = "Aymur" , model = 29085} +models.sub[19000] = { name = "Carnwenhan" , model = 29099} +models.sub[19003] = { name = "Nagi" , model = 29093} +models.sub[19006] = { name = "Tizona" , model = 29091} +models.sub[19062] = { name = "Yagrush" , model = 29087} +models.sub[19064] = { name = "Murgleis" , model = 29092} +models.sub[19065] = { name = "Vajra" , model = 29094} +models.sub[19066] = { name = "Burtgang" , model = 29098} +models.sub[19068] = { name = "Aymur" , model = 29085} +models.sub[19069] = { name = "Carnwenhan" , model = 29099} +models.sub[19072] = { name = "Nagi" , model = 29093} +models.sub[19075] = { name = "Tizona" , model = 29091} +models.sub[19078] = { name = "Terpsichore" , model = 29100} +models.sub[19082] = { name = "Yagrush" , model = 29087} +models.sub[19084] = { name = "Murgleis" , model = 29092} +models.sub[19085] = { name = "Vajra" , model = 29094} +models.sub[19086] = { name = "Burtgang" , model = 29098} +models.sub[19088] = { name = "Aymur" , model = 29085} +models.sub[19089] = { name = "Carnwenhan" , model = 29099} +models.sub[19092] = { name = "Nagi" , model = 29093} +models.sub[19095] = { name = "Tizona" , model = 29091} +models.sub[19098] = { name = "Terpsichore" , model = 29100} +models.sub[19100] = { name = "Cobra Knife" , model = 28852} +models.sub[19101] = { name = "Trainee Knife" , model = 28989} +models.sub[19102] = { name = "Main Gauche" , model = 28848} +models.sub[19103] = { name = "Darksteel Jambiya" , model = 29081} +models.sub[19104] = { name = "Dst. Jambiya +1" , model = 29081} +models.sub[19105] = { name = "Thug's Jambiya" , model = 29051} +models.sub[19106] = { name = "Thug's Jambiya +1" , model = 29051} +models.sub[19107] = { name = "Azoth" , model = 29102} +models.sub[19108] = { name = "Zareehkl Jambiya" , model = 29081} +models.sub[19109] = { name = "Trilling Dagger" , model = 28840} +models.sub[19110] = { name = "Trainee's Needle" , model = 28841} +models.sub[19111] = { name = "Silktone" , model = 28840} +models.sub[19112] = { name = "Farseer" , model = 28840} +models.sub[19113] = { name = "Ermine's Tail" , model = 29122} +models.sub[19114] = { name = "Galkan Dagger" , model = 28840} +models.sub[19115] = { name = "Fane Baselard" , model = 28840} +models.sub[19116] = { name = "Dweomer Knife" , model = 28830} +models.sub[19117] = { name = "Ogre Jambiya" , model = 29081} +models.sub[19118] = { name = "Machismo" , model = 29131} +models.sub[19119] = { name = "Ranging Knife" , model = 28852} +models.sub[19120] = { name = "Avis" , model = 29082} +models.sub[19121] = { name = "Sleight Kukri" , model = 28846} +models.sub[19122] = { name = "Courser's Pugio" , model = 28834} +models.sub[19123] = { name = "Cinquedea" , model = 28830} +models.sub[19124] = { name = "Creve-coeur" , model = 29051} +models.sub[19125] = { name = "Lyft Jambiya" , model = 29051} +models.sub[19126] = { name = "Papilio Kirpan" , model = 29081} +models.sub[19127] = { name = "Ranging Knife +1" , model = 28852} +models.sub[19128] = { name = "Edgeless Knife" , model = 28832} +models.sub[19129] = { name = "Rapidus Sax" , model = 28851} +models.sub[19130] = { name = "Clement Skean" , model = 28835} +models.sub[19131] = { name = "Magnus Dagger" , model = 28835} +models.sub[19132] = { name = "Twilight Knife" , model = 29199} +models.sub[19133] = { name = "Triplus Dagger" , model = 28849} +models.sub[19134] = { name = "Felibre's Dague" , model = 28830} +models.sub[19135] = { name = "Acinaces" , model = 29051} +models.sub[19136] = { name = "Phurba" , model = 28834} +models.sub[19137] = { name = "Angr Harpe" , model = 29026} +models.sub[19138] = { name = "Verus Knife" , model = 28830} +models.sub[19139] = { name = "Verus Knife +1" , model = 28830} +models.sub[19140] = { name = "Mantodea Harpe" , model = 29205} +models.sub[19141] = { name = "Oneiros Knife" , model = 28830} +models.sub[19142] = { name = "Gnadgott" , model = 28840} +models.sub[19143] = { name = "Lux Pugio" , model = 29206} +models.sub[19144] = { name = "Coruscanti" , model = 29208} +models.sub[19145] = { name = "Asteria" , model = 29213} +models.sub[19146] = { name = "Supernal Knife" , model = 29067} +models.sub[19147] = { name = "Janamaraka" , model = 29051} +models.sub[19148] = { name = "Pugiunculus" , model = 28840} +models.sub[19149] = { name = "Strategema Knife" , model = 28829} +models.sub[19271] = { name = "Osoraku" , model = 28985} +models.sub[19272] = { name = "Yagentoshiro" , model = 28984} +models.sub[19273] = { name = "Onishibari" , model = 29066} +models.sub[19274] = { name = "Trainee Burin" , model = 28987} +models.sub[19275] = { name = "Tsukumo" , model = 28986} +models.sub[19276] = { name = "Midare" , model = 28984} +models.sub[19277] = { name = "Tsugumi" , model = 28987} +models.sub[19278] = { name = "Fuchingiri" , model = 28981} +models.sub[19279] = { name = "Musanto" , model = 28983} +models.sub[19280] = { name = "Narigitsune" , model = 28981} +models.sub[19281] = { name = "Midare +1" , model = 28984} +models.sub[19282] = { name = "Hochomasamune" , model = 29194} +models.sub[19283] = { name = "Rusty Kunai" , model = 28987} +models.sub[19284] = { name = "Hiwa" , model = 28986} +models.sub[19285] = { name = "Kakko" , model = 29072} +models.sub[19286] = { name = "Kakko +1" , model = 29072} +models.sub[19287] = { name = "Kamome" , model = 28986} +models.sub[19288] = { name = "Sekirei" , model = 28984} +models.sub[19289] = { name = "Toki" , model = 28982} +models.sub[19290] = { name = "Aizenkunitoshi" , model = 28985} +models.sub[19291] = { name = "Oirandori" , model = 29066} +models.sub[19292] = { name = "Kogara" , model = 28986} +models.sub[19293] = { name = "Ichi-an" , model = 28984} +models.sub[19294] = { name = "Ichi-an +1" , model = 28984} +models.sub[19295] = { name = "Mujin Tanto" , model = 28985} +models.sub[19296] = { name = "Ban" , model = 28987} +models.sub[19297] = { name = "Kakesu" , model = 28985} +models.sub[19298] = { name = "Ikarigiri" , model = 29261} +models.sub[19299] = { name = "Aisa" , model = 28985} +models.sub[19300] = { name = "Aisa +1" , model = 28985} +models.sub[19301] = { name = "Kawasemi" , model = 29072} +models.sub[19302] = { name = "Uguisu" , model = 29277} +models.sub[19332] = { name = "Peeler" , model = 28831} +models.sub[19333] = { name = "Renegade" , model = 28833} +models.sub[19334] = { name = "Kartika" , model = 29082} +models.sub[19335] = { name = "Athame" , model = 28848} +models.sub[19336] = { name = "Dakini" , model = 28852} +models.sub[19337] = { name = "Side-sword" , model = 28940} +models.sub[19338] = { name = "Schiavona" , model = 28942} +models.sub[19339] = { name = "Nobilis" , model = 28949} +models.sub[19340] = { name = "Antea" , model = 28955} +models.sub[19341] = { name = "Soulsaber" , model = 28925} +models.sub[19347] = { name = "Chopper" , model = 28763} +models.sub[19348] = { name = "Splinter" , model = 28755} +models.sub[19349] = { name = "Bonebiter" , model = 28754} +models.sub[19350] = { name = "Punisher" , model = 28760} +models.sub[19351] = { name = "Skeggiold" , model = 28750} +models.sub[19367] = { name = "Kibashiri" , model = 28982} +models.sub[19368] = { name = "Koruri" , model = 28984} +models.sub[19369] = { name = "Mozu" , model = 28985} +models.sub[19370] = { name = "Isatu" , model = 29039} +models.sub[19371] = { name = "Kuina" , model = 28984} +models.sub[19377] = { name = "Stenz" , model = 28785} +models.sub[19378] = { name = "Rageblow" , model = 28787} +models.sub[19379] = { name = "Culacula" , model = 28788} +models.sub[19380] = { name = "Goedendag" , model = 28775} +models.sub[19381] = { name = "Ingrimm" , model = 28915} +models.sub[19398] = { name = "Twashtar" , model = 29137} +models.sub[19399] = { name = "Almace" , model = 29138} +models.sub[19401] = { name = "Farsha" , model = 29140} +models.sub[19405] = { name = "Kannagi" , model = 29185} +models.sub[19407] = { name = "Gambanteinn" , model = 29187} +models.sub[19416] = { name = "Daka" , model = 29051} +models.sub[19417] = { name = "Parazonium" , model = 28848} +models.sub[19418] = { name = "Kila" , model = 28852} +models.sub[19419] = { name = "Fusetto" , model = 28840} +models.sub[19420] = { name = "Badelaire" , model = 28949} +models.sub[19421] = { name = "Khanda" , model = 28955} +models.sub[19422] = { name = "Shamshir" , model = 28925} +models.sub[19423] = { name = "Machaera" , model = 29053} +models.sub[19428] = { name = "Alard's Axe" , model = 28754} +models.sub[19429] = { name = "Richardet's Axe" , model = 28760} +models.sub[19430] = { name = "Guichard's Axe" , model = 28750} +models.sub[19431] = { name = "Renaud's Axe" , model = 28750} +models.sub[19444] = { name = "Tobi" , model = 28985} +models.sub[19445] = { name = "Enchu" , model = 29039} +models.sub[19446] = { name = "Sekka" , model = 28984} +models.sub[19447] = { name = "Uzura" , model = 28982} +models.sub[19452] = { name = "Canne de Combat" , model = 28788} +models.sub[19453] = { name = "Naboot" , model = 28775} +models.sub[19454] = { name = "Hoeroa" , model = 28916} +models.sub[19455] = { name = "Makhila" , model = 28783} +models.sub[19457] = { name = "Twashtar" , model = 29137} +models.sub[19458] = { name = "Almace" , model = 29138} +models.sub[19460] = { name = "Farsha" , model = 29140} +models.sub[19464] = { name = "Kannagi" , model = 29185} +models.sub[19466] = { name = "Gambanteinn" , model = 29187} +models.sub[19474] = { name = "Daka +1" , model = 29051} +models.sub[19475] = { name = "Parazonium +1" , model = 28848} +models.sub[19476] = { name = "Kila +1" , model = 28852} +models.sub[19477] = { name = "Fusetto +1" , model = 28840} +models.sub[19478] = { name = "Badelaire +1" , model = 28949} +models.sub[19479] = { name = "Khanda +1" , model = 28955} +models.sub[19480] = { name = "Shamshir +1" , model = 28925} +models.sub[19481] = { name = "Machaera +1" , model = 29053} +models.sub[19486] = { name = "Alard's Axe +1" , model = 28754} +models.sub[19487] = { name = "Richardet's Axe +1" , model = 28760} +models.sub[19488] = { name = "Guichard's Axe +1" , model = 28750} +models.sub[19489] = { name = "Renaud's Axe +1" , model = 28750} +models.sub[19502] = { name = "Tobi +1" , model = 28985} +models.sub[19503] = { name = "Enchu +1" , model = 29039} +models.sub[19504] = { name = "Sekka +1" , model = 28984} +models.sub[19505] = { name = "Uzura +1" , model = 28982} +models.sub[19510] = { name = "Canne de Cbt. +1" , model = 28788} +models.sub[19511] = { name = "Naboot +1" , model = 28775} +models.sub[19512] = { name = "Hoeroa +1" , model = 28916} +models.sub[19513] = { name = "Makhila +1" , model = 28783} +models.sub[19535] = { name = "Twashtar" , model = 29137} +models.sub[19536] = { name = "Almace" , model = 29138} +models.sub[19538] = { name = "Farsha" , model = 29140} +models.sub[19542] = { name = "Kannagi" , model = 29185} +models.sub[19544] = { name = "Gambanteinn" , model = 29187} +models.sub[19552] = { name = "Daka +2" , model = 29051} +models.sub[19553] = { name = "Parazonium +2" , model = 28848} +models.sub[19554] = { name = "Kila +2" , model = 28852} +models.sub[19555] = { name = "Fusetto +2" , model = 28840} +models.sub[19556] = { name = "Badelaire +2" , model = 28949} +models.sub[19557] = { name = "Khanda +2" , model = 28955} +models.sub[19558] = { name = "Shamshir +2" , model = 28925} +models.sub[19559] = { name = "Machaera +2" , model = 29053} +models.sub[19564] = { name = "Alard's Axe +2" , model = 28754} +models.sub[19565] = { name = "Richard. Axe +2" , model = 28760} +models.sub[19566] = { name = "Guichard's Axe +2" , model = 28750} +models.sub[19567] = { name = "Renaud's Axe +2" , model = 28750} +models.sub[19580] = { name = "Tobi +2" , model = 28985} +models.sub[19581] = { name = "Enchu +2" , model = 29039} +models.sub[19582] = { name = "Sekka +2" , model = 28984} +models.sub[19583] = { name = "Uzura +2" , model = 28982} +models.sub[19588] = { name = "Canne de Cbt. +2" , model = 28788} +models.sub[19589] = { name = "Naboot +2" , model = 28775} +models.sub[19590] = { name = "Hoeroa +2" , model = 28916} +models.sub[19591] = { name = "Makhila +2" , model = 28783} +models.sub[19614] = { name = "Yagrush" , model = 29087} +models.sub[19616] = { name = "Murgleis" , model = 29092} +models.sub[19617] = { name = "Vajra" , model = 29094} +models.sub[19618] = { name = "Burtgang" , model = 29098} +models.sub[19620] = { name = "Aymur" , model = 29085} +models.sub[19621] = { name = "Carnwenhan" , model = 29099} +models.sub[19624] = { name = "Nagi" , model = 29093} +models.sub[19627] = { name = "Tizona" , model = 29091} +models.sub[19630] = { name = "Terpsichore" , model = 29100} +models.sub[19633] = { name = "Twashtar" , model = 29137} +models.sub[19634] = { name = "Almace" , model = 29138} +models.sub[19636] = { name = "Farsha" , model = 29140} +models.sub[19640] = { name = "Kannagi" , model = 29185} +models.sub[19642] = { name = "Gambanteinn" , model = 29187} +models.sub[19650] = { name = "Daka +3" , model = 29051} +models.sub[19651] = { name = "Parazonium +3" , model = 28848} +models.sub[19652] = { name = "Kila +3" , model = 28852} +models.sub[19653] = { name = "Fusetto +3" , model = 28840} +models.sub[19654] = { name = "Badelaire +3" , model = 28949} +models.sub[19655] = { name = "Khanda +3" , model = 28955} +models.sub[19656] = { name = "Shamshir +3" , model = 28925} +models.sub[19657] = { name = "Machaera +3" , model = 29053} +models.sub[19662] = { name = "Alard's Axe +3" , model = 28754} +models.sub[19663] = { name = "Richard. Axe +3" , model = 28760} +models.sub[19664] = { name = "Guichard's Axe +3" , model = 28750} +models.sub[19665] = { name = "Renaud's Axe +3" , model = 28750} +models.sub[19678] = { name = "Tobi +3" , model = 28985} +models.sub[19679] = { name = "Enchu +3" , model = 29039} +models.sub[19680] = { name = "Sekka +3" , model = 28984} +models.sub[19681] = { name = "Uzura +3" , model = 28982} +models.sub[19686] = { name = "Canne de Cbt. +3" , model = 28788} +models.sub[19687] = { name = "Naboot +3" , model = 28775} +models.sub[19688] = { name = "Hoeroa +3" , model = 28916} +models.sub[19689] = { name = "Makhila +3" , model = 28783} +models.sub[19712] = { name = "Yagrush" , model = 29087} +models.sub[19714] = { name = "Murgleis" , model = 29092} +models.sub[19715] = { name = "Vajra" , model = 29094} +models.sub[19716] = { name = "Burtgang" , model = 29098} +models.sub[19718] = { name = "Aymur" , model = 29085} +models.sub[19719] = { name = "Carnwenhan" , model = 29099} +models.sub[19722] = { name = "Nagi" , model = 29093} +models.sub[19725] = { name = "Tizona" , model = 29091} +models.sub[19728] = { name = "Terpsichore" , model = 29100} +models.sub[19747] = { name = "Mandau" , model = 29006} +models.sub[19748] = { name = "Excalibur" , model = 28992} +models.sub[19750] = { name = "Guttler" , model = 29019} +models.sub[19754] = { name = "Kikoku" , model = 29016} +models.sub[19756] = { name = "Mjollnir" , model = 28979} +models.sub[19788] = { name = "Gorkhali Kukri" , model = 28844} +models.sub[19789] = { name = "Mahakali's Kukri" , model = 28844} +models.sub[19806] = { name = "Twashtar" , model = 29137} +models.sub[19807] = { name = "Almace" , model = 29138} +models.sub[19809] = { name = "Farsha" , model = 29140} +models.sub[19813] = { name = "Kannagi" , model = 29185} +models.sub[19815] = { name = "Gambanteinn" , model = 29187} +models.sub[19821] = { name = "Yagrush" , model = 29087} +models.sub[19823] = { name = "Murgleis" , model = 29092} +models.sub[19824] = { name = "Vajra" , model = 29094} +models.sub[19825] = { name = "Burtgang" , model = 29098} +models.sub[19827] = { name = "Aymur" , model = 29085} +models.sub[19828] = { name = "Carnwenhan" , model = 29099} +models.sub[19831] = { name = "Nagi" , model = 29093} +models.sub[19834] = { name = "Tizona" , model = 29091} +models.sub[19837] = { name = "Terpsichore" , model = 29100} +models.sub[19840] = { name = "Mandau" , model = 29216} +models.sub[19841] = { name = "Excalibur" , model = 29217} +models.sub[19843] = { name = "Guttler" , model = 29219} +models.sub[19847] = { name = "Kikoku" , model = 29223} +models.sub[19849] = { name = "Mjollnir" , model = 29225} +models.sub[19854] = { name = "Twashtar" , model = 29243} +models.sub[19855] = { name = "Almace" , model = 29244} +models.sub[19857] = { name = "Farsha" , model = 29246} +models.sub[19861] = { name = "Kannagi" , model = 29250} +models.sub[19863] = { name = "Gambanteinn" , model = 29252} +models.sub[19871] = { name = "Khandroma" , model = 29070} +models.sub[19872] = { name = "Praxidikai" , model = 28847} +models.sub[19873] = { name = "Thokcha" , model = 28852} +models.sub[19874] = { name = "Centovente" , model = 28840} +models.sub[19875] = { name = "Brunello" , model = 28947} +models.sub[19876] = { name = "Khadga" , model = 28955} +models.sub[19877] = { name = "Shikargar" , model = 28922} +models.sub[19878] = { name = "Thibron" , model = 29053} +models.sub[19883] = { name = "Sacripante" , model = 28753} +models.sub[19884] = { name = "Ganelon" , model = 28759} +models.sub[19885] = { name = "Astolfo" , model = 28756} +models.sub[19886] = { name = "Fernagu" , model = 28750} +models.sub[19899] = { name = "Kasasagi" , model = 29043} +models.sub[19900] = { name = "Majimun" , model = 29039} +models.sub[19901] = { name = "Arisui" , model = 28984} +models.sub[19902] = { name = "Hitaki" , model = 28982} +models.sub[19907] = { name = "Rose Couverte" , model = 28786} +models.sub[19908] = { name = "Tahtib" , model = 28774} +models.sub[19909] = { name = "Tutunui" , model = 28920} +models.sub[19910] = { name = "Ukaldi" , model = 28782} +models.sub[19950] = { name = "Yagrush" , model = 29228} +models.sub[19952] = { name = "Murgleis" , model = 29230} +models.sub[19953] = { name = "Vajra" , model = 29231} +models.sub[19954] = { name = "Burtgang" , model = 29232} +models.sub[19956] = { name = "Aymur" , model = 29234} +models.sub[19957] = { name = "Carnwenhan" , model = 29235} +models.sub[19960] = { name = "Nagi" , model = 29237} +models.sub[19963] = { name = "Tizona" , model = 29240} +models.sub[19966] = { name = "Terpsichore" , model = 29241} +models.sub[20555] = { name = "Mandau" , model = 29006} +models.sub[20556] = { name = "Mandau" , model = 29216} +models.sub[20557] = { name = "Terpsichore" , model = 29100} +models.sub[20558] = { name = "Terpsichore" , model = 29241} +models.sub[20559] = { name = "Vajra" , model = 29094} +models.sub[20560] = { name = "Vajra" , model = 29231} +models.sub[20561] = { name = "Carnwenhan" , model = 29099} +models.sub[20562] = { name = "Carnwenhan" , model = 29235} +models.sub[20563] = { name = "Twashtar" , model = 29137} +models.sub[20564] = { name = "Twashtar" , model = 29243} +models.sub[20573] = { name = "Aern Dagger" , model = 29498} +models.sub[20576] = { name = "Qutrub Knife" , model = 29503} +models.sub[20577] = { name = "Chicken Knife II" , model = 29456} +models.sub[20579] = { name = "Skinflayer" , model = 29102} +models.sub[20580] = { name = "Kustawi" , model = 28829} +models.sub[20581] = { name = "Kustawi +1" , model = 28829} +models.sub[20583] = { name = "Mandau" , model = 29216} +models.sub[20584] = { name = "Terpsichore" , model = 29241} +models.sub[20585] = { name = "Vajra" , model = 29231} +models.sub[20586] = { name = "Carnwenhan" , model = 29235} +models.sub[20587] = { name = "Twashtar" , model = 29243} +models.sub[20592] = { name = "Sangoma" , model = 29430} +models.sub[20594] = { name = "Aeneas" , model = 29432} +models.sub[20595] = { name = "Malevolence" , model = 29213} +models.sub[20596] = { name = "Taming Sari" , model = 29300} +models.sub[20597] = { name = "Enchufla" , model = 29122} +models.sub[20598] = { name = "Shijo" , model = 29068} +models.sub[20599] = { name = "Kali" , model = 29189} +models.sub[20600] = { name = "Nibiru Knife" , model = 29404} +models.sub[20601] = { name = "Blurred Knife" , model = 29131} +models.sub[20602] = { name = "Blurred Knife +1" , model = 29131} +models.sub[20603] = { name = "Ternion Dagger" , model = 28840} +models.sub[20604] = { name = "Ternion Dagger +1" , model = 28840} +models.sub[20605] = { name = "Odium" , model = 29403} +models.sub[20606] = { name = "Anathema Harpe" , model = 29205} +models.sub[20607] = { name = "Anathema Harpe +1" , model = 29205} +models.sub[20608] = { name = "Jugo Kukri" , model = 28843} +models.sub[20609] = { name = "Jugo Kukri +1" , model = 28843} +models.sub[20610] = { name = "Rhadamanthus" , model = 29396} +models.sub[20611] = { name = "Sangarius" , model = 28959} +models.sub[20612] = { name = "Sangarius +1" , model = 28959} +models.sub[20613] = { name = "Pukulatmuj" , model = 28940} +models.sub[20614] = { name = "Pukulatmuj +1" , model = 28940} +models.sub[20615] = { name = "Levante Dagger" , model = 28838} +models.sub[20616] = { name = "Ipetam" , model = 29382} +models.sub[20617] = { name = "Homestead Dagger" , model = 28838} +models.sub[20618] = { name = "Sandung" , model = 29269} +models.sub[20619] = { name = "Polyhymnia" , model = 29122} +models.sub[20620] = { name = "Sabebus" , model = 28848} +models.sub[20621] = { name = "Nanti Knife" , model = 28852} +models.sub[20622] = { name = "Nanti Knife +1" , model = 28852} +models.sub[20623] = { name = "Leisilonu +2" , model = 28851} +models.sub[20624] = { name = "Eminent Dagger" , model = 28835} +models.sub[20625] = { name = "Secespita" , model = 28847} +models.sub[20626] = { name = "Blitto Needle" , model = 28835} +models.sub[20627] = { name = "Surcouf's Jambiya" , model = 29051} +models.sub[20628] = { name = "Mindmeld Kris" , model = 29018} +models.sub[20629] = { name = "Legato Dagger" , model = 29213} +models.sub[20630] = { name = "Atoyac" , model = 29287} +models.sub[20631] = { name = "Khandroma -1" , model = 29070} +models.sub[20632] = { name = "Vanir Knife" , model = 28830} +models.sub[20633] = { name = "Cama. Dagger" , model = 29300} +models.sub[20634] = { name = "Leisilonu +1" , model = 28851} +models.sub[20635] = { name = "Forefront Dagger" , model = 28838} +models.sub[20636] = { name = "Izhiikoh" , model = 29287} +models.sub[20637] = { name = "Aphotic Kukri" , model = 28843} +models.sub[20638] = { name = "Coalition Dirk" , model = 29278} +models.sub[20639] = { name = "Oxidant Baselard" , model = 28842} +models.sub[20640] = { name = "Nitric Baselard" , model = 28842} +models.sub[20641] = { name = "Leisilonu" , model = 28851} +models.sub[20642] = { name = "Tzustes Knife +1" , model = 28832} +models.sub[20643] = { name = "Macoquetza" , model = 29287} +models.sub[20644] = { name = "Tzustes Knife" , model = 28832} +models.sub[20645] = { name = "Excalibur" , model = 28992} +models.sub[20646] = { name = "Excalibur" , model = 29217} +models.sub[20647] = { name = "Murgleis" , model = 29092} +models.sub[20648] = { name = "Murgleis" , model = 29230} +models.sub[20649] = { name = "Burtgang" , model = 29098} +models.sub[20650] = { name = "Burtgang" , model = 29232} +models.sub[20651] = { name = "Tizona" , model = 29091} +models.sub[20652] = { name = "Tizona" , model = 29240} +models.sub[20653] = { name = "Almace" , model = 29138} +models.sub[20654] = { name = "Almace" , model = 29244} +models.sub[20665] = { name = "Kam'lanaut's Sword" , model = 29479} +models.sub[20666] = { name = "Blizzard Brand" , model = 29454} +models.sub[20667] = { name = "Blizzard Brand +1" , model = 29454} +models.sub[20668] = { name = "Firetongue" , model = 29455} +models.sub[20669] = { name = "Firetongue +1" , model = 29455} +models.sub[20674] = { name = "Aern Sword" , model = 29497} +models.sub[20677] = { name = "Colada" , model = 29062} +models.sub[20678] = { name = "Firangi" , model = 29117} +models.sub[20679] = { name = "Tanmogayi" , model = 29030} +models.sub[20680] = { name = "Tanmogayi +1" , model = 29030} +models.sub[20681] = { name = "Flyssa" , model = 29071} +models.sub[20682] = { name = "Flyssa +1" , model = 29071} +models.sub[20683] = { name = "Zantetsuken" , model = 29076} +models.sub[20685] = { name = "Excalibur" , model = 29217} +models.sub[20686] = { name = "Murgleis" , model = 29230} +models.sub[20687] = { name = "Burtgang" , model = 29232} +models.sub[20688] = { name = "Tizona" , model = 29240} +models.sub[20689] = { name = "Almace" , model = 29244} +models.sub[20690] = { name = "Reikiko" , model = 29443} +models.sub[20694] = { name = "Fermion Sword" , model = 29428} +models.sub[20695] = { name = "Sequence" , model = 29433} +models.sub[20696] = { name = "Combuster" , model = 28950} +models.sub[20697] = { name = "Combuster +1" , model = 28950} +models.sub[20698] = { name = "Fettering Blade" , model = 29429} +models.sub[20699] = { name = "Koboto" , model = 28931} +models.sub[20700] = { name = "Nixxer" , model = 29071} +models.sub[20701] = { name = "Iris" , model = 29103} +models.sub[20702] = { name = "Emissary" , model = 28922} +models.sub[20703] = { name = "Deacon Saber" , model = 29256} +models.sub[20704] = { name = "Deacon Sword" , model = 29257} +models.sub[20705] = { name = "Brilliance" , model = 29422} +models.sub[20706] = { name = "Vampirism" , model = 29424} +models.sub[20707] = { name = "Medeina Kilij" , model = 29074} +models.sub[20708] = { name = "Demersal Degen" , model = 28857} +models.sub[20709] = { name = "Demers. Degen +1" , model = 28857} +models.sub[20710] = { name = "Nibiru Blade" , model = 29405} +models.sub[20711] = { name = "Blurred Sword" , model = 29132} +models.sub[20712] = { name = "Blurred Sword +1" , model = 29132} +models.sub[20713] = { name = "Excalipoor" , model = 29401} +models.sub[20714] = { name = "Excalipoor II" , model = 29401} +models.sub[20715] = { name = "Acclimator" , model = 29397} +models.sub[20716] = { name = "Perfervid Sword" , model = 28927} +models.sub[20717] = { name = "Arendsi Fleuret" , model = 28864} +models.sub[20718] = { name = "Claidheamh Soluis" , model = 29383} +models.sub[20719] = { name = "Homestead Blade" , model = 28934} +models.sub[20720] = { name = "Egeking" , model = 28926} +models.sub[20721] = { name = "Mimesis" , model = 28954} +models.sub[20722] = { name = "Usonmunku" , model = 28939} +models.sub[20723] = { name = "Dija Sword" , model = 28939} +models.sub[20724] = { name = "Dija Sword +1" , model = 28939} +models.sub[20725] = { name = "Iztaasu +2" , model = 29190} +models.sub[20726] = { name = "Eminent Scimitar" , model = 28930} +models.sub[20727] = { name = "Tabahi Fleuret" , model = 28864} +models.sub[20728] = { name = "Kheshig Blade" , model = 28953} +models.sub[20729] = { name = "Vivifiante" , model = 28958} +models.sub[20730] = { name = "Predatrice" , model = 29056} +models.sub[20731] = { name = "Xiutleato" , model = 29288} +models.sub[20732] = { name = "Brunello -1" , model = 28947} +models.sub[20733] = { name = "Anahera Saber" , model = 29256} +models.sub[20734] = { name = "Anahera Sword" , model = 29257} +models.sub[20735] = { name = "Cama. Blade" , model = 29301} +models.sub[20736] = { name = "Iztaasu +1" , model = 29190} +models.sub[20737] = { name = "Forefront Blade" , model = 28934} +models.sub[20738] = { name = "Buramenk'ah" , model = 29288} +models.sub[20739] = { name = "Halachuinic Sword" , model = 28956} +models.sub[20740] = { name = "Camatlatia" , model = 29288} +models.sub[20741] = { name = "Coalition Blade" , model = 29279} +models.sub[20742] = { name = "Iztaasu" , model = 29190} +models.sub[20743] = { name = "Bihkah Sword +1" , model = 28942} +models.sub[20744] = { name = "Bihkah Sword" , model = 28942} +models.sub[20790] = { name = "Guttler" , model = 29019} +models.sub[20791] = { name = "Guttler" , model = 29219} +models.sub[20792] = { name = "Aymur" , model = 29085} +models.sub[20793] = { name = "Aymur" , model = 29234} +models.sub[20794] = { name = "Farsha" , model = 29140} +models.sub[20795] = { name = "Farsha" , model = 29246} +models.sub[20796] = { name = "Purgation" , model = 29059} +models.sub[20797] = { name = "Skullrender" , model = 29263} +models.sub[20798] = { name = "Deacon Tabar" , model = 29259} +models.sub[20799] = { name = "Mdomo Axe" , model = 29025} +models.sub[20800] = { name = "Mdomo Axe +1" , model = 29025} +models.sub[20801] = { name = "Nibiru Tabar" , model = 29407} +models.sub[20802] = { name = "Blurred Axe" , model = 29415} +models.sub[20803] = { name = "Blurred Axe +1" , model = 29415} +models.sub[20804] = { name = "Perun" , model = 28763} +models.sub[20805] = { name = "Perun +1" , model = 28763} +models.sub[20806] = { name = "Buramgh" , model = 28755} +models.sub[20807] = { name = "Buramgh +1" , model = 28755} +models.sub[20808] = { name = "Tramontane Axe" , model = 28753} +models.sub[20809] = { name = "Kumbhakarna" , model = 29385} +models.sub[20810] = { name = "Homestead Axe" , model = 28755} +models.sub[20811] = { name = "Arktoi" , model = 29272} +models.sub[20812] = { name = "Izizoeksi" , model = 29293} +models.sub[20813] = { name = "Emxgha" , model = 28759} +models.sub[20814] = { name = "Budliqa" , model = 28762} +models.sub[20815] = { name = "Budliqa +1" , model = 28762} +models.sub[20816] = { name = "Faizzeer +2" , model = 29059} +models.sub[20817] = { name = "Eminent Axe" , model = 28754} +models.sub[20818] = { name = "Hurlbat" , model = 28763} +models.sub[20819] = { name = "Antican Axe" , model = 28754} +models.sub[20820] = { name = "Hatxiik" , model = 29289} +models.sub[20821] = { name = "Sacripante -1" , model = 28753} +models.sub[20822] = { name = "Anahera Tabar" , model = 29259} +models.sub[20823] = { name = "Cama. Axe" , model = 29303} +models.sub[20824] = { name = "Faizzeer +1" , model = 29059} +models.sub[20825] = { name = "Forefront Axe" , model = 28755} +models.sub[20826] = { name = "Hunahpu" , model = 29293} +models.sub[20827] = { name = "Kerehcatl" , model = 29289} +models.sub[20828] = { name = "Brethren Axe" , model = 28763} +models.sub[20829] = { name = "Icoyoca" , model = 29289} +models.sub[20830] = { name = "Coalition Axe" , model = 29281} +models.sub[20831] = { name = "Aalak' Axe" , model = 28756} +models.sub[20832] = { name = "Aalak' Axe +1" , model = 28756} +models.sub[20833] = { name = "Faizzeer" , model = 29059} +models.sub[20970] = { name = "Kikoku" , model = 29016} +models.sub[20971] = { name = "Kikoku" , model = 29223} +models.sub[20972] = { name = "Nagi" , model = 29093} +models.sub[20973] = { name = "Nagi" , model = 29237} +models.sub[20974] = { name = "Kannagi" , model = 29185} +models.sub[20975] = { name = "Kannagi" , model = 29250} +models.sub[20977] = { name = "Heishi Shorinken" , model = 29439} +models.sub[20978] = { name = "Ochu" , model = 29285} +models.sub[20979] = { name = "Aizushintogo" , model = 29111} +models.sub[20980] = { name = "Raicho" , model = 29072} +models.sub[20981] = { name = "Raicho +1" , model = 29072} +models.sub[20982] = { name = "Shuhansadamune" , model = 29194} +models.sub[20983] = { name = "Mijin" , model = 29404} +models.sub[20984] = { name = "Kujaku" , model = 29418} +models.sub[20985] = { name = "Kujaku +1" , model = 29418} +models.sub[20986] = { name = "Achiuchikapu" , model = 29399} +models.sub[20987] = { name = "Tancho" , model = 28984} +models.sub[20988] = { name = "Tancho +1" , model = 28984} +models.sub[20989] = { name = "Izuna" , model = 29389} +models.sub[20990] = { name = "Jushimatsu" , model = 29381} +models.sub[20991] = { name = "Chidori" , model = 28981} +models.sub[20992] = { name = "Taikogane" , model = 29381} +models.sub[20993] = { name = "Senkutanto" , model = 29285} +models.sub[20994] = { name = "Shigi" , model = 29277} +models.sub[20995] = { name = "Isuka" , model = 28984} +models.sub[20996] = { name = "Kannakiri +2" , model = 29119} +models.sub[20997] = { name = "Raimitsukane" , model = 28985} +models.sub[20998] = { name = "Kaitsuburi" , model = 29066} +models.sub[20999] = { name = "Habukatana" , model = 28982} +models.sub[21000] = { name = "Magorokuhocho" , model = 28981} +models.sub[21001] = { name = "Kasasagi -1" , model = 28985} +models.sub[21003] = { name = "Cama. Katana" , model = 28982} +models.sub[21004] = { name = "Kannakiri +1" , model = 29119} +models.sub[21005] = { name = "Kiji" , model = 28986} +models.sub[21006] = { name = "Pamun" , model = 29039} +models.sub[21007] = { name = "Pamun +1" , model = 29039} +models.sub[21008] = { name = "Kotekirigo" , model = 28984} +models.sub[21009] = { name = "Nakajimarai" , model = 28982} +models.sub[21010] = { name = "Nakajimarai +1" , model = 28982} +models.sub[21011] = { name = "Enju" , model = 28985} +models.sub[21012] = { name = "Enju +1" , model = 28985} +models.sub[21013] = { name = "Kannakiri" , model = 29119} +models.sub[21014] = { name = "Ichijintanto" , model = 29285} +models.sub[21060] = { name = "Mjollnir" , model = 28979} +models.sub[21061] = { name = "Mjollnir" , model = 29225} +models.sub[21062] = { name = "Yagrush" , model = 29087} +models.sub[21063] = { name = "Yagrush" , model = 29228} +models.sub[21064] = { name = "Gambanteinn" , model = 29187} +models.sub[21065] = { name = "Gambanteinn" , model = 29252} +models.sub[21066] = { name = "Trial Wand" , model = 29305} +models.sub[21067] = { name = "Nodal Wand" , model = 29305} +models.sub[21068] = { name = "Nodal Wand" , model = 29305} +models.sub[21069] = { name = "Nodal Wand" , model = 29305} +models.sub[21070] = { name = "Idris" , model = 29379} +models.sub[21072] = { name = "Gada" , model = 29109} +models.sub[21073] = { name = "Izcalli" , model = 28787} +models.sub[21074] = { name = "Kupo Rod" , model = 29046} +models.sub[21075] = { name = "Septoptic" , model = 29031} +models.sub[21076] = { name = "Septoptic +1" , model = 29031} +models.sub[21077] = { name = "Mjollnir" , model = 29225} +models.sub[21078] = { name = "Yagrush" , model = 29228} +models.sub[21079] = { name = "Gambanteinn" , model = 29252} +models.sub[21080] = { name = "Idris" , model = 29379} +models.sub[21082] = { name = "Tishtrya" , model = 29441} +models.sub[21083] = { name = "Sucellus" , model = 29008} +models.sub[21084] = { name = "Queller Rod" , model = 28912} +models.sub[21085] = { name = "Solstice" , model = 29271} +models.sub[21086] = { name = "Heartstopper" , model = 29427} +models.sub[21087] = { name = "Heartstopper +1" , model = 29427} +models.sub[21088] = { name = "Divinity" , model = 29423} +models.sub[21089] = { name = "Rubicundity" , model = 29425} +models.sub[21090] = { name = "Loxotic Mace" , model = 28775} +models.sub[21091] = { name = "Loxotic Mace +1" , model = 28775} +models.sub[21092] = { name = "Nibiru Cudgel" , model = 29413} +models.sub[21093] = { name = "Blurred Rod" , model = 29420} +models.sub[21094] = { name = "Blurred Rod +1" , model = 29420} +models.sub[21095] = { name = "Heartbeater" , model = 29400} +models.sub[21096] = { name = "Heartbeater +1" , model = 29400} +models.sub[21097] = { name = "Leafkin Bopper" , model = 29395} +models.sub[21098] = { name = "Leafkin Bopper +1" , model = 29395} +models.sub[21099] = { name = "Magesmasher" , model = 28785} +models.sub[21100] = { name = "Magesmasher +1" , model = 28785} +models.sub[21101] = { name = "Herkuleskeule" , model = 29032} +models.sub[21102] = { name = "Mafic Cudgel" , model = 28772} +models.sub[21103] = { name = "Vadose Rod" , model = 28893} +models.sub[21104] = { name = "Eosuchus Club" , model = 28782} +models.sub[21105] = { name = "Nehushtan" , model = 29391} +models.sub[21107] = { name = "Kyuka Uchiwa" , model = 29380} +models.sub[21108] = { name = "Kyuka Uchiwa +1" , model = 29380} +models.sub[21109] = { name = "Homestead Wand" , model = 28904} +models.sub[21110] = { name = "Sindri" , model = 28784} +models.sub[21111] = { name = "Bolelabunga" , model = 29299} +models.sub[21112] = { name = "Gabaxorea" , model = 28898} +models.sub[21113] = { name = "P. Sprig. Club" , model = 29309} +models.sub[21114] = { name = "R. Sprig. Club" , model = 29307} +models.sub[21115] = { name = "Aedold +2" , model = 29118} +models.sub[21116] = { name = "Cagliostro's Rod" , model = 28912} +models.sub[21117] = { name = "Hagoita" , model = 29069} +models.sub[21118] = { name = "G. Spriggan Club" , model = 29308} +models.sub[21119] = { name = "Eminent Wand" , model = 28900} +models.sub[21120] = { name = "Patriarch Cane" , model = 28913} +models.sub[21121] = { name = "Rose Couverte -1" , model = 28786} +models.sub[21122] = { name = "Mes'yohi Rod" , model = 28892} +models.sub[21123] = { name = "Cama. Wand" , model = 29283} +models.sub[21124] = { name = "Dowser's Wand" , model = 28920} +models.sub[21125] = { name = "Tamaxchi" , model = 29299} +models.sub[21126] = { name = "Aedold +1" , model = 29118} +models.sub[21127] = { name = "Forefront Wand" , model = 28904} +models.sub[21128] = { name = "Mondaha Cudgel" , model = 28773} +models.sub[21129] = { name = "Sharur" , model = 29032} +models.sub[21130] = { name = "Sharur +1" , model = 29032} +models.sub[21131] = { name = "Coalition Rod" , model = 29283} +models.sub[21132] = { name = "Aedold" , model = 29118} +models.sub[21133] = { name = "Sasah Wand +1" , model = 29051} +models.sub[21134] = { name = "Sasah Wand" , model = 29051} +models.sub[21554] = { name = "Arasy Knife" , model = 28829} +models.sub[21555] = { name = "Arasy Knife +1" , model = 28829} +models.sub[21556] = { name = "Beryllium Kris" , model = 29018} +models.sub[21557] = { name = "Beryllium Kris +1" , model = 29018} +models.sub[21558] = { name = "Rune Kris" , model = 29018} +models.sub[21559] = { name = "Raetic Kris" , model = 29018} +models.sub[21560] = { name = "Raetic Kris +1" , model = 29018} +models.sub[21561] = { name = "Tokko Knife" , model = 28830} +models.sub[21562] = { name = "Ajja Knife" , model = 28829} +models.sub[21563] = { name = "Eletta Knife" , model = 29396} +models.sub[21564] = { name = "Kaja Knife" , model = 29508} +models.sub[21565] = { name = "Tauret" , model = 29519} +models.sub[21566] = { name = "Voluspa Knife" , model = 28830} +models.sub[21573] = { name = "Assassin's Knife" , model = 28829} +models.sub[21574] = { name = "Plun. Knife" , model = 28829} +models.sub[21575] = { name = "Gandring" , model = 29486} +models.sub[21576] = { name = "Bard's Knife" , model = 28829} +models.sub[21577] = { name = "Bihu Knife" , model = 28829} +models.sub[21578] = { name = "Barfawc" , model = 29486} +models.sub[21579] = { name = "Comm. Knife" , model = 28829} +models.sub[21580] = { name = "Lanun Knife" , model = 28829} +models.sub[21581] = { name = "Rostam" , model = 29486} +models.sub[21582] = { name = "Etoile Knife" , model = 28829} +models.sub[21583] = { name = "Horos Knife" , model = 28829} +models.sub[21584] = { name = "Setan Kober" , model = 29486} +models.sub[21604] = { name = "Arasy Sword" , model = 28950} +models.sub[21605] = { name = "Arasy Sword +1" , model = 28950} +models.sub[21606] = { name = "Enriching Sword" , model = 28922} +models.sub[21607] = { name = "Enr. Sword +1" , model = 28922} +models.sub[21608] = { name = "Onion Sword II" , model = 29459} +models.sub[21609] = { name = "Save the Queen II" , model = 29462} +models.sub[21610] = { name = "Hepatizon Rapier" , model = 28859} +models.sub[21611] = { name = "Hep. Rapier +1" , model = 28859} +models.sub[21612] = { name = "Raetic Blade" , model = 28926} +models.sub[21613] = { name = "Raetic Blade +1" , model = 28926} +models.sub[21614] = { name = "Hepatizon Sapara" , model = 28927} +models.sub[21615] = { name = "Hep. Sapara +1" , model = 28927} +models.sub[21617] = { name = "Tokko Sword" , model = 28939} +models.sub[21618] = { name = "Ajja Sword" , model = 28944} +models.sub[21619] = { name = "Eletta Sword" , model = 28960} +models.sub[21620] = { name = "Kaja Sword" , model = 29509} +models.sub[21621] = { name = "Naegling" , model = 29520} +models.sub[21622] = { name = "Voluspa Sword" , model = 28947} +models.sub[21625] = { name = "Duelist's Sword" , model = 28950} +models.sub[21626] = { name = "Vitiation Sword" , model = 28950} +models.sub[21627] = { name = "Crocea Mors" , model = 29491} +models.sub[21628] = { name = "Valor Sword" , model = 28950} +models.sub[21629] = { name = "Cabal. Sword" , model = 28950} +models.sub[21630] = { name = "Moralltach" , model = 29491} +models.sub[21631] = { name = "Mirage Sword" , model = 28950} +models.sub[21632] = { name = "Luhlaza Sword" , model = 28950} +models.sub[21633] = { name = "Zomorrodnegar" , model = 29491} +models.sub[21635] = { name = "Malignance Sword" , model = 28952} +models.sub[21704] = { name = "Arasy Tabar" , model = 28753} +models.sub[21705] = { name = "Arasy Tabar +1" , model = 28753} +models.sub[21706] = { name = "Barbarity" , model = 28763} +models.sub[21707] = { name = "Barbarity +1" , model = 28763} +models.sub[21708] = { name = "Beryllium Pick" , model = 28759} +models.sub[21709] = { name = "Beryllium Pick +1" , model = 28759} +models.sub[21710] = { name = "Raetic Axe" , model = 28757} +models.sub[21711] = { name = "Raetic Axe +1" , model = 28757} +models.sub[21712] = { name = "Voluspa Axe" , model = 28759} +models.sub[21715] = { name = "Monster Axe" , model = 28753} +models.sub[21716] = { name = "Ankusa Axe" , model = 28753} +models.sub[21717] = { name = "Pangu" , model = 29483} +models.sub[21718] = { name = "Tokko Axe" , model = 28754} +models.sub[21719] = { name = "Ajja Axe" , model = 28753} +models.sub[21720] = { name = "Eletta Axe" , model = 29263} +models.sub[21721] = { name = "Kaja Axe" , model = 29522} +models.sub[21722] = { name = "Dolichenus" , model = 29522} +models.sub[21741] = { name = "Demonic Axe" , model = 29465} +models.sub[21742] = { name = "Aern Axe" , model = 29499} +models.sub[21744] = { name = "Gramk's Axe" , model = 29502} +models.sub[21746] = { name = "Digirbalag" , model = 28754} +models.sub[21747] = { name = "Freydis" , model = 29191} +models.sub[21748] = { name = "Habilitator" , model = 29059} +models.sub[21749] = { name = "Habilitator +1" , model = 29059} +models.sub[21750] = { name = "Guttler" , model = 29219} +models.sub[21751] = { name = "Aymur" , model = 29234} +models.sub[21752] = { name = "Farsha" , model = 29246} +models.sub[21753] = { name = "Tri-edge" , model = 29435} +models.sub[21904] = { name = "Kanaria" , model = 29043} +models.sub[21905] = { name = "Taka" , model = 29277} +models.sub[21906] = { name = "Kikoku" , model = 29223} +models.sub[21907] = { name = "Nagi" , model = 29237} +models.sub[21908] = { name = "Kannagi" , model = 29250} +models.sub[21909] = { name = "Yoshikiri" , model = 29072} +models.sub[21910] = { name = "Yoshikiri +1" , model = 29072} +models.sub[21912] = { name = "Voluspa Katana" , model = 28985} +models.sub[21915] = { name = "Koga Shin." , model = 28985} +models.sub[21916] = { name = "Mochi. Shin." , model = 28985} +models.sub[21917] = { name = "Fudo Masamune" , model = 29488} +models.sub[21918] = { name = "Tokko Katana" , model = 28985} +models.sub[21919] = { name = "Ajja Katana" , model = 28981} +models.sub[21920] = { name = "Eletta Katana" , model = 29072} +models.sub[21921] = { name = "Kaja Katana" , model = 29515} +models.sub[21922] = { name = "Gokotai" , model = 29515} +models.sub[21923] = { name = "Debahocho" , model = 28984} +models.sub[21924] = { name = "Debahocho +1" , model = 28984} +models.sub[22004] = { name = "Soulflayer's Wand" , model = 29495} +models.sub[22006] = { name = "Voluspa Hammer" , model = 28784} +models.sub[22015] = { name = "Arasy Rod" , model = 28890} +models.sub[22016] = { name = "Arasy Rod +1" , model = 28890} +models.sub[22017] = { name = "Seika Uchiwa" , model = 29470} +models.sub[22018] = { name = "Seika Uchiwa +1" , model = 29470} +models.sub[22019] = { name = "Jingly Rod" , model = 29473} +models.sub[22020] = { name = "Jingly Rod +1" , model = 29473} +models.sub[22021] = { name = "Ames" , model = 28901} +models.sub[22022] = { name = "Ames +1" , model = 28901} +models.sub[22023] = { name = "Beryllium Mace" , model = 28775} +models.sub[22024] = { name = "Beryllium Mace +1" , model = 28775} +models.sub[22025] = { name = "Raetic Rod" , model = 29008} +models.sub[22026] = { name = "Raetic Rod +1" , model = 29008} +models.sub[22027] = { name = "Tokko Rod" , model = 28891} +models.sub[22028] = { name = "Ajja Rod" , model = 28890} +models.sub[22029] = { name = "Eletta Rod" , model = 28912} +models.sub[22030] = { name = "Kaja Rod" , model = 29517} +models.sub[22031] = { name = "Maxentius" , model = 29517} +models.sub[22033] = { name = "Cleric's Wand" , model = 28890} +models.sub[22034] = { name = "Piety Wand" , model = 28890} +models.sub[22035] = { name = "Asclepius" , model = 29490} +models.sub[22036] = { name = "Bagua Wand" , model = 28890} +models.sub[22037] = { name = "Sifang Wand" , model = 28890} +models.sub[22038] = { name = "Bhima" , model = 29490} +models.sub[22039] = { name = "Floral Hagoita" , model = 29507} \ No newline at end of file diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 08c0223c25..016f128219 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -41,7 +41,7 @@ slips.items = { [slips.storages[26]] = L{23063, 23130, 23197, 23264, 23331, 23064, 23131, 23198, 23265, 23332, 23065, 23132, 23199, 23266, 23333, 23066, 23133, 23200, 23267, 23334, 23067, 23134, 23201, 23268, 23335, 23068, 23135, 23202, 23269, 23336, 23069, 23136, 23203, 23270, 23337, 23070, 23137, 23204, 23271, 23338, 23071, 23138, 23205, 23272, 23339, 23072, 23139, 23206, 23273, 23340, 23073, 23140, 23207, 23274, 23341, 23074, 23141, 23208, 23275, 23342, 23075, 23142, 23209, 23276, 23343, 23076, 23143, 23210, 23277, 23344, 23077, 23144, 23211, 23278, 23345, 23078, 23145, 23212, 23279, 23346, 23079, 23146, 23213, 23280, 23347, 23080, 23147, 23214, 23281, 23348, 23081, 23148, 23215, 23282, 23349, 23082, 23149, 23216, 23283, 23350, 23083, 23150, 23217, 23284, 23351, 23084, 23151, 23218, 23285, 23352}, -- 110 [slips.storages[27]] = L{23398, 23465, 23532, 23599, 23666, 23399, 23466, 23533, 23600, 23667, 23400, 23467, 23534, 23601, 23668, 23401, 23468, 23535, 23602, 23669, 23402, 23469, 23536, 23603, 23670, 23403, 23470, 23537, 23604, 23671, 23404, 23471, 23538, 23605, 23672, 23405, 23472, 23539, 23606, 23673, 23406, 23473, 23540, 23607, 23674, 23407, 23474, 23541, 23608, 23675, 23408, 23475, 23542, 23609, 23676, 23409, 23476, 23543, 23610, 23677, 23410, 23477, 23544, 23611, 23678, 23411, 23478, 23545, 23612, 23679, 23412, 23479, 23546, 23613, 23680, 23413, 23480, 23547, 23614, 23681, 23414, 23481, 23548, 23615, 23682, 23415, 23482, 23549, 23616, 23683, 23416, 23483, 23550, 23617, 23684, 23417, 23484, 23551, 23618, 23685, 23418, 23485, 23552, 23619, 23686, 23419, 23486, 23553, 23620, 23687}, -- 110 [slips.storages[28]] = L{21515, 21561, 21617, 21670, 21718, 21775, 21826, 21879, 21918, 21971, 22027, 22082, 22108, 22214, 21516, 21562, 21618, 21671, 21719, 21776, 21827, 21880, 21919, 21972, 22028, 22083, 22109, 22215, 21517, 21563, 21619, 21672, 21720, 21777, 21828, 21881, 21920, 21973, 22029, 22084, 22110, 22216, 21518, 21564, 21620, 21673, 21721, 21778, 21829, 21882, 21921, 21974, 22030, 22085, 22111, 22217, 21519, 21565, 21621, 21674, 21722, 21779, 21830, 21883, 21922, 21975, 22031, 22086, 22107, 22218, 22089}, --71 - --[slips.storages[29]] = L{23085, 23152, 23219, 23286, 23353, 23086, 23153, 23220, 23287, 23354, 23087, 23154, 23221, 23288, 23355, 23088, 23155, 23222, 23289, 23356, 23089, 23156, 23223, 23290, 23357, 23090, 23157, 23224, 23291, 23358, 23091, 23158, 23225, 23292, 23359, 23092, 23159, 23226, 23293, 23360, 23093, 23160, 23227, 23294, 23361, 23094, 23161, 23228, 23295, 23362, 23095, 23162, 23229, 23363, 23096, 23163, 23230, 23297, 23364, 23097, 23164, 23231, 23298, 23365, 23098, 23165, 23232, 23299, 23366, 23099, 23166, 23233, 23300, 23367, 23100, 23167, 23234, 23301, 23368, 23101, 23168, 23235, 23302, 23369, 23102, 23169, 23236, 23303, 23370, 23103, 23170, 23237, 23304, 23371, 23104, 23171, 23238, 23305, 23372, 23105, 23172, 23239, 23306, 23373, 23106, 23173, 23240, 23307, 23374}, -- 110 + --[slips.storages[29]] = L{23085, 23152, 23219, 23286, 23353, 23086, 23153, 23220, 23287, 23354, 23087, 23154, 23221, 23288, 23355, 23088, 23155, 23222, 23289, 23356, 23089, 23156, 23223, 23290, 23357, 23090, 23157, 23224, 23291, 23358, 23091, 23158, 23225, 23292, 23359, 23092, 23159, 23226, 23293, 23360, 23093, 23160, 23227, 23294, 23361, 23094, 23161, 23228, 23295, 23362, 23095, 23162, 23229, 23296, 23363, 23096, 23163, 23230, 23297, 23364, 23097, 23164, 23231, 23298, 23365, 23098, 23165, 23232, 23299, 23366, 23099, 23166, 23233, 23300, 23367, 23100, 23167, 23234, 23301, 23368, 23101, 23168, 23235, 23302, 23369, 23102, 23169, 23236, 23303, 23370, 23103, 23170, 23237, 23304, 23371, 23104, 23171, 23238, 23305, 23372, 23105, 23172, 23239, 23306, 23373, 23106, 23173, 23240, 23307, 23374}, -- 110 } function slips.get_slip_id(n) From c002be72b777771496eafc6dc9ea7ed4df5fb9df Mon Sep 17 00:00:00 2001 From: Byrth Date: Mon, 12 Sep 2022 07:35:15 -0400 Subject: [PATCH 0870/1002] digger messages updates --- addons/digger/messages.lua | 120 ++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/addons/digger/messages.lua b/addons/digger/messages.lua index db2e57c019..e9599e2916 100644 --- a/addons/digger/messages.lua +++ b/addons/digger/messages.lua @@ -1,61 +1,61 @@ messages = {} -messages[2] = {bayld=7376, ease=7368, fail=7293, full=7291, notes=7375, points=7373, standing=7374, success=6390} -messages[4] = {bayld=7370, ease=7362, fail=7287, full=7285, notes=7369, points=7367, standing=7368, success=6390} -messages[5] = {bayld=7327, ease=7319, fail=7244, full=7242, notes=7326, points=7324, standing=7325, success=6403} -messages[7] = {bayld=7321, ease=7313, fail=7238, full=7236, notes=7320, points=7318, standing=7319, success=6390} -messages[24] = {bayld=7657, ease=7649, fail=7574, full=7572, notes=7656, points=7654, standing=7655, success=6390} -messages[25] = {bayld=7177, ease=7169, fail=7094, full=7092, notes=7176, points=7174, standing=7175, success=6390} -messages[51] = {bayld=7152, ease=7144, fail=7069, full=7067, notes=7151, points=7149, standing=7150, success=6390} -messages[52] = {bayld=7152, ease=7144, fail=7069, full=7067, notes=7151, points=7149, standing=7150, success=6390} -messages[61] = {bayld=7152, ease=7144, fail=7069, full=7067, notes=7151, points=7149, standing=7150, success=6390} -messages[79] = {bayld=7152, ease=7144, fail=7069, full=7067, notes=7151, points=7149, standing=7150, success=6390} -messages[81] = {bayld=7836, ease=7828, fail=7753, full=7751, notes=7835, points=7833, standing=7834, success=6390} -messages[82] = {bayld=7468, ease=7460, fail=7385, full=7383, notes=7467, points=7465, standing=7466, success=6390} -messages[83] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} -messages[84] = {bayld=7175, ease=7167, fail=7092, full=7090, notes=7174, points=7172, standing=7173, success=6390} -messages[88] = {bayld=7461, ease=7453, fail=7378, full=7376, notes=7460, points=7458, standing=7459, success=6390} -messages[89] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} -messages[90] = {bayld=7252, ease=7244, fail=7169, full=7167, notes=7251, points=7249, standing=7250, success=6390} -messages[91] = {bayld=7175, ease=7167, fail=7092, full=7090, notes=7174, points=7172, standing=7173, success=6390} -messages[95] = {bayld=7182, ease=7174, fail=7099, full=7097, notes=7181, points=7179, standing=7180, success=6390} -messages[96] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} -messages[97] = {bayld=7713, ease=7705, fail=7630, full=7628, notes=7712, points=7710, standing=7711, success=6390} -messages[98] = {bayld=7713, ease=7705, fail=7630, full=7628, notes=7712, points=7710, standing=7711, success=6390} -messages[100] = {bayld=7336, ease=7328, fail=7253, full=7251, notes=7335, points=7333, standing=7334, success=6412} -messages[101] = {bayld=7336, ease=7328, fail=7253, full=7251, notes=7335, points=7333, standing=7334, success=6412} -messages[102] = {bayld=7318, ease=7310, fail=7235, full=7233, notes=7317, points=7315, standing=7316, success=6390} -messages[103] = {bayld=7336, ease=7328, fail=7253, full=7251, notes=7335, points=7333, standing=7334, success=6412} -messages[104] = {bayld=7810, ease=7802, fail=7727, full=7725, notes=7809, points=7807, standing=7808, success=6412} -messages[105] = {bayld=7336, ease=7328, fail=7253, full=7251, notes=7335, points=7333, standing=7334, success=6412} -messages[106] = {bayld=7336, ease=7328, fail=7253, full=7251, notes=7335, points=7333, standing=7334, success=6571} -messages[107] = {bayld=7336, ease=7328, fail=7253, full=7251, notes=7335, points=7333, standing=7334, success=6412} -messages[108] = {bayld=7318, ease=7310, fail=7235, full=7233, notes=7317, points=7315, standing=7316, success=6390} -messages[109] = {bayld=7336, ease=7328, fail=7253, full=7251, notes=7335, points=7333, standing=7334, success=6412} -messages[110] = {bayld=7336, ease=7328, fail=7253, full=7251, notes=7335, points=7333, standing=7334, success=6412} -messages[111] = {bayld=7336, ease=7328, fail=7253, full=7251, notes=7335, points=7333, standing=7334, success=6571} -messages[112] = {bayld=7353, ease=7345, fail=7270, full=7268, notes=7352, points=7350, standing=7351, success=6403} -messages[113] = {bayld=7656, ease=7648, fail=7573, full=7571, notes=7655, points=7653, standing=7654, success=6390} -messages[114] = {bayld=7656, ease=7648, fail=7573, full=7571, notes=7655, points=7653, standing=7654, success=6390} -messages[115] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} -messages[116] = {bayld=7314, ease=7306, fail=7231, full=7229, notes=7313, points=7311, standing=7312, success=6390} -messages[117] = {bayld=7336, ease=7328, fail=7253, full=7251, notes=7335, points=7333, standing=7334, success=6571} -messages[118] = {bayld=7355, ease=7347, fail=7272, full=7270, notes=7354, points=7352, standing=7353, success=6425} -messages[119] = {bayld=7336, ease=7328, fail=7253, full=7251, notes=7335, points=7333, standing=7334, success=6412} -messages[120] = {bayld=7344, ease=7336, fail=7261, full=7259, notes=7343, points=7341, standing=7342, success=6412} -messages[121] = {bayld=7656, ease=7648, fail=7573, full=7571, notes=7655, points=7653, standing=7654, success=6390} -messages[122] = {bayld=7314, ease=7306, fail=7231, full=7229, notes=7313, points=7311, standing=7312, success=6390} -messages[123] = {bayld=7656, ease=7648, fail=7573, full=7571, notes=7655, points=7653, standing=7654, success=6390} -messages[124] = {bayld=7656, ease=7648, fail=7573, full=7571, notes=7655, points=7653, standing=7654, success=6390} -messages[125] = {bayld=7314, ease=7306, fail=7231, full=7229, notes=7313, points=7311, standing=7312, success=6390} -messages[126] = {bayld=7314, ease=7306, fail=7231, full=7229, notes=7313, points=7311, standing=7312, success=6390} -messages[127] = {bayld=7314, ease=7306, fail=7231, full=7229, notes=7313, points=7311, standing=7312, success=6390} -messages[128] = {bayld=7314, ease=7306, fail=7231, full=7229, notes=7313, points=7311, standing=7312, success=6390} -messages[136] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} -messages[137] = {bayld=7677, ease=7669, fail=7594, full=7592, notes=7676, points=7674, standing=7675, success=6390} -messages[260] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} -messages[261] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} -messages[262] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} -messages[263] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} -messages[265] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} -messages[266] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} -messages[267] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} +messages[2] = {bayld=7379, ease=7371, fail=7296, full=7294, notes=7378, points=7376, standing=7377, success=6390} +messages[4] = {bayld=7373, ease=7365, fail=7290, full=7288, notes=7372, points=7370, standing=7371, success=6390} +messages[5] = {bayld=7330, ease=7322, fail=7247, full=7245, notes=7329, points=7327, standing=7328, success=6403} +messages[7] = {bayld=7324, ease=7316, fail=7241, full=7239, notes=7323, points=7321, standing=7322, success=6390} +messages[24] = {bayld=7660, ease=7652, fail=7577, full=7575, notes=7659, points=7657, standing=7658, success=6390} +messages[25] = {bayld=7180, ease=7172, fail=7097, full=7095, notes=7179, points=7177, standing=7178, success=6390} +messages[51] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} +messages[52] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} +messages[61] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} +messages[79] = {bayld=7155, ease=7147, fail=7072, full=7070, notes=7154, points=7152, standing=7153, success=6390} +messages[81] = {bayld=7839, ease=7831, fail=7756, full=7754, notes=7838, points=7836, standing=7837, success=6390} +messages[82] = {bayld=7471, ease=7463, fail=7388, full=7386, notes=7470, points=7468, standing=7469, success=6390} +messages[83] = {bayld=7158, ease=7150, fail=7075, full=7073, notes=7157, points=7155, standing=7156, success=6390} +messages[84] = {bayld=7178, ease=7170, fail=7095, full=7093, notes=7177, points=7175, standing=7176, success=6390} +messages[88] = {bayld=7464, ease=7456, fail=7381, full=7379, notes=7463, points=7461, standing=7462, success=6390} +messages[89] = {bayld=7158, ease=7150, fail=7075, full=7073, notes=7157, points=7155, standing=7156, success=6390} +messages[90] = {bayld=7255, ease=7247, fail=7172, full=7170, notes=7254, points=7252, standing=7253, success=6390} +messages[91] = {bayld=7178, ease=7170, fail=7095, full=7093, notes=7177, points=7175, standing=7176, success=6390} +messages[95] = {bayld=7185, ease=7177, fail=7102, full=7100, notes=7184, points=7182, standing=7183, success=6390} +messages[96] = {bayld=7158, ease=7150, fail=7075, full=7073, notes=7157, points=7155, standing=7156, success=6390} +messages[97] = {bayld=7716, ease=7708, fail=7633, full=7631, notes=7715, points=7713, standing=7714, success=6390} +messages[98] = {bayld=7716, ease=7708, fail=7633, full=7631, notes=7715, points=7713, standing=7714, success=6390} +messages[100] = {bayld=7339, ease=7331, fail=7256, full=7254, notes=7338, points=7336, standing=7337, success=6412} +messages[101] = {bayld=7339, ease=7331, fail=7256, full=7254, notes=7338, points=7336, standing=7337, success=6412} +messages[102] = {bayld=7321, ease=7313, fail=7238, full=7236, notes=7320, points=7318, standing=7319, success=6390} +messages[103] = {bayld=7339, ease=7331, fail=7256, full=7254, notes=7338, points=7336, standing=7337, success=6412} +messages[104] = {bayld=7813, ease=7805, fail=7730, full=7728, notes=7812, points=7810, standing=7811, success=6412} +messages[105] = {bayld=7339, ease=7331, fail=7256, full=7254, notes=7338, points=7336, standing=7337, success=6412} +messages[106] = {bayld=7339, ease=7331, fail=7256, full=7254, notes=7338, points=7336, standing=7337, success=6571} +messages[107] = {bayld=7339, ease=7331, fail=7256, full=7254, notes=7338, points=7336, standing=7337, success=6412} +messages[108] = {bayld=7321, ease=7313, fail=7238, full=7236, notes=7320, points=7318, standing=7319, success=6390} +messages[109] = {bayld=7339, ease=7331, fail=7256, full=7254, notes=7338, points=7336, standing=7337, success=6412} +messages[110] = {bayld=7339, ease=7331, fail=7256, full=7254, notes=7338, points=7336, standing=7337, success=6412} +messages[111] = {bayld=7339, ease=7331, fail=7256, full=7254, notes=7338, points=7336, standing=7337, success=6571} +messages[112] = {bayld=7356, ease=7348, fail=7273, full=7271, notes=7355, points=7353, standing=7354, success=6403} +messages[113] = {bayld=7659, ease=7651, fail=7576, full=7574, notes=7658, points=7656, standing=7657, success=6390} +messages[114] = {bayld=7659, ease=7651, fail=7576, full=7574, notes=7658, points=7656, standing=7657, success=6390} +messages[115] = {bayld=7158, ease=7150, fail=7075, full=7073, notes=7157, points=7155, standing=7156, success=6390} +messages[116] = {bayld=7317, ease=7309, fail=7234, full=7232, notes=7316, points=7314, standing=7315, success=6390} +messages[117] = {bayld=7339, ease=7331, fail=7256, full=7254, notes=7338, points=7336, standing=7337, success=6571} +messages[118] = {bayld=7358, ease=7350, fail=7275, full=7273, notes=7357, points=7355, standing=7356, success=6425} +messages[119] = {bayld=7339, ease=7331, fail=7256, full=7254, notes=7338, points=7336, standing=7337, success=6412} +messages[120] = {bayld=7347, ease=7339, fail=7264, full=7262, notes=7346, points=7344, standing=7345, success=6412} +messages[121] = {bayld=7659, ease=7651, fail=7576, full=7574, notes=7658, points=7656, standing=7657, success=6390} +messages[122] = {bayld=7317, ease=7309, fail=7234, full=7232, notes=7316, points=7314, standing=7315, success=6390} +messages[123] = {bayld=7659, ease=7651, fail=7576, full=7574, notes=7658, points=7656, standing=7657, success=6390} +messages[124] = {bayld=7659, ease=7651, fail=7576, full=7574, notes=7658, points=7656, standing=7657, success=6390} +messages[125] = {bayld=7317, ease=7309, fail=7234, full=7232, notes=7316, points=7314, standing=7315, success=6390} +messages[126] = {bayld=7317, ease=7309, fail=7234, full=7232, notes=7316, points=7314, standing=7315, success=6390} +messages[127] = {bayld=7317, ease=7309, fail=7234, full=7232, notes=7316, points=7314, standing=7315, success=6390} +messages[128] = {bayld=7317, ease=7309, fail=7234, full=7232, notes=7316, points=7314, standing=7315, success=6390} +messages[136] = {bayld=7158, ease=7150, fail=7075, full=7073, notes=7157, points=7155, standing=7156, success=6390} +messages[137] = {bayld=7680, ease=7672, fail=7597, full=7595, notes=7679, points=7677, standing=7678, success=6390} +messages[260] = {bayld=7158, ease=7150, fail=7075, full=7073, notes=7157, points=7155, standing=7156, success=6390} +messages[261] = {bayld=7158, ease=7150, fail=7075, full=7073, notes=7157, points=7155, standing=7156, success=6390} +messages[262] = {bayld=7158, ease=7150, fail=7075, full=7073, notes=7157, points=7155, standing=7156, success=6390} +messages[263] = {bayld=7158, ease=7150, fail=7075, full=7073, notes=7157, points=7155, standing=7156, success=6390} +messages[265] = {bayld=7158, ease=7150, fail=7075, full=7073, notes=7157, points=7155, standing=7156, success=6390} +messages[266] = {bayld=7158, ease=7150, fail=7075, full=7073, notes=7157, points=7155, standing=7156, success=6390} +messages[267] = {bayld=7158, ease=7150, fail=7075, full=7073, notes=7157, points=7155, standing=7156, success=6390} From a61a3be50214d8747dd4dcdc03ae9b161c78fb24 Mon Sep 17 00:00:00 2001 From: Byrth Date: Mon, 12 Sep 2022 07:36:17 -0400 Subject: [PATCH 0871/1002] boxdestroyer message updates --- addons/boxdestroyer/messages.lua | 120 +++++++++++++++---------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/addons/boxdestroyer/messages.lua b/addons/boxdestroyer/messages.lua index 7ae3377a40..01a7b69edd 100644 --- a/addons/boxdestroyer/messages.lua +++ b/addons/boxdestroyer/messages.lua @@ -1,63 +1,63 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination" for the associated zone IDs - [100] = 8075, - [101] = 7513, - [102] = 7926, - [103] = 8101, - [104] = 8666, - [105] = 7717, - [106] = 8091, - [107] = 7552, - [108] = 7621, - [109] = 8484, - [110] = 7608, - [111] = 8585, - [112] = 8187, - [113] = 7936, - [114] = 7786, - [115] = 7882, - [116] = 7578, - [117] = 7585, - [118] = 8127, - [119] = 8364, - [120] = 7524, - [121] = 8104, - [122] = 7442, - [123] = 7887, - [124] = 7838, - [125] = 7655, - [126] = 8071, - [127] = 7359, - [128] = 7514, - [130] = 7578, - [153] = 11404, - [157] = 7384, - [158] = 7390, - [159] = 8453, - [160] = 7417, - [166] = 10586, - [167] = 10600, - [169] = 7547, - [172] = 7420, - [173] = 10525, - [174] = 11403, - [176] = 7612, - [177] = 11227, - [178] = 11407, - [184] = 8637, - [190] = 8261, - [191] = 8381, - [192] = 7417, - [193] = 8393, - [194] = 8273, - [195] = 7604, - [196] = 8313, - [197] = 7358, - [198] = 8279, - [200] = 7535, - [204] = 7523, - [205] = 11490, - [208] = 8292, - [212] = 10646, - [213] = 10456, + [100] = 8078, + [101] = 7516, + [102] = 7929, + [103] = 8104, + [104] = 8669, + [105] = 7720, + [106] = 8094, + [107] = 7555, + [108] = 7624, + [109] = 8487, + [110] = 7611, + [111] = 8588, + [112] = 8190, + [113] = 7939, + [114] = 7789, + [115] = 7885, + [116] = 7581, + [117] = 7588, + [118] = 8130, + [119] = 8367, + [120] = 7527, + [121] = 8107, + [122] = 7445, + [123] = 7890, + [124] = 7841, + [125] = 7658, + [126] = 8074, + [127] = 7362, + [128] = 7517, + [130] = 7581, + [153] = 11407, + [157] = 7387, + [158] = 7393, + [159] = 8456, + [160] = 7420, + [166] = 10589, + [167] = 10603, + [169] = 7550, + [172] = 7423, + [173] = 10528, + [174] = 11406, + [176] = 7615, + [177] = 11230, + [178] = 11410, + [184] = 8640, + [190] = 8264, + [191] = 8384, + [192] = 7420, + [193] = 8396, + [194] = 8276, + [195] = 7607, + [196] = 8316, + [197] = 7361, + [198] = 8282, + [200] = 7538, + [204] = 7526, + [205] = 11493, + [208] = 8295, + [212] = 10649, + [213] = 10459, } offsets = {greater_less=1, failure=2, success=4, second_even_odd=5, first_even_odd=6, range=7, less=8, greater=9, equal=10, second_multiple=11, first_multiple=12, tool_failure=13} From b3b3327b12ec7f09dcdbd37058047ee6b2fd33bd Mon Sep 17 00:00:00 2001 From: Chiaia Date: Mon, 12 Sep 2022 08:56:29 -0400 Subject: [PATCH 0872/1002] Sept 11th, 2022 Update --- addons/libs/slips.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 016f128219..5604d74623 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -11,7 +11,7 @@ _libs.slips = slips slips.default_storages = {'inventory', 'safe', 'storage', 'locker', 'satchel', 'sack', 'case', 'wardrobe', 'safe2', 'wardrobe2', 'wardrobe3', 'wardrobe4'} -slips.storages = L{29312, 29313, 29314, 29315, 29316, 29317, 29318, 29319, 29320, 29321, 29322, 29323, 29324, 29325, 29326, 29327, 29328, 29329, 29330, 29331, 29332, 29333, 29334, 29335, 29336, 29337, 29338, 29339} +slips.storages = L{29312, 29313, 29314, 29315, 29316, 29317, 29318, 29319, 29320, 29321, 29322, 29323, 29324, 29325, 29326, 29327, 29328, 29329, 29330, 29331, 29332, 29333, 29334, 29335, 29336, 29337, 29338, 29339, 29340, 29341} slips.items = { [slips.storages[1]] = L{16084, 14546, 14961, 15625, 15711, 16085, 14547, 14962, 15626, 15712, 16086, 14548, 14963, 15627, 15713, 16087, 14549, 14964, 15628, 15714, 16088, 14550, 14965, 15629, 15715, 16089, 14551, 14966, 15630, 15716, 16090, 14552, 14967, 15631, 15717, 16091, 14553, 14968, 15632, 15718, 16092, 14554, 14969, 15633, 15719, 16093, 14555, 14970, 15634, 15720, 16094, 14556, 14971, 15635, 15721, 16095, 14557, 14972, 15636, 15722, 16096, 14558, 14973, 15637, 15723, 16097, 14559, 14974, 15638, 15724, 16098, 14560, 14975, 15639, 15725, 16099, 14561, 14976, 15640, 15726, 16100, 14562, 14977, 15641, 15727, 16101, 14563, 14978, 15642, 15728, 16102, 14564, 14979, 15643, 15729, 16103, 14565, 14980, 15644, 15730, 16106, 14568, 14983, 15647, 15733, 16107, 14569, 14984, 15648, 15734, 16108, 14570, 14985, 15649, 15735, 16602, 17741, 18425, 18491, 18588, 18717, 18718, 18850, 18943, 16069, 14530, 14940, 15609, 15695, 16062, 14525, 14933, 15604, 15688, 16064, 14527, 14935, 15606, 15690, 18685, 18065, 17851, 18686, 18025, 18435, 18113, 17951, 17715, 18485, 18408, 18365, 18583, 18417, 18388, 16267, 16268, 16269, 16228, 16229, 15911, 15799, 15800, 15990, 17745, 18121, 16117, 14577, 17857}, -- 168 [slips.storages[2]] = L{12421, 12549, 12677, 12805, 12933, 13911, 14370, 14061, 14283, 14163, 12429, 12557, 12685, 12813, 12941, 13924, 14371, 14816, 14296, 14175, 13934, 14387, 14821, 14303, 14184, 13935, 14388, 14822, 14304, 14185, 13876, 13787, 14006, 14247, 14123, 13877, 13788, 14007, 14248, 14124, 13908, 14367, 14058, 14280, 14160, 13909, 14368, 14059, 14281, 14161, 16113, 14573, 14995, 15655, 15740, 16115, 14575, 14997, 15657, 15742, 16114, 14574, 14996, 15656, 15741, 16116, 14576, 14998, 15658, 15743, 12818, 18198, 12946, 18043, 12690, 17659, 12296, 12434, 15471, 15472, 15473, 15508, 15509, 15510, 15511, 15512, 15513, 15514, 17710, 17595, 18397, 18360, 18222, 17948, 18100, 15475, 15476, 15477, 15488, 15961, 14815, 14812, 14813, 15244, 15240, 14488, 14905, 15576, 15661, 15241, 14489, 14906, 15577, 15662, 13927, 14378, 14076, 14308, 14180, 13928, 14379, 14077, 14309, 14181, 10438, 10276, 10320, 10326, 10367, 10439, 10277, 10321, 10327, 10368, 10440, 10278, 10322, 10328, 10369, 10441, 10279, 10323, 10329, 10370, 25734, 25735, 25736, 25737, 25738, 25739, 25740, 25741, 25742, 25743, 25744}, -- 155 @@ -41,7 +41,7 @@ slips.items = { [slips.storages[26]] = L{23063, 23130, 23197, 23264, 23331, 23064, 23131, 23198, 23265, 23332, 23065, 23132, 23199, 23266, 23333, 23066, 23133, 23200, 23267, 23334, 23067, 23134, 23201, 23268, 23335, 23068, 23135, 23202, 23269, 23336, 23069, 23136, 23203, 23270, 23337, 23070, 23137, 23204, 23271, 23338, 23071, 23138, 23205, 23272, 23339, 23072, 23139, 23206, 23273, 23340, 23073, 23140, 23207, 23274, 23341, 23074, 23141, 23208, 23275, 23342, 23075, 23142, 23209, 23276, 23343, 23076, 23143, 23210, 23277, 23344, 23077, 23144, 23211, 23278, 23345, 23078, 23145, 23212, 23279, 23346, 23079, 23146, 23213, 23280, 23347, 23080, 23147, 23214, 23281, 23348, 23081, 23148, 23215, 23282, 23349, 23082, 23149, 23216, 23283, 23350, 23083, 23150, 23217, 23284, 23351, 23084, 23151, 23218, 23285, 23352}, -- 110 [slips.storages[27]] = L{23398, 23465, 23532, 23599, 23666, 23399, 23466, 23533, 23600, 23667, 23400, 23467, 23534, 23601, 23668, 23401, 23468, 23535, 23602, 23669, 23402, 23469, 23536, 23603, 23670, 23403, 23470, 23537, 23604, 23671, 23404, 23471, 23538, 23605, 23672, 23405, 23472, 23539, 23606, 23673, 23406, 23473, 23540, 23607, 23674, 23407, 23474, 23541, 23608, 23675, 23408, 23475, 23542, 23609, 23676, 23409, 23476, 23543, 23610, 23677, 23410, 23477, 23544, 23611, 23678, 23411, 23478, 23545, 23612, 23679, 23412, 23479, 23546, 23613, 23680, 23413, 23480, 23547, 23614, 23681, 23414, 23481, 23548, 23615, 23682, 23415, 23482, 23549, 23616, 23683, 23416, 23483, 23550, 23617, 23684, 23417, 23484, 23551, 23618, 23685, 23418, 23485, 23552, 23619, 23686, 23419, 23486, 23553, 23620, 23687}, -- 110 [slips.storages[28]] = L{21515, 21561, 21617, 21670, 21718, 21775, 21826, 21879, 21918, 21971, 22027, 22082, 22108, 22214, 21516, 21562, 21618, 21671, 21719, 21776, 21827, 21880, 21919, 21972, 22028, 22083, 22109, 22215, 21517, 21563, 21619, 21672, 21720, 21777, 21828, 21881, 21920, 21973, 22029, 22084, 22110, 22216, 21518, 21564, 21620, 21673, 21721, 21778, 21829, 21882, 21921, 21974, 22030, 22085, 22111, 22217, 21519, 21565, 21621, 21674, 21722, 21779, 21830, 21883, 21922, 21975, 22031, 22086, 22107, 22218, 22089}, --71 - --[slips.storages[29]] = L{23085, 23152, 23219, 23286, 23353, 23086, 23153, 23220, 23287, 23354, 23087, 23154, 23221, 23288, 23355, 23088, 23155, 23222, 23289, 23356, 23089, 23156, 23223, 23290, 23357, 23090, 23157, 23224, 23291, 23358, 23091, 23158, 23225, 23292, 23359, 23092, 23159, 23226, 23293, 23360, 23093, 23160, 23227, 23294, 23361, 23094, 23161, 23228, 23295, 23362, 23095, 23162, 23229, 23296, 23363, 23096, 23163, 23230, 23297, 23364, 23097, 23164, 23231, 23298, 23365, 23098, 23165, 23232, 23299, 23366, 23099, 23166, 23233, 23300, 23367, 23100, 23167, 23234, 23301, 23368, 23101, 23168, 23235, 23302, 23369, 23102, 23169, 23236, 23303, 23370, 23103, 23170, 23237, 23304, 23371, 23104, 23171, 23238, 23305, 23372, 23105, 23172, 23239, 23306, 23373, 23106, 23173, 23240, 23307, 23374}, -- 110 + [slips.storages[29]] = L{23085, 23152, 23219, 23286, 23353, 23086, 23153, 23220, 23287, 23354, 23087, 23154, 23221, 23288, 23355, 23088, 23155, 23222, 23289, 23356, 23089, 23156, 23223, 23290, 23357, 23090, 23157, 23224, 23291, 23358, 23091, 23158, 23225, 23292, 23359, 23092, 23159, 23226, 23293, 23360, 23093, 23160, 23227, 23294, 23361, 23094, 23161, 23228, 23295, 23362, 23095, 23162, 23229, 23296, 23363, 23096, 23163, 23230, 23297, 23364, 23097, 23164, 23231, 23298, 23365, 23098, 23165, 23232, 23299, 23366, 23099, 23166, 23233, 23300, 23367, 23100, 23167, 23234, 23301, 23368, 23101, 23168, 23235, 23302, 23369, 23102, 23169, 23236, 23303, 23370, 23103, 23170, 23237, 23304, 23371, 23104, 23171, 23238, 23305, 23372, 23105, 23172, 23239, 23306, 23373, 23106, 23173, 23240, 23307, 23374}, -- 110 } function slips.get_slip_id(n) From 77a054d53718300d996e4a943d3c59f69c7f1708 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Mon, 12 Sep 2022 14:11:38 -0400 Subject: [PATCH 0873/1002] Fixes + Slip 22 added items. --- addons/libs/slips.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 5604d74623..ea85424da1 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -10,8 +10,8 @@ local slips = {} _libs.slips = slips -slips.default_storages = {'inventory', 'safe', 'storage', 'locker', 'satchel', 'sack', 'case', 'wardrobe', 'safe2', 'wardrobe2', 'wardrobe3', 'wardrobe4'} -slips.storages = L{29312, 29313, 29314, 29315, 29316, 29317, 29318, 29319, 29320, 29321, 29322, 29323, 29324, 29325, 29326, 29327, 29328, 29329, 29330, 29331, 29332, 29333, 29334, 29335, 29336, 29337, 29338, 29339, 29340, 29341} +slips.default_storages = {'inventory', 'safe', 'storage', 'locker', 'satchel', 'sack', 'case', 'wardrobe', 'safe2', 'wardrobe2', 'wardrobe3', 'wardrobe4', 'wardrobe5', 'wardrobe6', 'wardrobe7', 'wardrobe8'} +slips.storages = L{29312, 29313, 29314, 29315, 29316, 29317, 29318, 29319, 29320, 29321, 29322, 29323, 29324, 29325, 29326, 29327, 29328, 29329, 29330, 29331, 29332, 29333, 29334, 29335, 29336, 29337, 29338, 29339, 29340} -- 29341(Slip 30) slips.items = { [slips.storages[1]] = L{16084, 14546, 14961, 15625, 15711, 16085, 14547, 14962, 15626, 15712, 16086, 14548, 14963, 15627, 15713, 16087, 14549, 14964, 15628, 15714, 16088, 14550, 14965, 15629, 15715, 16089, 14551, 14966, 15630, 15716, 16090, 14552, 14967, 15631, 15717, 16091, 14553, 14968, 15632, 15718, 16092, 14554, 14969, 15633, 15719, 16093, 14555, 14970, 15634, 15720, 16094, 14556, 14971, 15635, 15721, 16095, 14557, 14972, 15636, 15722, 16096, 14558, 14973, 15637, 15723, 16097, 14559, 14974, 15638, 15724, 16098, 14560, 14975, 15639, 15725, 16099, 14561, 14976, 15640, 15726, 16100, 14562, 14977, 15641, 15727, 16101, 14563, 14978, 15642, 15728, 16102, 14564, 14979, 15643, 15729, 16103, 14565, 14980, 15644, 15730, 16106, 14568, 14983, 15647, 15733, 16107, 14569, 14984, 15648, 15734, 16108, 14570, 14985, 15649, 15735, 16602, 17741, 18425, 18491, 18588, 18717, 18718, 18850, 18943, 16069, 14530, 14940, 15609, 15695, 16062, 14525, 14933, 15604, 15688, 16064, 14527, 14935, 15606, 15690, 18685, 18065, 17851, 18686, 18025, 18435, 18113, 17951, 17715, 18485, 18408, 18365, 18583, 18417, 18388, 16267, 16268, 16269, 16228, 16229, 15911, 15799, 15800, 15990, 17745, 18121, 16117, 14577, 17857}, -- 168 [slips.storages[2]] = L{12421, 12549, 12677, 12805, 12933, 13911, 14370, 14061, 14283, 14163, 12429, 12557, 12685, 12813, 12941, 13924, 14371, 14816, 14296, 14175, 13934, 14387, 14821, 14303, 14184, 13935, 14388, 14822, 14304, 14185, 13876, 13787, 14006, 14247, 14123, 13877, 13788, 14007, 14248, 14124, 13908, 14367, 14058, 14280, 14160, 13909, 14368, 14059, 14281, 14161, 16113, 14573, 14995, 15655, 15740, 16115, 14575, 14997, 15657, 15742, 16114, 14574, 14996, 15656, 15741, 16116, 14576, 14998, 15658, 15743, 12818, 18198, 12946, 18043, 12690, 17659, 12296, 12434, 15471, 15472, 15473, 15508, 15509, 15510, 15511, 15512, 15513, 15514, 17710, 17595, 18397, 18360, 18222, 17948, 18100, 15475, 15476, 15477, 15488, 15961, 14815, 14812, 14813, 15244, 15240, 14488, 14905, 15576, 15661, 15241, 14489, 14906, 15577, 15662, 13927, 14378, 14076, 14308, 14180, 13928, 14379, 14077, 14309, 14181, 10438, 10276, 10320, 10326, 10367, 10439, 10277, 10321, 10327, 10368, 10440, 10278, 10322, 10328, 10369, 10441, 10279, 10323, 10329, 10370, 25734, 25735, 25736, 25737, 25738, 25739, 25740, 25741, 25742, 25743, 25744}, -- 155 @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757, 25909}, -- 192 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752}, -- 156 SE Skipped an index hence the 0 as one of the items + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912}, -- 159 SE Skipped an index hence the 0 as one of the items [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067, 21680, 22071}, -- 177 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, -- 115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, -- 115 From 7d056c22476ce62b07a23a1135410019e98abcd0 Mon Sep 17 00:00:00 2001 From: Chiaia Date: Wed, 14 Sep 2022 16:34:14 -0400 Subject: [PATCH 0874/1002] Slip 29 Support --- addons/findAll/findAll.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/findAll/findAll.lua b/addons/findAll/findAll.lua index 192f6f96f5..7d9879e3f4 100644 --- a/addons/findAll/findAll.lua +++ b/addons/findAll/findAll.lua @@ -192,7 +192,7 @@ storages_order = S(res.bags:map(string.gsub-{' ', ''} .. string.lower .. return index1 < index2 end) -storage_slips_order = L{'slip 01', 'slip 02', 'slip 03', 'slip 04', 'slip 05', 'slip 06', 'slip 07', 'slip 08', 'slip 09', 'slip 10', 'slip 11', 'slip 12', 'slip 13', 'slip 14', 'slip 15', 'slip 16', 'slip 17', 'slip 18', 'slip 19', 'slip 20', 'slip 21', 'slip 22', 'slip 23', 'slip 24', 'slip 25', 'slip 26', 'slip 27', 'slip 28'} +storage_slips_order = L{'slip 01', 'slip 02', 'slip 03', 'slip 04', 'slip 05', 'slip 06', 'slip 07', 'slip 08', 'slip 09', 'slip 10', 'slip 11', 'slip 12', 'slip 13', 'slip 14', 'slip 15', 'slip 16', 'slip 17', 'slip 18', 'slip 19', 'slip 20', 'slip 21', 'slip 22', 'slip 23', 'slip 24', 'slip 25', 'slip 26', 'slip 27', 'slip 28', 'slip 29'} merged_storages_orders = storages_order + storage_slips_order + L{'key items'} function search(query, export) From 41eb479f51de5151642f3cfbdc4908138e262175 Mon Sep 17 00:00:00 2001 From: Byrth Date: Tue, 11 Oct 2022 07:54:31 -0400 Subject: [PATCH 0875/1002] Add Blueblade Fell --- addons/libs/slips.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index ea85424da1..aa5c01a9ac 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -11,7 +11,7 @@ _libs.slips = slips slips.default_storages = {'inventory', 'safe', 'storage', 'locker', 'satchel', 'sack', 'case', 'wardrobe', 'safe2', 'wardrobe2', 'wardrobe3', 'wardrobe4', 'wardrobe5', 'wardrobe6', 'wardrobe7', 'wardrobe8'} -slips.storages = L{29312, 29313, 29314, 29315, 29316, 29317, 29318, 29319, 29320, 29321, 29322, 29323, 29324, 29325, 29326, 29327, 29328, 29329, 29330, 29331, 29332, 29333, 29334, 29335, 29336, 29337, 29338, 29339, 29340} -- 29341(Slip 30) +slips.storages = L{29312, 29313, 29314, 29315, 29316, 29317, 29318, 29319, 29320, 29321, 29322, 29323, 29324, 29325, 29326, 29327, 29328, 29329, 29330, 29331, 29332, 29333, 29334, 29335, 29336, 29337, 29338, 29339, 29340,} -- 29341(Slip 30) slips.items = { [slips.storages[1]] = L{16084, 14546, 14961, 15625, 15711, 16085, 14547, 14962, 15626, 15712, 16086, 14548, 14963, 15627, 15713, 16087, 14549, 14964, 15628, 15714, 16088, 14550, 14965, 15629, 15715, 16089, 14551, 14966, 15630, 15716, 16090, 14552, 14967, 15631, 15717, 16091, 14553, 14968, 15632, 15718, 16092, 14554, 14969, 15633, 15719, 16093, 14555, 14970, 15634, 15720, 16094, 14556, 14971, 15635, 15721, 16095, 14557, 14972, 15636, 15722, 16096, 14558, 14973, 15637, 15723, 16097, 14559, 14974, 15638, 15724, 16098, 14560, 14975, 15639, 15725, 16099, 14561, 14976, 15640, 15726, 16100, 14562, 14977, 15641, 15727, 16101, 14563, 14978, 15642, 15728, 16102, 14564, 14979, 15643, 15729, 16103, 14565, 14980, 15644, 15730, 16106, 14568, 14983, 15647, 15733, 16107, 14569, 14984, 15648, 15734, 16108, 14570, 14985, 15649, 15735, 16602, 17741, 18425, 18491, 18588, 18717, 18718, 18850, 18943, 16069, 14530, 14940, 15609, 15695, 16062, 14525, 14933, 15604, 15688, 16064, 14527, 14935, 15606, 15690, 18685, 18065, 17851, 18686, 18025, 18435, 18113, 17951, 17715, 18485, 18408, 18365, 18583, 18417, 18388, 16267, 16268, 16269, 16228, 16229, 15911, 15799, 15800, 15990, 17745, 18121, 16117, 14577, 17857}, -- 168 [slips.storages[2]] = L{12421, 12549, 12677, 12805, 12933, 13911, 14370, 14061, 14283, 14163, 12429, 12557, 12685, 12813, 12941, 13924, 14371, 14816, 14296, 14175, 13934, 14387, 14821, 14303, 14184, 13935, 14388, 14822, 14304, 14185, 13876, 13787, 14006, 14247, 14123, 13877, 13788, 14007, 14248, 14124, 13908, 14367, 14058, 14280, 14160, 13909, 14368, 14059, 14281, 14161, 16113, 14573, 14995, 15655, 15740, 16115, 14575, 14997, 15657, 15742, 16114, 14574, 14996, 15656, 15741, 16116, 14576, 14998, 15658, 15743, 12818, 18198, 12946, 18043, 12690, 17659, 12296, 12434, 15471, 15472, 15473, 15508, 15509, 15510, 15511, 15512, 15513, 15514, 17710, 17595, 18397, 18360, 18222, 17948, 18100, 15475, 15476, 15477, 15488, 15961, 14815, 14812, 14813, 15244, 15240, 14488, 14905, 15576, 15661, 15241, 14489, 14906, 15577, 15662, 13927, 14378, 14076, 14308, 14180, 13928, 14379, 14077, 14309, 14181, 10438, 10276, 10320, 10326, 10367, 10439, 10277, 10321, 10327, 10368, 10440, 10278, 10322, 10328, 10369, 10441, 10279, 10323, 10329, 10370, 25734, 25735, 25736, 25737, 25738, 25739, 25740, 25741, 25742, 25743, 25744}, -- 155 @@ -34,14 +34,14 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757, 25909}, -- 192 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912}, -- 159 SE Skipped an index hence the 0 as one of the items + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912, 3753}, -- 160 SE Skipped an index hence the 0 as one of the items [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067, 21680, 22071}, -- 177 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, -- 115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, -- 115 [slips.storages[26]] = L{23063, 23130, 23197, 23264, 23331, 23064, 23131, 23198, 23265, 23332, 23065, 23132, 23199, 23266, 23333, 23066, 23133, 23200, 23267, 23334, 23067, 23134, 23201, 23268, 23335, 23068, 23135, 23202, 23269, 23336, 23069, 23136, 23203, 23270, 23337, 23070, 23137, 23204, 23271, 23338, 23071, 23138, 23205, 23272, 23339, 23072, 23139, 23206, 23273, 23340, 23073, 23140, 23207, 23274, 23341, 23074, 23141, 23208, 23275, 23342, 23075, 23142, 23209, 23276, 23343, 23076, 23143, 23210, 23277, 23344, 23077, 23144, 23211, 23278, 23345, 23078, 23145, 23212, 23279, 23346, 23079, 23146, 23213, 23280, 23347, 23080, 23147, 23214, 23281, 23348, 23081, 23148, 23215, 23282, 23349, 23082, 23149, 23216, 23283, 23350, 23083, 23150, 23217, 23284, 23351, 23084, 23151, 23218, 23285, 23352}, -- 110 [slips.storages[27]] = L{23398, 23465, 23532, 23599, 23666, 23399, 23466, 23533, 23600, 23667, 23400, 23467, 23534, 23601, 23668, 23401, 23468, 23535, 23602, 23669, 23402, 23469, 23536, 23603, 23670, 23403, 23470, 23537, 23604, 23671, 23404, 23471, 23538, 23605, 23672, 23405, 23472, 23539, 23606, 23673, 23406, 23473, 23540, 23607, 23674, 23407, 23474, 23541, 23608, 23675, 23408, 23475, 23542, 23609, 23676, 23409, 23476, 23543, 23610, 23677, 23410, 23477, 23544, 23611, 23678, 23411, 23478, 23545, 23612, 23679, 23412, 23479, 23546, 23613, 23680, 23413, 23480, 23547, 23614, 23681, 23414, 23481, 23548, 23615, 23682, 23415, 23482, 23549, 23616, 23683, 23416, 23483, 23550, 23617, 23684, 23417, 23484, 23551, 23618, 23685, 23418, 23485, 23552, 23619, 23686, 23419, 23486, 23553, 23620, 23687}, -- 110 [slips.storages[28]] = L{21515, 21561, 21617, 21670, 21718, 21775, 21826, 21879, 21918, 21971, 22027, 22082, 22108, 22214, 21516, 21562, 21618, 21671, 21719, 21776, 21827, 21880, 21919, 21972, 22028, 22083, 22109, 22215, 21517, 21563, 21619, 21672, 21720, 21777, 21828, 21881, 21920, 21973, 22029, 22084, 22110, 22216, 21518, 21564, 21620, 21673, 21721, 21778, 21829, 21882, 21921, 21974, 22030, 22085, 22111, 22217, 21519, 21565, 21621, 21674, 21722, 21779, 21830, 21883, 21922, 21975, 22031, 22086, 22107, 22218, 22089}, --71 - [slips.storages[29]] = L{23085, 23152, 23219, 23286, 23353, 23086, 23153, 23220, 23287, 23354, 23087, 23154, 23221, 23288, 23355, 23088, 23155, 23222, 23289, 23356, 23089, 23156, 23223, 23290, 23357, 23090, 23157, 23224, 23291, 23358, 23091, 23158, 23225, 23292, 23359, 23092, 23159, 23226, 23293, 23360, 23093, 23160, 23227, 23294, 23361, 23094, 23161, 23228, 23295, 23362, 23095, 23162, 23229, 23296, 23363, 23096, 23163, 23230, 23297, 23364, 23097, 23164, 23231, 23298, 23365, 23098, 23165, 23232, 23299, 23366, 23099, 23166, 23233, 23300, 23367, 23100, 23167, 23234, 23301, 23368, 23101, 23168, 23235, 23302, 23369, 23102, 23169, 23236, 23303, 23370, 23103, 23170, 23237, 23304, 23371, 23104, 23171, 23238, 23305, 23372, 23105, 23172, 23239, 23306, 23373, 23106, 23173, 23240, 23307, 23374}, -- 110 + [slips.storages[29]] = L{23085, 23152, 23219, 23286, 23353, 23086, 23153, 23220, 23287, 23354, 23087, 23154, 23221, 23288, 23355, 23088, 23155, 23222, 23289, 23356, 23089, 23156, 23223, 23290, 23357, 23090, 23157, 23224, 23291, 23358, 23091, 23158, 23225, 23292, 23359, 23092, 23159, 23226, 23293, 23360, 23093, 23160, 23227, 23294, 23361, 23094, 23161, 23228, 23295, 23362, 23095, 23162, 23229, 23296, 23363, 23096, 23163, 23230, 23297, 23364, 23097, 23164, 23231, 23298, 23365, 23098, 23165, 23232, 23299, 23366, 23099, 23166, 23233, 23300, 23367, 23100, 23167, 23234, 23301, 23368, 23101, 23168, 23235, 23302, 23369, 23102, 23169, 23236, 23303, 23370, 23103, 23170, 23237, 23304, 23371, 23104, 23171, 23238, 23305, 23372, 23105, 23172, 23239, 23306, 23373, 23106, 23173, 23240, 23307, 23374}, -- 110 } function slips.get_slip_id(n) From c5984dc0c4456f196133f2c24ee4082dbf9917cc Mon Sep 17 00:00:00 2001 From: funkworkz Date: Tue, 11 Oct 2022 10:21:41 -0500 Subject: [PATCH 0876/1002] Update setbgm.lua Unknown Title. If someone has a better idea for a placeholder name, by all means please edit it. --- addons/setbgm/setbgm.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/setbgm/setbgm.lua b/addons/setbgm/setbgm.lua index 0080faadbb..4f9566c4f0 100644 --- a/addons/setbgm/setbgm.lua +++ b/addons/setbgm/setbgm.lua @@ -51,7 +51,7 @@ music_types = { songs = { [25]='Voracious Resurgence Unknown 1', [26]='Voracious Resurgence Unknown 2', [27]='Voracious Resurgence Unknown 3', [28]='Voracious Resurgence Unknown 4', [29]="Devils' Delight", [30]="Odyssey - Bumba", [31]='Voracious Resurgence Unknown 5', [32]='Voracious Resurgence Unknown 6', - [33]='Voracious Resurgence Unknown 7', [34]="We Are Vana'diel", [35]='Goddessspeed', + [33]='Voracious Resurgence Unknown 7', [34]="We Are Vana'diel", [35]='Goddessspeed', [36]='Sortie - +3 Area', [40]='Cloister of Time and Souls', [41]='Royal Wanderlust', [42]='Snowdrift Waltz', [43]='Troubled Shadows', [44]='Where Lords Rule Not', [45]='Summers Lost', [46]='Goddess Divine', [47]='Echoes of Creation', [48]='Main Theme', [49]='Luck of the Mog', [50]='Feast of the Ladies', [51]='Abyssea - Scarlet Skies, Shadowed Plains', [52]='Melodies Errant', [53]='Shinryu', [54]='Everlasting Bonds', [55]='Provenance Watcher', [56]='Where it All Begins', [57]='Steel Sings, Blades Dance', [58]='A New Direction', [59]='The Pioneers', [60]='Into Lands Primeval - Ulbuka', [61]="Water's Umbral Knell", [62]='Keepers of the Wild', [63]='The Sacred City of Adoulin', [64]='Breaking Ground', [65]='Hades', [66]='Arciela', [67]='Mog Resort', [68]='Worlds Away', [69]="Distant Worlds (Nanaa Mihgo's version)", From 3c94fd5613fabad7215173d0d497a310df48e5e9 Mon Sep 17 00:00:00 2001 From: WinterSolstice8 <60417494+WinterSolstice8@users.noreply.github.com> Date: Thu, 13 Oct 2022 20:20:00 -0700 Subject: [PATCH 0877/1002] [shortcuts] Pass valid commands through if target and command is valid --- addons/shortcuts/shortcuts.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/shortcuts/shortcuts.lua b/addons/shortcuts/shortcuts.lua index a2f5da526e..9d05fa40e5 100644 --- a/addons/shortcuts/shortcuts.lua +++ b/addons/shortcuts/shortcuts.lua @@ -290,7 +290,7 @@ function command_logic(original,modified) windower.send_command('@input '..lastsent) return '',false end - elseif command2_list[command] then + elseif command2_list[command] or (command_list[command] and valid_target(potential_targ)) then -- If the submitted command does not require ability interpretation and is fine already, send it out. lastsent = '' if logging then From 36df4b7111d62567c2e5b557799c6c226c0ad786 Mon Sep 17 00:00:00 2001 From: zetaepyon Date: Sat, 29 Oct 2022 23:09:51 -0500 Subject: [PATCH 0878/1002] Create linuxfix.lua --- addons/linuxfix/linuxfix.lua | 143 +++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 addons/linuxfix/linuxfix.lua diff --git a/addons/linuxfix/linuxfix.lua b/addons/linuxfix/linuxfix.lua new file mode 100644 index 0000000000..bc29feeded --- /dev/null +++ b/addons/linuxfix/linuxfix.lua @@ -0,0 +1,143 @@ +_addon.name = 'linuxfix' +_addon.version = '0.5.0' +_addon.author = 'Rubenator,Surik,BeYoNDLiFe' + +--[[ + Do not bother using this if you are on Windows. + + This addon will need to be autoloaded via your init. + + This code has only been tested with fairly standard en-US keyboards. + + This addon restores full keyboard functionality in Windower with newer versions of Wine and bypasses the need to build your own version of Wine with a specific commit reverted. + It also remaps Windows key bindings and makes them functional again with the exception of bindings with multiple modifiers such as %^!1 (Ctrl+Super+Alt+1). The listbinds command is only capable of returning a single modifier and thus they cannot be remapped correctly. + It reads and parses the content of the 'listbinds' command anytime it runs and forwards the keys as appropriate to the client. It also hides the output of this command to avoid console spam. + It's not a fix since it doesn't actually repair the original issue of the keybinds using raw keyboard input but it does work nicely as a workaround. + + When there are a left and right version of a key such as lctrl and rctrl windower sends the lctrl dik even when the right key has been pressed. This also applies to enter and numpadenter. + While the correct keys are in the table below, windower will just use the left version. + + For lack of a better method of keeping the keybinds up to date, the list is refreshed every time you press a key. This was done because Gearswap files frequently rebind keys between jobs. + Since this caused significant lag, a limit was placed so it could not run more than once per second. This limit can be modified using the 'check_rate' variable. + The binds are also now added to a table and don't have to be parsed everytime you press a key which has reduced overhead as well. + + Big shoutout and thanks to Rubenator, he took the awful code Surik and BeYoNDLiFe gave him and made it so much better. +]]-- + +check_rate = 1 + +require('luau') +mods = S{} +keybinds = {} +last_state = T{} +local dik_lookup = T{[-1]='sysrq', [1]='escape', [2]='1', [3]='2', [4]='3', [5]='4', [6]='5', [7]='6', [8]='7', [9]='8', [10]='9', [11]='0', [12]='-', [13]='=', [14]='backspace', [15]='tab', [16]='q', [17]='w', [18]='e', [19]='r', [20]='t', [21]='y', [22]='u', [23]='i', [24]='o', [25]='p', [26]='[', [27]=']', [28]='enter', [30]='a', [31]='s', [32]='d', [33]='f', [34]='g', [35]='h', [36]='j', [37]='k', [38]='l', [39]="\\;", [40]="'", [41]='`', [43]='\\\\', [44]='z', [45]='x', [46]='c', [47]='v', [48]='b', [49]='n', [50]='m', [51]=',', [52]='.', [53]='/', [54]='rshift', [55]='numpad*', [57]='space', [58]='capslock', [59]='f1', [60]='f2', [61]='f3', [62]='f4', [63]='f5', [64]='f6', [65]='f7', [66]='f8', [67]='f9', [68]='f10', [69]='numlock', [70]='scrolllock', [71]='numpad7', [72]='numpad8', [73]='numpad9', [74]='numpad-', [75]='numpad4', [76]='numpad5', [77]='numpad6', [78]='numpad+', [79]='numpad1', [80]='numpad2', [81]='numpad3', [82]='numpad0', [83]='numpad.', [86]='oem_102', [87]='f11', [88]='f12', [100]='f13', [101]='f14', [102]='f15', [112]='kana', [115]='abnt_c1', [121]='convert', [123]='noconvert', [125]='yen', [126]='abnt_c2', [141]='numpadequals', [145]='at', [146]='colon', [147]='underline', [148]='kanji', [149]='stop', [150]='ax', [151]='unlabeled', [153]='nexttrack', [156]='numpadenter', [157]='rctrl', [160]='mute', [161]='calculator', [162]='playpause', [164]='mediastop', [174]='volumedown', [176]='volumeup', [178]='webhome', [179]='numpadcomma', [181]='numpad/', [183]='sysrq', [184]='rmenu', [197]='pause', [199]='home', [200]='up', [201]='pageup', [203]='left', [205]='right', [207]='end', [208]='down', [209]='pagedown', [210]='insert', [211]='delete', [220]='rwin', [222]='power', [223]='sleep', [227]='wake', [229]='websearch', [230]='webfavorites', [231]='webrefresh', [232]='webstop', [233]='', [234]='webback', [235]='mycomputer', [236]='mail', [237]='mediaselect'} +local mod_lookup = T{[29]='Ctrl', [42]='Shift', [56]='Alt', [219]='Win', [221]='Apps'} +key_lookup = T{} +name_lookup = T{} +last_update = nil +do + key_lookup:update(dik_lookup:map(function(name) return {name=name} end)) + key_lookup:update(mod_lookup:map(function(name) return {name=name, mod=true} end)) + for dik, data in pairs(key_lookup) do + name_lookup[data.name] = {mod=data.mod, dik=dik} + end +end + +windower.register_event('keyboard',function(dik,pressed) + if pressed == last_state[dik] then return end + last_state[dik] = pressed + local key_data = key_lookup[dik] + if not key_data then return end + if key_data.mod then + if pressed then + mods:add(key_data.name) + else + mods:remove(key_data.name) + end + send_key_state(key_data, pressed) + elseif pressed then + if not last_update or os.clock() - last_update > check_rate then + windower.send_command('listbinds') + end + local command = check_bind(key_data) + if command then + windower.send_command(command) + else + send_key_state(key_data, pressed) + end + else + send_key_state(key_data, pressed) + end +end) + +function check_bind(key_data) + local binds = keybinds[key_data.name] + if not binds then return false end + local info = windower.ffxi.get_info() + local chat_open = info and info.chat_open + --if chat_open == nil then return false end + binds = binds:filter(function(bind) + return (bind.chat_state == nil or chat_open and bind.chat_state == 'ChatOnly' or not chat_open) and (bind.mods:length() == bind.mods:intersection(mods):length()) + end) + local number_of_binds = binds:length() + if number_of_binds == 0 then + return false + else + return binds:first().command + end +end + +function send_key_state(key_data, pressed) + windower.send_command('setkey %s %s':format(key_data.name, pressed and "down" or "up")) +end + +windower.register_event('incoming text', function(original, modified, color, color_m, blocked) + if color ~= 141 then return end + if ListBinds then + if original == '===== Done Listing Currently Bound Keys =====' then + ListBinds = false + for _,binds in pairs(new_keybinds) do + binds:sort(function(a,b) return a.mods:length() > b.mods:length() end) + end + keybinds = new_keybinds + else + add_bind(original) + end + return true + elseif original == '===== Listing Currently Bound Keys =====' then + last_update = os.clock() + new_keybinds = {} + ListBinds = true + return true + end +end) + +local chat_states = {['(NoChat)']='NoChat', ['(ChatOnly)']='ChatOnly'} +function add_bind(original) + local bind, command = original:match('^([^:]*): (.*)$') + if not bind or not command then return end + bind = bind:gsub('^%-', 'minus'):gsub('%-%-', '-minus') + parts = bind:split('-'):map(string.gsub-{'minus', '-'}) + local chat_state, key + local mods = S{} + for _,part in pairs(parts) do + if chat_states[part] then + chat_state = chat_states[part] + elseif part ~= '' then + local key_data = name_lookup[part] + if key_data then + if key_data.mod then + mods:add(part) + else + key = part + end + end + end + end + if not new_keybinds[key] then + new_keybinds[key] = L{} + end + new_keybinds[key]:append({key=key, mods=mods, chat_state=chat_state, command=command}) +end + +windower.send_command('listbinds') From dbd4c2b9961440008dc985f65f9a9ae3175319ad Mon Sep 17 00:00:00 2001 From: Chiaia Date: Thu, 10 Nov 2022 09:28:33 -0500 Subject: [PATCH 0879/1002] Slip 30 --- addons/libs/slips.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index aa5c01a9ac..904ca10ccd 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -11,7 +11,7 @@ _libs.slips = slips slips.default_storages = {'inventory', 'safe', 'storage', 'locker', 'satchel', 'sack', 'case', 'wardrobe', 'safe2', 'wardrobe2', 'wardrobe3', 'wardrobe4', 'wardrobe5', 'wardrobe6', 'wardrobe7', 'wardrobe8'} -slips.storages = L{29312, 29313, 29314, 29315, 29316, 29317, 29318, 29319, 29320, 29321, 29322, 29323, 29324, 29325, 29326, 29327, 29328, 29329, 29330, 29331, 29332, 29333, 29334, 29335, 29336, 29337, 29338, 29339, 29340,} -- 29341(Slip 30) +slips.storages = L{29312, 29313, 29314, 29315, 29316, 29317, 29318, 29319, 29320, 29321, 29322, 29323, 29324, 29325, 29326, 29327, 29328, 29329, 29330, 29331, 29332, 29333, 29334, 29335, 29336, 29337, 29338, 29339, 29340, 29341} slips.items = { [slips.storages[1]] = L{16084, 14546, 14961, 15625, 15711, 16085, 14547, 14962, 15626, 15712, 16086, 14548, 14963, 15627, 15713, 16087, 14549, 14964, 15628, 15714, 16088, 14550, 14965, 15629, 15715, 16089, 14551, 14966, 15630, 15716, 16090, 14552, 14967, 15631, 15717, 16091, 14553, 14968, 15632, 15718, 16092, 14554, 14969, 15633, 15719, 16093, 14555, 14970, 15634, 15720, 16094, 14556, 14971, 15635, 15721, 16095, 14557, 14972, 15636, 15722, 16096, 14558, 14973, 15637, 15723, 16097, 14559, 14974, 15638, 15724, 16098, 14560, 14975, 15639, 15725, 16099, 14561, 14976, 15640, 15726, 16100, 14562, 14977, 15641, 15727, 16101, 14563, 14978, 15642, 15728, 16102, 14564, 14979, 15643, 15729, 16103, 14565, 14980, 15644, 15730, 16106, 14568, 14983, 15647, 15733, 16107, 14569, 14984, 15648, 15734, 16108, 14570, 14985, 15649, 15735, 16602, 17741, 18425, 18491, 18588, 18717, 18718, 18850, 18943, 16069, 14530, 14940, 15609, 15695, 16062, 14525, 14933, 15604, 15688, 16064, 14527, 14935, 15606, 15690, 18685, 18065, 17851, 18686, 18025, 18435, 18113, 17951, 17715, 18485, 18408, 18365, 18583, 18417, 18388, 16267, 16268, 16269, 16228, 16229, 15911, 15799, 15800, 15990, 17745, 18121, 16117, 14577, 17857}, -- 168 [slips.storages[2]] = L{12421, 12549, 12677, 12805, 12933, 13911, 14370, 14061, 14283, 14163, 12429, 12557, 12685, 12813, 12941, 13924, 14371, 14816, 14296, 14175, 13934, 14387, 14821, 14303, 14184, 13935, 14388, 14822, 14304, 14185, 13876, 13787, 14006, 14247, 14123, 13877, 13788, 14007, 14248, 14124, 13908, 14367, 14058, 14280, 14160, 13909, 14368, 14059, 14281, 14161, 16113, 14573, 14995, 15655, 15740, 16115, 14575, 14997, 15657, 15742, 16114, 14574, 14996, 15656, 15741, 16116, 14576, 14998, 15658, 15743, 12818, 18198, 12946, 18043, 12690, 17659, 12296, 12434, 15471, 15472, 15473, 15508, 15509, 15510, 15511, 15512, 15513, 15514, 17710, 17595, 18397, 18360, 18222, 17948, 18100, 15475, 15476, 15477, 15488, 15961, 14815, 14812, 14813, 15244, 15240, 14488, 14905, 15576, 15661, 15241, 14489, 14906, 15577, 15662, 13927, 14378, 14076, 14308, 14180, 13928, 14379, 14077, 14309, 14181, 10438, 10276, 10320, 10326, 10367, 10439, 10277, 10321, 10327, 10368, 10440, 10278, 10322, 10328, 10369, 10441, 10279, 10323, 10329, 10370, 25734, 25735, 25736, 25737, 25738, 25739, 25740, 25741, 25742, 25743, 25744}, -- 155 @@ -42,6 +42,7 @@ slips.items = { [slips.storages[27]] = L{23398, 23465, 23532, 23599, 23666, 23399, 23466, 23533, 23600, 23667, 23400, 23467, 23534, 23601, 23668, 23401, 23468, 23535, 23602, 23669, 23402, 23469, 23536, 23603, 23670, 23403, 23470, 23537, 23604, 23671, 23404, 23471, 23538, 23605, 23672, 23405, 23472, 23539, 23606, 23673, 23406, 23473, 23540, 23607, 23674, 23407, 23474, 23541, 23608, 23675, 23408, 23475, 23542, 23609, 23676, 23409, 23476, 23543, 23610, 23677, 23410, 23477, 23544, 23611, 23678, 23411, 23478, 23545, 23612, 23679, 23412, 23479, 23546, 23613, 23680, 23413, 23480, 23547, 23614, 23681, 23414, 23481, 23548, 23615, 23682, 23415, 23482, 23549, 23616, 23683, 23416, 23483, 23550, 23617, 23684, 23417, 23484, 23551, 23618, 23685, 23418, 23485, 23552, 23619, 23686, 23419, 23486, 23553, 23620, 23687}, -- 110 [slips.storages[28]] = L{21515, 21561, 21617, 21670, 21718, 21775, 21826, 21879, 21918, 21971, 22027, 22082, 22108, 22214, 21516, 21562, 21618, 21671, 21719, 21776, 21827, 21880, 21919, 21972, 22028, 22083, 22109, 22215, 21517, 21563, 21619, 21672, 21720, 21777, 21828, 21881, 21920, 21973, 22029, 22084, 22110, 22216, 21518, 21564, 21620, 21673, 21721, 21778, 21829, 21882, 21921, 21974, 22030, 22085, 22111, 22217, 21519, 21565, 21621, 21674, 21722, 21779, 21830, 21883, 21922, 21975, 22031, 22086, 22107, 22218, 22089}, --71 [slips.storages[29]] = L{23085, 23152, 23219, 23286, 23353, 23086, 23153, 23220, 23287, 23354, 23087, 23154, 23221, 23288, 23355, 23088, 23155, 23222, 23289, 23356, 23089, 23156, 23223, 23290, 23357, 23090, 23157, 23224, 23291, 23358, 23091, 23158, 23225, 23292, 23359, 23092, 23159, 23226, 23293, 23360, 23093, 23160, 23227, 23294, 23361, 23094, 23161, 23228, 23295, 23362, 23095, 23162, 23229, 23296, 23363, 23096, 23163, 23230, 23297, 23364, 23097, 23164, 23231, 23298, 23365, 23098, 23165, 23232, 23299, 23366, 23099, 23166, 23233, 23300, 23367, 23100, 23167, 23234, 23301, 23368, 23101, 23168, 23235, 23302, 23369, 23102, 23169, 23236, 23303, 23370, 23103, 23170, 23237, 23304, 23371, 23104, 23171, 23238, 23305, 23372, 23105, 23172, 23239, 23306, 23373, 23106, 23173, 23240, 23307, 23374}, -- 110 + [slips.storages[30]] = L{23420, 23487, 23554, 23621, 23688, 23421, 23488, 23555, 23622, 23689, 23422, 23489, 23556, 23623, 23690, 23423, 23490, 23557, 23624, 23691, 23424, 23491, 23558, 23625, 23692, 23425, 23492, 23559, 23626, 23693, 23426, 23493, 23560, 23627, 23694, 23427, 23494, 23561, 23628, 23695, 23428, 23495, 23562, 23629, 23696, 23429, 23496, 23563, 23630, 23697, 23430, 23497, 23564, 23631, 23698, 23431, 23498, 23565, 23632, 23699, 23432, 23499, 23566, 23633, 23700, 23433, 23500, 23567, 23634, 23701, 23434, 23501, 23568, 23635, 23702, 23435, 23502, 23569, 23636, 23703, 23436, 23503, 23570, 23637, 23704, 23437, 23504, 23571, 23638, 23705, 23438, 23505, 23572, 23639, 23706, 23439, 23506, 23573, 23640, 23707, 23440, 23507, 23574, 23641, 23708, 23441, 23508, 23575, 23642, 23709}, -- 110 } function slips.get_slip_id(n) From ccb67ac0338ce53d75bfaba7844c3b3e227433a2 Mon Sep 17 00:00:00 2001 From: funkworkz Date: Fri, 18 Nov 2022 12:05:23 -0600 Subject: [PATCH 0880/1002] Update setbgm.lua Learned the song name from the new Orchestrion Key Item implemented in game. --- addons/setbgm/setbgm.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/setbgm/setbgm.lua b/addons/setbgm/setbgm.lua index 4f9566c4f0..da8f4648d4 100644 --- a/addons/setbgm/setbgm.lua +++ b/addons/setbgm/setbgm.lua @@ -50,8 +50,8 @@ music_types = { } songs = { - [25]='Voracious Resurgence Unknown 1', [26]='Voracious Resurgence Unknown 2', [27]='Voracious Resurgence Unknown 3', [28]='Voracious Resurgence Unknown 4', [29]="Devils' Delight", [30]="Odyssey - Bumba", [31]='Voracious Resurgence Unknown 5', [32]='Voracious Resurgence Unknown 6', - [33]='Voracious Resurgence Unknown 7', [34]="We Are Vana'diel", [35]='Goddessspeed', [36]='Sortie - +3 Area', + [25]='Voracious Resurgence Unknown 1', [26]='Voracious Resurgence Unknown 2', [27]='Voracious Resurgence Unknown 3', [28]='The Destiny Destroyers', [29]="Devils' Delight", [30]="Odyssey - Bumba", [31]='Voracious Resurgence Unknown 4', [32]='Voracious Resurgence Unknown 5', + [33]='Voracious Resurgence Unknown 6', [34]="We Are Vana'diel", [35]='Goddessspeed', [36]='Sortie - +3 Area', [40]='Cloister of Time and Souls', [41]='Royal Wanderlust', [42]='Snowdrift Waltz', [43]='Troubled Shadows', [44]='Where Lords Rule Not', [45]='Summers Lost', [46]='Goddess Divine', [47]='Echoes of Creation', [48]='Main Theme', [49]='Luck of the Mog', [50]='Feast of the Ladies', [51]='Abyssea - Scarlet Skies, Shadowed Plains', [52]='Melodies Errant', [53]='Shinryu', [54]='Everlasting Bonds', [55]='Provenance Watcher', [56]='Where it All Begins', [57]='Steel Sings, Blades Dance', [58]='A New Direction', [59]='The Pioneers', [60]='Into Lands Primeval - Ulbuka', [61]="Water's Umbral Knell", [62]='Keepers of the Wild', [63]='The Sacred City of Adoulin', [64]='Breaking Ground', [65]='Hades', [66]='Arciela', [67]='Mog Resort', [68]='Worlds Away', [69]="Distant Worlds (Nanaa Mihgo's version)", From a1dde863f4f3e6844833e980e34c2eb519d825fe Mon Sep 17 00:00:00 2001 From: Imisnew Date: Thu, 28 Jul 2022 11:34:51 +0900 Subject: [PATCH 0881/1002] Allow multiple 'text' children in a single XML tag. --- addons/libs/config.lua | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/addons/libs/config.lua b/addons/libs/config.lua index 7829c7f199..ee9befcdd2 100644 --- a/addons/libs/config.lua +++ b/addons/libs/config.lua @@ -277,19 +277,31 @@ function settings_table(node, settings, key, meta) return t end - if not node.children:all(function(n) + local function tag_or_comment(n) return n.type == 'tag' or n.type == 'comment' - end) and not (#node.children == 1 and node.children[1].type == 'text') then + end + local function text_or_comment(n) + return n.type == 'text' or n.type == 'comment' + end + + if not node.children:all(tag_or_comment) and not node.children:all(text_or_comment) then error('Malformatted settings file.') return t end -- TODO: Type checking necessary? merge should take care of that. - if #node.children == 1 and node.children[1].type == 'text' then - local val = node.children[1].value - if node.children[1].cdata then + if #node.children >= 1 and node.children:all(text_or_comment) then + if node.children:any(function(n) return n.cdata end) then meta.cdata:add(key) - return val + end + + local val = '' + for child in node.children:it() do + if child.type == 'comment' then + meta.comments[key] = child.value:trim() + elseif child.type == 'text' then + val = val .. child.value + end end if val:lower() == 'false' then From 4b611d207347b8dda4ce9a3f26351f05b8a6765f Mon Sep 17 00:00:00 2001 From: Chiaia Date: Fri, 2 Dec 2022 01:13:58 -0500 Subject: [PATCH 0882/1002] Slip 30 Support --- addons/findAll/findAll.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/findAll/findAll.lua b/addons/findAll/findAll.lua index 7d9879e3f4..6df4295437 100644 --- a/addons/findAll/findAll.lua +++ b/addons/findAll/findAll.lua @@ -192,7 +192,7 @@ storages_order = S(res.bags:map(string.gsub-{' ', ''} .. string.lower .. return index1 < index2 end) -storage_slips_order = L{'slip 01', 'slip 02', 'slip 03', 'slip 04', 'slip 05', 'slip 06', 'slip 07', 'slip 08', 'slip 09', 'slip 10', 'slip 11', 'slip 12', 'slip 13', 'slip 14', 'slip 15', 'slip 16', 'slip 17', 'slip 18', 'slip 19', 'slip 20', 'slip 21', 'slip 22', 'slip 23', 'slip 24', 'slip 25', 'slip 26', 'slip 27', 'slip 28', 'slip 29'} +storage_slips_order = L{'slip 01', 'slip 02', 'slip 03', 'slip 04', 'slip 05', 'slip 06', 'slip 07', 'slip 08', 'slip 09', 'slip 10', 'slip 11', 'slip 12', 'slip 13', 'slip 14', 'slip 15', 'slip 16', 'slip 17', 'slip 18', 'slip 19', 'slip 20', 'slip 21', 'slip 22', 'slip 23', 'slip 24', 'slip 25', 'slip 26', 'slip 27', 'slip 28', 'slip 29', 'slip30'} merged_storages_orders = storages_order + storage_slips_order + L{'key items'} function search(query, export) From 2b08be6d8bb2249a066afbb4cb961fa390ba591a Mon Sep 17 00:00:00 2001 From: Imisnew Date: Sat, 3 Dec 2022 00:42:39 +0900 Subject: [PATCH 0883/1002] Revert "[shortcuts] Pass valid commands through if target and command is valid" This reverts commit 3c94fd5613fabad7215173d0d497a310df48e5e9. --- addons/shortcuts/shortcuts.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/shortcuts/shortcuts.lua b/addons/shortcuts/shortcuts.lua index 9d05fa40e5..a2f5da526e 100644 --- a/addons/shortcuts/shortcuts.lua +++ b/addons/shortcuts/shortcuts.lua @@ -290,7 +290,7 @@ function command_logic(original,modified) windower.send_command('@input '..lastsent) return '',false end - elseif command2_list[command] or (command_list[command] and valid_target(potential_targ)) then + 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 From d1dc68cd4b13538fa778ad8528797e2b004c9337 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Fri, 2 Dec 2022 12:50:23 -0700 Subject: [PATCH 0884/1002] revert breaking [config] changes From adfc1f6acd039ca834d3517c45ccdb79e26206c9 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Fri, 2 Dec 2022 13:06:53 -0700 Subject: [PATCH 0885/1002] revert breaking [config] change -- but for real this time --- addons/libs/config.lua | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/addons/libs/config.lua b/addons/libs/config.lua index ee9befcdd2..7829c7f199 100644 --- a/addons/libs/config.lua +++ b/addons/libs/config.lua @@ -277,31 +277,19 @@ function settings_table(node, settings, key, meta) return t end - local function tag_or_comment(n) + if not node.children:all(function(n) return n.type == 'tag' or n.type == 'comment' - end - local function text_or_comment(n) - return n.type == 'text' or n.type == 'comment' - end - - if not node.children:all(tag_or_comment) and not node.children:all(text_or_comment) then + end) and not (#node.children == 1 and node.children[1].type == 'text') then error('Malformatted settings file.') return t end -- TODO: Type checking necessary? merge should take care of that. - if #node.children >= 1 and node.children:all(text_or_comment) then - if node.children:any(function(n) return n.cdata end) then + if #node.children == 1 and node.children[1].type == 'text' then + local val = node.children[1].value + if node.children[1].cdata then meta.cdata:add(key) - end - - local val = '' - for child in node.children:it() do - if child.type == 'comment' then - meta.comments[key] = child.value:trim() - elseif child.type == 'text' then - val = val .. child.value - end + return val end if val:lower() == 'false' then From d05a6928ef5f3faeda60b1ea20076c4b0033d61c Mon Sep 17 00:00:00 2001 From: Chiaia Date: Sat, 10 Dec 2022 03:44:17 -0500 Subject: [PATCH 0886/1002] Missing space fixed --- addons/findAll/findAll.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/findAll/findAll.lua b/addons/findAll/findAll.lua index 6df4295437..69167ea3c5 100644 --- a/addons/findAll/findAll.lua +++ b/addons/findAll/findAll.lua @@ -192,7 +192,7 @@ storages_order = S(res.bags:map(string.gsub-{' ', ''} .. string.lower .. return index1 < index2 end) -storage_slips_order = L{'slip 01', 'slip 02', 'slip 03', 'slip 04', 'slip 05', 'slip 06', 'slip 07', 'slip 08', 'slip 09', 'slip 10', 'slip 11', 'slip 12', 'slip 13', 'slip 14', 'slip 15', 'slip 16', 'slip 17', 'slip 18', 'slip 19', 'slip 20', 'slip 21', 'slip 22', 'slip 23', 'slip 24', 'slip 25', 'slip 26', 'slip 27', 'slip 28', 'slip 29', 'slip30'} +storage_slips_order = L{'slip 01', 'slip 02', 'slip 03', 'slip 04', 'slip 05', 'slip 06', 'slip 07', 'slip 08', 'slip 09', 'slip 10', 'slip 11', 'slip 12', 'slip 13', 'slip 14', 'slip 15', 'slip 16', 'slip 17', 'slip 18', 'slip 19', 'slip 20', 'slip 21', 'slip 22', 'slip 23', 'slip 24', 'slip 25', 'slip 26', 'slip 27', 'slip 28', 'slip 29', 'slip 30'} merged_storages_orders = storages_order + storage_slips_order + L{'key items'} function search(query, export) From 61c1db415b6e4a0c5c4e9d1531c0625bf475c7ba Mon Sep 17 00:00:00 2001 From: Byrth Date: Mon, 12 Dec 2022 10:53:28 -0500 Subject: [PATCH 0887/1002] Boxdestroyer update --- addons/boxdestroyer/messages.lua | 48 ++++++++++++++++---------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/addons/boxdestroyer/messages.lua b/addons/boxdestroyer/messages.lua index 01a7b69edd..b955bc6173 100644 --- a/addons/boxdestroyer/messages.lua +++ b/addons/boxdestroyer/messages.lua @@ -1,31 +1,31 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination" for the associated zone IDs - [100] = 8078, + [100] = 8066, [101] = 7516, - [102] = 7929, - [103] = 8104, - [104] = 8669, - [105] = 7720, - [106] = 8094, - [107] = 7555, - [108] = 7624, - [109] = 8487, - [110] = 7611, - [111] = 8588, - [112] = 8190, + [102] = 7917, + [103] = 8092, + [104] = 8657, + [105] = 7708, + [106] = 8082, + [107] = 7543, + [108] = 7612, + [109] = 8475, + [110] = 7599, + [111] = 8576, + [112] = 8178, [113] = 7939, - [114] = 7789, - [115] = 7885, - [116] = 7581, - [117] = 7588, - [118] = 8130, - [119] = 8367, - [120] = 7527, - [121] = 8107, + [114] = 7777, + [115] = 7873, + [116] = 7569, + [117] = 7576, + [118] = 8118, + [119] = 8355, + [120] = 7515, + [121] = 8095, [122] = 7445, - [123] = 7890, - [124] = 7841, - [125] = 7658, - [126] = 8074, + [123] = 7878, + [124] = 7829, + [125] = 7646, + [126] = 8062, [127] = 7362, [128] = 7517, [130] = 7581, From 15bf559b93d59e3c27221c15506b030388bad28c Mon Sep 17 00:00:00 2001 From: Byrth Date: Wed, 14 Dec 2022 19:12:15 -0500 Subject: [PATCH 0888/1002] update slips for 2022-12 --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 904ca10ccd..55ee0f3578 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757, 25909}, -- 192 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912, 3753}, -- 160 SE Skipped an index hence the 0 as one of the items + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912, 3753, 23806, 3754}, -- 162 SE Skipped an index hence the 0 as one of the items [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067, 21680, 22071}, -- 177 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, -- 115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, -- 115 From 052d19cd307a3a718ecea94d318fb1f24d1fb4ad Mon Sep 17 00:00:00 2001 From: Byrth Date: Sat, 7 Jan 2023 13:26:54 -0500 Subject: [PATCH 0889/1002] Add queue library --- addons/GearSwap/gearswap.lua | 15 +++-- addons/GearSwap/refresh.lua | 120 +++++++++++++++++------------------ 2 files changed, 68 insertions(+), 67 deletions(-) diff --git a/addons/GearSwap/gearswap.lua b/addons/GearSwap/gearswap.lua index 2d5d37129a..4d23192210 100644 --- a/addons/GearSwap/gearswap.lua +++ b/addons/GearSwap/gearswap.lua @@ -48,6 +48,7 @@ require 'logger' error = _raw.error require 'lists' +require 'queues' require 'sets' @@ -134,7 +135,7 @@ initialize_packet_parsing() windower.register_event('load',function() windower.debug('load') refresh_globals() - + if world.logged_in then refresh_user_env() if debugging.general then windower.send_command('@unload spellcast;') end @@ -152,11 +153,11 @@ windower.register_event('addon command',function (...) logit('\n\n'..tostring(os.clock)..table.concat({...},' ')) local splitup = {...} if not splitup[1] then return end -- handles //gs - + for i,v in pairs(splitup) do splitup[i] = windower.from_shift_jis(windower.convert_auto_trans(v)) end local cmd = table.remove(splitup,1):lower() - + if cmd == 'c' then if gearswap_disabled then return end if splitup[1] then @@ -278,7 +279,7 @@ end function incoming_chunk(id,data,modified,injected,blocked) windower.debug('incoming chunk '..id) - + if next_packet_events and next_packet_events.sequence_id ~= data:unpack('H',3) then if not next_packet_events.globals_update or next_packet_events.globals_update ~= data:unpack('H',3) then refresh_globals() @@ -301,7 +302,7 @@ function incoming_chunk(id,data,modified,injected,blocked) next_packet_events = nil end end - + if not injected and parse.i[id] then parse.i[id](data,blocked) end @@ -309,7 +310,7 @@ end function outgoing_chunk(id,original,data,injected,blocked) windower.debug('outgoing chunk '..id) - + if not blocked and parse.o[id] then parse.o[id](data,injected) end @@ -321,7 +322,7 @@ windower.register_event('outgoing chunk',outgoing_chunk) windower.register_event('status change',function(new,old) windower.debug('status change '..new) if gearswap_disabled or T{2,3,4}:contains(old) or T{2,3,4}:contains(new) then return end - + refresh_globals() equip_sets('status_change',nil,res.statuses[new].english,res.statuses[old].english) end) diff --git a/addons/GearSwap/refresh.lua b/addons/GearSwap/refresh.lua index 9fb5e95607..fd5798786d 100644 --- a/addons/GearSwap/refresh.lua +++ b/addons/GearSwap/refresh.lua @@ -61,38 +61,38 @@ end ----------------------------------------------------------------------------------- function load_user_files(job_id,user_file) job_id = tonumber(job_id) - + if current_file then user_pcall('file_unload',current_file) end - + for i in pairs(registered_user_events) do unregister_event_user(i) end - + for i in pairs(__raw.text.registry) do windower.text.delete(i) end - + for i in pairs(__raw.prim.registry) do windower.prim.delete(i) end - + current_file = nil sets = nil user_env = nil unhandled_command_events = {} --registered_user_events = {} include_user_path = nil - + language = 'english' -- Reset language to english when changing job files. refresh_globals() - + if job_id and res.jobs[job_id] then player.main_job_id = job_id update_job_names() end - + local path,base_dir,filename path,base_dir,filename = pathsearch({user_file}) @@ -104,7 +104,7 @@ function load_user_files(job_id,user_file) player.name..'.lua',short_job..'.lua',long_job..'.lua','default.lua'} path,base_dir,filename = pathsearch(tab) end - + if not path then current_file = nil sets = nil @@ -120,18 +120,18 @@ function load_user_files(job_id,user_file) show_swaps = show_swaps,debug_mode=debug_mode,include_path=user_include_path, register_unhandled_command=user_unhandled_command,move_spell_target=move_spell_target, language=language, - + -- Library functions - string=string,math=math,table=table,set=set,list=list,T=T,S=S,L=L,pack=pack,functions=functions, + string=string,math=math,table=table,set=set,list=list,queue=queue,T=T,S=S,L=L,Q=Q,pack=pack,functions=functions, os=os,texts=texts,bit=bit,type=type,tostring=tostring,tonumber=tonumber,pairs=pairs, ipairs=ipairs, print=print, add_to_chat=add_to_chat_user,unpack=unpack,next=next, select=select,lua_base_path=windower.addon_path,empty=empty,file=file, loadstring=loadstring,assert=assert,error=error,pcall=pcall,io=io,dofile=dofile, - + debug=debug,coroutine=coroutine,setmetatable=setmetatable,getmetatable=getmetatable, rawset=rawset,rawget=rawget,require=include_user, _libs=_libs, - + -- Player environment things buffactive=buffactive, player=player, @@ -145,12 +145,12 @@ function load_user_files(job_id,user_file) body=empty,hands=empty,ring1=empty,ring2=empty, back=empty,waist=empty,legs=empty,feet=empty}} } - + user_env['_G'] = user_env - + -- Try to load data/_
    .lua local funct, err = loadfile(path) - + -- If the file cannot be loaded, print the error and load the default. if funct == nil then print('User file problem: '..err) @@ -161,24 +161,24 @@ function load_user_files(job_id,user_file) current_file = filename print('GearSwap: Loaded your '..current_file..' file!') end - + setfenv(funct, user_env) - + -- Verify that funct contains functions. local status, plugin = pcall(funct) - + if not status then error('GearSwap: File failed to load: \n'..plugin) sets = nil return nil end - + _global.pretarget_cast_delay = 0 _global.precast_cast_delay = 0 _global.cancel_spell = false _global.current_event = 'get_sets' user_pcall('get_sets') - + gearswap_disabled = false sets = user_env.sets end @@ -204,10 +204,10 @@ function refresh_player(dt,user_event_flag) if not user_event_flag or dt > 0.5 then pl = windower.ffxi.get_player() if not pl or not pl.vitals then return end - + player_mob_table = windower.ffxi.get_mob_by_index(pl.index) if not player_mob_table then return end - + table.reassign(player,pl) for i,v in pairs(player.vitals) do player[i]=v @@ -221,7 +221,7 @@ function refresh_player(dt,user_event_flag) end player.nation_id = player.nation player.nation = res.regions[player.nation_id][language] or 'None' - + for i,v in pairs(player_mob_table) do if i == 'name' then player.mob_name = v @@ -229,12 +229,12 @@ function refresh_player(dt,user_event_flag) player[i] = v end end - + if player_mob_table.race ~= nil then player.race_id = player.race player.race = res.races[player.race][language] end - + -- If we have a pet, create or update the table info. if player_mob_table and player_mob_table.pet_index then local player_pet_table = windower.ffxi.get_mob_by_index(player_mob_table.pet_index) @@ -244,7 +244,7 @@ function refresh_player(dt,user_event_flag) pet.is_npc = nil pet.isvalid = true if pet.tp then pet.tp = pet.tp/10 end - + if avatar_element[pet.name] then pet.element = res.elements[avatar_element[pet.name]][language] else @@ -256,12 +256,12 @@ function refresh_player(dt,user_event_flag) else table.reassign(pet, {isvalid=false}) end - + if player.main_job_id == 18 or player.sub_job_id == 18 then local auto_tab if player.main_job_id == 18 then auto_tab = windower.ffxi.get_mjob_data() else auto_tab = windower.ffxi.get_sjob_data() end - + if auto_tab.name then for i,v in pairs(auto_tab) do if not T{'available_heads','attachments','available_frames','available_attachments','frame','head'}:contains(i) then @@ -298,7 +298,7 @@ function refresh_player(dt,user_event_flag) pet.attachments[res.items[id][language]] = true end end - + if pet.max_mp ~= 0 then pet.mpp = math.floor(pet.mp/pet.max_mp*100) else @@ -308,7 +308,7 @@ function refresh_player(dt,user_event_flag) elseif player.main_job_id == 23 then local species_id = windower.ffxi.get_mjob_data().species -- Should add instincts when they become available - + if species_id then player.species = {} for i,v in pairs(res.monstrosity[species_id]) do @@ -326,15 +326,15 @@ function refresh_player(dt,user_event_flag) player.species = nil end end - + -- This being nil does not cause a return, but items should not really be changing when zoning. local cur_equip = table.reassign({},items.equipment) - + -- Assign player.equipment to be the gear that has been sent out and the server currently thinks -- you are wearing. (the sent_out_equip for loop above). player.equipment = make_user_table() table.reassign(player.equipment,to_names_set(cur_equip)) - + -- Assign player.inventory to be keyed to item.inventory[i][language] and to have a value of count, similar to buffactive for i,bag in pairs(res.bags) do local bag_name = to_windower_bag_api(bag.en) @@ -345,18 +345,18 @@ function refresh_player(dt,user_event_flag) player.target = target_complete(windower.ffxi.get_mob_by_target('t')) player.subtarget = target_complete(windower.ffxi.get_mob_by_target('st')) player.last_subtarget = target_complete(windower.ffxi.get_mob_by_target('lastst')) + - - + table.reassign(fellow,target_complete(windower.ffxi.get_mob_by_target(''))) if fellow.name then fellow.isvalid = true else fellow.isvalid=false end - + table.reassign(buffactive,convert_buff_list(player.buffs)) - + for global_variable_name,extradatatable in pairs(_ExtraData) do if _G[global_variable_name] then for sub_variable_name,value in pairs(extradatatable) do @@ -396,7 +396,7 @@ function refresh_ffxi_info(dt,user_event_flag) world[i] = v end end - + for global_variable_name,extradatatable in pairs(_ExtraData) do if _G[global_variable_name] then for sub_variable_name,value in pairs(extradatatable) do @@ -477,25 +477,25 @@ function refresh_group_info(dt,user_event_flag) if not alliance or #alliance == 0 then alliance = make_alliance() end - + local c_alliance = make_alliance() - + local j = windower.ffxi.get_party() or {} - + c_alliance.leader = j.alliance_leader -- Test whether this works c_alliance[1].leader = j.party1_leader c_alliance[2].leader = j.party2_leader c_alliance[3].leader = j.party3_leader - + for i,v in pairs(j) do if type(v) == 'table' and v.mob and v.mob.race then v.mob.race_id = v.mob.race v.mob.race = res.races[v.mob.race][language] end - + local allyIndex local partyIndex - + -- For 'p#', ally index is 1, party index is the second char if i:sub(1,1) == 'p' and tonumber(i:sub(2)) then allyIndex = 1 @@ -505,7 +505,7 @@ function refresh_group_info(dt,user_event_flag) allyIndex = tonumber(i:sub(2,2))+1 partyIndex = tonumber(i:sub(3))+1 end - + if allyIndex and partyIndex then if v.mob and partybuffs[v.mob.index] then v.buffactive = convert_buff_list(partybuffs[v.mob.index].buffs) @@ -515,7 +515,7 @@ function refresh_group_info(dt,user_event_flag) c_alliance[allyIndex][partyIndex] = v c_alliance[allyIndex].count = c_alliance[allyIndex].count + 1 c_alliance.count = c_alliance.count + 1 - + if v.mob then if v.mob.id == c_alliance[1].leader then c_alliance[1].leader = v @@ -524,14 +524,14 @@ function refresh_group_info(dt,user_event_flag) elseif v.mob.id == c_alliance[3].leader then c_alliance[3].leader = v end - + if v.mob.id == c_alliance.leader then c_alliance.leader = v end end end end - + -- Clear the old structure while maintaining the party references: for ally_party = 1,3 do @@ -542,7 +542,7 @@ function refresh_group_info(dt,user_event_flag) end alliance.count = 0 alliance.leader = nil - + -- Reassign to the new structure table.reassign(alliance[1],c_alliance[1]) table.reassign(alliance[2],c_alliance[2]) @@ -582,15 +582,15 @@ end ----------------------------------------------------------------------------------- function convert_buff_list(bufflist) local buffarr = {} - for i,id in pairs(bufflist) do - if res.buffs[id] then -- For some reason we always have buff 255 active, which doesn't have an entry. + for _,id in pairs(bufflist) do + if res.buffs[id] then local buff = res.buffs[id][language]:lower() if buffarr[buff] then buffarr[buff] = buffarr[buff] +1 else buffarr[buff] = 1 end - + if buffarr[id] then buffarr[id] = buffarr[id] +1 else @@ -656,7 +656,7 @@ end function refresh_user_env(job_id) refresh_globals() if not job_id then job_id = windower.ffxi.get_player().main_job_id end - + if not job_id then windower.send_command('@wait 1;lua i '.._addon.name..' refresh_user_env') else @@ -678,17 +678,17 @@ function pathsearch(files_list) -- base directory search order: -- windower -- %appdata%/Windower/GearSwap - + -- sub directory search order: -- libs-dev (only in windower addon path) -- libs (only in windower addon path) -- data/player.name -- data/common -- data - + local gearswap_data = windower.addon_path .. 'data/' local gearswap_appdata = (os.getenv('APPDATA') or '') .. '/Windower/GearSwap/' - + local search_path = { [1] = windower.addon_path .. 'libs-dev/', [2] = windower.addon_path .. 'libs/', @@ -700,7 +700,7 @@ function pathsearch(files_list) [8] = gearswap_appdata, [9] = windower.windower_path .. 'addons/libs/' } - + local user_path local normal_path @@ -712,7 +712,7 @@ function pathsearch(files_list) user_path = basepath .. include_user_path .. '/' .. v end normal_path = basepath .. v - + if user_path and windower.file_exists(user_path) then return user_path,basepath,v elseif normal_path and windower.file_exists(normal_path) then @@ -722,6 +722,6 @@ function pathsearch(files_list) end end end - + return false end From 78d50e757d1d6604e1b7776f9378cab129370477 Mon Sep 17 00:00:00 2001 From: Byrth Date: Sat, 7 Jan 2023 13:29:48 -0500 Subject: [PATCH 0890/1002] Batch buff_details and add for party members --- addons/GearSwap/packet_parsing.lua | 132 +++++++++++++++++------------ addons/GearSwap/refresh.lua | 5 +- addons/GearSwap/statics.lua | 40 ++++----- 3 files changed, 101 insertions(+), 76 deletions(-) diff --git a/addons/GearSwap/packet_parsing.lua b/addons/GearSwap/packet_parsing.lua index 410ea7613c..3b9541d889 100644 --- a/addons/GearSwap/packet_parsing.lua +++ b/addons/GearSwap/packet_parsing.lua @@ -33,7 +33,7 @@ parse.i[0x00A] = function (data) windower.debug('zone change') command_registry = Command_Registry.new() table.clear(not_sent_out_equip) - + player.id = data:unpack('I',0x05) player.index = data:unpack('H',0x09) if player.main_job_id and player.main_job_id ~= data:byte(0xB5) and player.name and player.name == data:unpack('z',0x85) and not gearswap_disabled then @@ -49,7 +49,7 @@ parse.i[0x00A] = function (data) player.max_hp = data:unpack('I',0xE9) player.max_mp = data:unpack('I',0xED) update_job_names() - + world.zone_id = data:unpack('H',0x31) _ExtraData.world.conquest = false for i,v in pairs(region_to_zone_map) do @@ -63,9 +63,9 @@ parse.i[0x00A] = function (data) end weather_update(data:byte(0x69)) world.logged_in = true - + _ExtraData.world.in_mog_house = data:byte(0x81) == 1 - + _ExtraData.player.base_str = data:unpack('H',0xCD) _ExtraData.player.base_dex = data:unpack('H',0xCF) _ExtraData.player.base_vit = data:unpack('H',0xD1) @@ -80,7 +80,7 @@ parse.i[0x00A] = function (data) _ExtraData.player.add_int = data:unpack('h',0xE3) _ExtraData.player.add_mnd = data:unpack('h',0xE5) _ExtraData.player.add_chr = data:unpack('h',0xE7) - + _ExtraData.player.str = _ExtraData.player.base_str + _ExtraData.player.add_str _ExtraData.player.dex = _ExtraData.player.base_dex + _ExtraData.player.add_dex _ExtraData.player.vit = _ExtraData.player.base_vit + _ExtraData.player.add_vit @@ -89,7 +89,7 @@ parse.i[0x00A] = function (data) _ExtraData.player.mnd = _ExtraData.player.base_mnd + _ExtraData.player.add_mnd _ExtraData.player.chr = _ExtraData.player.base_chr + _ExtraData.player.add_chr refresh_ffxi_info() - + blank_0x063_v9_inc = true end @@ -115,7 +115,7 @@ parse.i[0x01B] = function (data) for job_id = 1,23 do player.jobs[to_windower_api(res.jobs[job_id].english)] = data:byte(job_id + 72) end - + local enc = data:unpack('H',0x61) local tab = {} for slot_id,slot_name in pairs(default_slot_map) do @@ -243,12 +243,12 @@ function parse_equip_chunk(chunk) if inv_slot == 0 then -- Unequipping local bag_id = items.equipment[equip_slot].bag_id inv_slot = items.equipment[equip_slot].slot - + if inv_slot == empty then return end -- unequipping something that was already unequipped? - + local inv = items[to_windower_compact(res.bags[bag_id].english)] if not inv[inv_slot] then inv[inv_slot] = make_empty_item_table(inv_slot) end - + inv[inv_slot].status = 0 -- Set the status to "unequipped" items.equipment[equip_slot] = {slot=empty,bag_id=0} else @@ -380,7 +380,7 @@ parse.i[0x061] = function (data) player.max_mp = data:unpack('I',9) player.main_job_id = data:byte(13) player.main_job_level = data:byte(14) - + _ExtraData.player.nation_id = data:byte(0x51) _ExtraData.player.nation = res.regions[_ExtraData.player.nation_id][language] or 'None' _ExtraData.player.base_str = data:unpack('H',0x15) @@ -407,7 +407,7 @@ parse.i[0x061] = function (data) _ExtraData.player.earth_resistance = data:unpack('h',0x3F) _ExtraData.player.water_resistance = data:unpack('h',0x41) _ExtraData.player.dark_resistance = data:unpack('h',0x43) - + _ExtraData.player.str = _ExtraData.player.base_str + _ExtraData.player.add_str _ExtraData.player.dex = _ExtraData.player.base_dex + _ExtraData.player.add_dex _ExtraData.player.vit = _ExtraData.player.base_vit + _ExtraData.player.add_vit @@ -415,7 +415,7 @@ parse.i[0x061] = function (data) _ExtraData.player.int = _ExtraData.player.base_int + _ExtraData.player.add_int _ExtraData.player.mnd = _ExtraData.player.base_mnd + _ExtraData.player.add_mnd _ExtraData.player.chr = _ExtraData.player.base_chr + _ExtraData.player.add_chr - + if player.sub_job_id ~= data:byte(15) then -- Subjob change event local temp_sub = player.sub_job @@ -463,7 +463,7 @@ parse.i[0x063] = function (data) newbuffs[i] = setmetatable({ name=res.buffs[buff_id].name, buff=copy_entry(res.buffs[buff_id]), - id = buff_id, + id=buff_id, time=t, date=os.date('*t',t), }, @@ -489,7 +489,7 @@ parse.i[0x063] = function (data) end end end - + -- Look for time-independent matches, which are assumedly a spell overwriting itself for n,new in pairs(newbuffs) do newbuffs[n].matched_imprecisely = nil @@ -504,7 +504,8 @@ parse.i[0x063] = function (data) end end end - + + local batch = L{} for n,new in pairs(newbuffs) do if new.matched_exactly then newbuffs[n].matched_exactly = nil @@ -517,7 +518,7 @@ parse.i[0x063] = function (data) end local buff_name = res.buffs[new.id][language] windower.debug('refresh buff '..buff_name..' ('..tostring(new.id)..')') - if not gearswap_disabled then + if false and not gearswap_disabled then refresh_globals() equip_sets('buff_refresh',nil,buff_name,new) end @@ -529,17 +530,14 @@ parse.i[0x063] = function (data) local buff_name = res.buffs[new.id][language] windower.debug('gain buff '..buff_name..' ('..tostring(new.id)..')') -- Need to figure out what I'm going to do with this: - if T{'terror','sleep','stun','petrification','charm','weakness'}:contains(buff_name:lower()) then + if T{'terror','sleep','stun','petrification','charm','weakness','lullaby'}:contains(buff_name:lower()) then for ts,v in pairs(command_registry) do if v.midaction then command_registry:delete_entry(ts) end end end - if not gearswap_disabled then - refresh_globals() - equip_sets('buff_change',nil,buff_name,true,new) - end + batch:append({name=buff_name,gain=true,tab=new}) end end for i,old in pairs(_ExtraData.player.buff_details) do @@ -550,10 +548,13 @@ parse.i[0x063] = function (data) end local buff_name = res.buffs[old.id][language] windower.debug('lose buff '..buff_name..' ('..tostring(old.id)..')') - if not gearswap_disabled then - refresh_globals() - equip_sets('buff_change',nil,buff_name,false,old) - end + batch:append({name=buff_name,gain=false,tab=old}) + end + end + if not gearswap_disabled and #batch > 0 then + refresh_globals() + for v,_ in batch:it() do + equip_sets('buff_change',nil,v.name,v.gain,v.tab) end end end @@ -575,29 +576,33 @@ parse.i[0x067] = function (data) end parse.i[0x068] = function (data) - if player.index == data:unpack('H',0x07) then -- You are the owner _ExtraData.pet.tp = data:unpack('H',0x11) end end parse.i[0x076] = function (data) - partybuffs = {} + _ExtraPartyData.buffs = {} + _ExtraPartyData.buff_details = {} for i = 0,4 do if data:unpack('I',i*48+5) == 0 then break else local index = data:unpack('H',i*48+5+4) - partybuffs[index] = { - id = data:unpack('I',i*48+5+0), - index = data:unpack('H',i*48+5+4), - buffs = {} - } + _ExtraPartyData.buffs[index] = {} + _ExtraPartyData.buff_details[index] = {} for n=1,32 do - partybuffs[index].buffs[n] = data:byte(i*48+5+16+n-1) + 256*( math.floor( data:byte(i*48+5+8+ math.floor((n-1)/4)) / 4^((n-1)%4) )%4) + local buff_id = data:byte(i*48+5+16+n-1) + 256*( math.floor( data:byte(i*48+5+8+ math.floor((n-1)/4)) / 4^((n-1)%4) )%4) + if buff_id ~= 255 and buff_id ~= 0 then + _ExtraPartyData.buffs[index][n] = buff_id + _ExtraPartyData.buff_details[index][n] = { + name=res.buffs[buff_id].name, + buff=copy_entry(res.buffs[buff_id]), + id=buff_id, + } + end end - - + if alliance[1] then local cur_player for n,m in pairs(alliance[1]) do @@ -606,17 +611,26 @@ parse.i[0x076] = function (data) break end end - local new_buffs = convert_buff_list(partybuffs[index].buffs) - if cur_player and cur_player.buffactive and not gearswap_disabled then + local new_buffs = convert_buff_list(_ExtraPartyData.buffs[index]) + if index == 1464 then + local newbuff_count = 0 + for _,v in pairs(new_buffs) do + newbuff_count = newbuff_count + 1 + end + end + if cur_player and cur_player.buffactive and not gearswap_disabled and + user_env and type(user_env['party_buff_change']) == 'function' then + -- Make sure the character existed before (with a buffactive list) - Avoids zoning. + -- This is also the heaviest event, so make sure the user is using it. local old_buffs = cur_player.buffactive - -- Make sure the character existed before (with a buffactive list) - Avoids zoning. + local batch = L{} for n,m in pairs(new_buffs) do if type(n) == 'number' and m ~= old_buffs[n] then if not old_buffs[n] or m > old_buffs[n] then -- gaining buff - equip_sets('party_buff_change',nil,cur_player,res.buffs[n][language],true,copy_entry(res.buffs[n])) + batch:append({player=cur_player,name=res.buffs[n][language],gain=true,tab=copy_entry(res.buffs[n])}) old_buffs[n] = nil else -- losing buff - equip_sets('party_buff_change',nil,cur_player,res.buffs[n][language],false,copy_entry(res.buffs[n])) + batch:append({player=cur_player,name=res.buffs[n][language],gain=false,tab=copy_entry(res.buffs[n])}) old_buffs[n] = nil end elseif type(n) ~= 'number' then @@ -624,18 +638,34 @@ parse.i[0x076] = function (data) old_buffs[n] = nil end end - + for n,m in pairs(old_buffs) do if type(n) == 'number' and m ~= new_buffs[n] then-- losing buff - equip_sets('party_buff_change',nil,cur_player,res.buffs[n][language],false,copy_entry(res.buffs[n])) + batch:append({player=cur_player,name=res.buffs[n][language],gain=false,tab=copy_entry(res.buffs[n])}) + end + end + if #batch > 0 then + refresh_globals() + for v,_ in batch:it() do + equip_sets('party_buff_change',nil,v.player,v.name,v.gain,v.tab) end end end if cur_player then - cur_player.buffactive = new_buffs + if cur_player.buffactive then + table.reassign(cur_player.buffactive, new_buffs) + else + cur_player.buffactive = new_buffs + end + end + if cur_player and cur_player.id ~= player.id then + if cur_player.buff_details then + table.reassign(cur_player.buff_details,_ExtraPartyData.buff_details[index]) + else + cur_player.buff_details = _ExtraPartyData.buff_details[index] + end end end - end end end @@ -647,7 +677,7 @@ function update_vitals(id, hp, mp, tp, hpp, mpp) player.vitals.tp = tp player.vitals.hpp = hpp player.vitals.mpp = mpp - + player.hp = hp player.mp = mp player.tp = tp @@ -702,9 +732,9 @@ parse.o[0x100] = function(data) local newmain = data:byte(5) if res.jobs[newmain] and newmain ~= 0 and newmain ~= player.main_job_id then windower.debug('job change') - + command_registry = Command_Registry.new() - + table.clear(not_sent_out_equip) table.clear(equip_list_history) table.clear(equip_list) @@ -716,10 +746,9 @@ parse.o[0x100] = function(data) end windower.send_command('lua i '.._addon.name..' load_user_files '..newmain) end - - + if gearswap_disabled then return end - + local newmain = data:byte(5) if res.jobs[newmain] and newmain ~= player.main_job_id then command_enable('main','sub','range','ammo','head','neck','lear','rear','body','hands','lring','rring','back','waist','legs','feet') -- enable all slots @@ -735,7 +764,6 @@ function initialize_packet_parsing() end if i == 0x63 and lastpacket and lastpacket:byte(5) ~= 9 then -- Not receiving an accurate buff line on load because the wrong 0x063 packet was sent last - end end end diff --git a/addons/GearSwap/refresh.lua b/addons/GearSwap/refresh.lua index fd5798786d..18040d1824 100644 --- a/addons/GearSwap/refresh.lua +++ b/addons/GearSwap/refresh.lua @@ -507,8 +507,9 @@ function refresh_group_info(dt,user_event_flag) end if allyIndex and partyIndex then - if v.mob and partybuffs[v.mob.index] then - v.buffactive = convert_buff_list(partybuffs[v.mob.index].buffs) + if v.mob and _ExtraPartyData.buffs[v.mob.index] then + v.buffactive = convert_buff_list(_ExtraPartyData.buffs[v.mob.index]) + v.buff_details = _ExtraPartyData.buff_details[v.mob.index] elseif v.mob and v.mob.index == player.index then v.buffactive = buffactive end diff --git a/addons/GearSwap/statics.lua b/addons/GearSwap/statics.lua index a81f428bee..b0fd4a0587 100644 --- a/addons/GearSwap/statics.lua +++ b/addons/GearSwap/statics.lua @@ -25,7 +25,7 @@ --SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- Convert the spells and job abilities into a referenceable list of aliases -- - + unify_prefix = {['/ma'] = '/ma', ['/magic']='/ma',['/jobability'] = '/ja',['/ja']='/ja',['/item']='/item',['/song']='/ma', ['/so']='/ma',['/ninjutsu']='/ma',['/weaponskill']='/ws',['/ws']='/ws',['/ra']='/ra',['/rangedattack']='/ra',['/nin']='/ma', ['/throw']='/ra',['/range']='/ra',['/shoot']='/ra',['/monsterskill']='/ms',['/ms']='/ms',['/pet']='/ja',['Monster']='Monster',['/bstpet']='/ja'} @@ -37,16 +37,16 @@ action_type_map = {['/ja']='Ability',['/jobability']='Ability',['/so']='Magic',[ equippable_item_bags = {res.bags:equippable(true):extract()} usable_item_bags = {res.bags:with('command','temporary'), table.extract(equippable_item_bags)} - + bag_string_lookup = {} for i,v in pairs(res.bags) do bag_string_lookup[to_windower_bag_api(v.en)]=i end - + bstpet_range = {min=672,max=798} -- Range of the JA resource devoted to BST jugpet abilities - + delay_map_to_action_type = {['Ability']=3,['Magic']=20,['Ranged Attack']=10,['Item']=10,['Monster Move']=10,['Interruption']=3} - + validabils = {} validabils['english'] = {['/ma'] = {}, ['/ja'] = {}, ['/ws'] = {}, ['/item'] = {}, ['/ra'] = {}, ['/ms'] = {}, ['/pet'] = {}, ['/trig'] = {}, ['/echo'] = {}} validabils['french'] = {['/ma'] = {}, ['/ja'] = {}, ['/ws'] = {}, ['/item'] = {}, ['/ra'] = {}, ['/ms'] = {}, ['/pet'] = {}, ['/trig'] = {}, ['/echo'] = {}} @@ -92,7 +92,7 @@ for i,v in pairs(res.items) do make_entry(v,i) end end - + -- Should transition these slot maps to be based off res.slots, but it's very unlikely to change. default_slot_map = T{'sub','range','ammo','head','body','hands','legs','feet','neck','waist', 'left_ear', 'right_ear', 'left_ring', 'right_ring','back'} @@ -126,14 +126,14 @@ encumbrance_map[0] = 0x79 -- Slots mapped onto encumbrance byte values. addendum_white = {[14]="Poisona",[15]="Paralyna",[16]="Blindna",[17]="Silena",[18]="Stona",[19]="Viruna",[20]="Cursna", [143]="Erase",[13]="Raise II",[140]="Raise III",[141]="Reraise II",[142]="Reraise III",[135]="Reraise"} - + addendum_black = {[253]="Sleep",[259]="Sleep II",[260]="Dispel",[162]="Stone IV",[163]="Stone V",[167]="Thunder IV", [168]="Thunder V",[157]="Aero IV",[158]="Aero V",[152]="Blizzard IV",[153]="Blizzard V",[147]="Fire IV",[148]="Fire V", [172]="Water IV",[173]="Water V",[255]="Break"} resources_ranged_attack = {id="0",index="0",prefix="/range",english="Ranged",german="Fernwaffe",french="Attaque à dist.",japanese="飛び道具",type="Misc",element="None",targets=S{"Enemy"}} - + -- _globals -- user_data_table = { __newindex = function(tab, key, val) @@ -145,16 +145,6 @@ user_data_table = { end } ---[[eq_data_table = { - __newindex = function(tab, key, val) - rawset(tab, slot_map[user_key_filter(key)], newtab) - end, - - __index = function(tab, key) - return rawget(tab, slot_map[user_key_filter(key)]) - end - }]] - slot_map = make_user_table() slot_map.main = 0 @@ -232,6 +222,12 @@ _ExtraData = { pet = {}, world = {in_mog_house = false,conquest=false}, } +-- _ExtraPartyData is the same, but for the party. +-- These structures are necessarily indexed by player index. +_ExtraPartyData = { + buffs = {}, + buff_details = {}, +} unbridled_learning_set = {['Thunderbolt']=true,['Harden Shell']=true,['Absolute Terror']=true, ['Gates of Hades']=true,['Tourbillion']=true,['Pyric Bulwark']=true,['Bilgestorm']=true, @@ -334,7 +330,7 @@ universal_tool_map = { ['Yain: Ichi'] = res.items[2972], } -region_to_zone_map = { +region_to_zone_map = { [4] = S{100,101,139,140,141,142,167,190}, [5] = S{102,103,108,193,196,248}, [6] = S{1,2,104,105,149,150,195}, @@ -355,7 +351,7 @@ region_to_zone_map = { [22] = S{11,12,13}, [24] = S{24,25,26,27,28,29,30,31,32}, } - + function initialize_globals() local pl = windower.ffxi.get_player() @@ -375,14 +371,14 @@ function initialize_globals() if not player.jobs then player.jobs = {} end if not player.merits then player.merits = {} end end - + player.equipment = make_user_table() pet = make_user_table() pet.isvalid = false fellow = make_user_table() fellow.isvalid = false partybuffs = {} - + -- GearSwap effectively needs to maintain two inventory structures: -- one is the proposed current inventory based on equip packets sent to the server, -- the other is the currently reported inventory based on packets sent from the server. From d14a40de365ce9c90ede66124a8b355ec31264e4 Mon Sep 17 00:00:00 2001 From: Byrth Date: Sat, 7 Jan 2023 13:29:58 -0500 Subject: [PATCH 0891/1002] Fix bug in move_spell_target() --- addons/GearSwap/user_functions.lua | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/addons/GearSwap/user_functions.lua b/addons/GearSwap/user_functions.lua index afdcf84816..2062955ddc 100644 --- a/addons/GearSwap/user_functions.lua +++ b/addons/GearSwap/user_functions.lua @@ -77,10 +77,10 @@ function move_spell_target(position_table) error('\nGearSwap: move_spell_target() is only valid in the precast function', 2) return end - + if type(position_table) == 'table' and type(position_table.x or position_table.X) == 'number' and type(position_table.y or position_table.Y) == 'number' and - type(position_table.z or positino_table.Z) == 'number' then + type(position_table.z or position_table.Z) == 'number' then _global.target_arrow.x = position_table.x or position_table.X _global.target_arrow.y = position_table.y or position_table.Y _global.target_arrow.z = position_table.z or position_table.Z @@ -160,13 +160,13 @@ function enable(...) error('\nGearSwap: enable error, passed an unrecognized slot name. ('..tostring(v)..')',2) end end - + return sending_table end function user_enable(...) local sending_table = enable(...) - + if table.length(sending_table) > 0 then equip(sending_table) end @@ -175,7 +175,7 @@ end function command_enable(...) local sending_table = enable(...) - + if table.length(sending_table) > 0 then refresh_globals() equip_sets('equip_command',nil,sending_table) @@ -223,7 +223,7 @@ function print_set(set,title) end end end - + if #set == table.length(set) then -- If it is a list (keyed by continuous whole number starting at 1), then print it out in order for key,value in ipairs(set) do print_element(key,value) @@ -235,7 +235,7 @@ function print_set(set,title) print_element(k,set[k]) end end - for key,value in pairs(set) do + for key,_ in pairs(set) do if not slot_map[key] then print_element(key,set[key]) end @@ -301,21 +301,21 @@ function include_user(str, load_include_in_this_table) if not (type(str) == 'string') then error('\nGearSwap: include() was passed an invalid value ('..tostring(str)..'). (must be a string)', 2) end - + str = str:lower() if type(package.loaded[str]) == 'table' then return package.loaded[str] elseif T{'pack'}:contains(str) then return end - + if str:sub(-4)~='.lua' then str = str..'.lua' end local path, loaded_values = pathsearch({str}) - + if not path then error('\nGearSwap: Cannot find the include file ('..tostring(str)..').', 2) end - + local f, err = loadfile(path) if f and not err then if load_include_in_this_table and type(load_include_in_this_table) == 'table' then @@ -358,7 +358,7 @@ function user_midaction(bool) return true, v.spell end end - + return false end @@ -390,7 +390,7 @@ function add_to_chat_user(num,str) -- It only needs the number. num=8 end - + if language == 'japanese' then msg.add_to_chat(num,windower.to_shift_jis(str)) else @@ -420,4 +420,4 @@ user_windower = {register_event = register_event_user, raw_register_event = raw_ user_coroutine = coroutine user_coroutine.sleep = user_sleep user_coroutine.yield = user_yield -setmetatable(user_windower,{__index=windower}) \ No newline at end of file +setmetatable(user_windower,{__index=windower}) From 22cbc86d8421aee63c80549fbd72e71e6da3a4dc Mon Sep 17 00:00:00 2001 From: Byrth Date: Sat, 7 Jan 2023 13:32:57 -0500 Subject: [PATCH 0892/1002] add disable check to check_spell() for gear spells --- addons/GearSwap/helper_functions.lua | 72 +++++++++++++++------------- 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/addons/GearSwap/helper_functions.lua b/addons/GearSwap/helper_functions.lua index 0034d6031a..9732048843 100644 --- a/addons/GearSwap/helper_functions.lua +++ b/addons/GearSwap/helper_functions.lua @@ -148,7 +148,7 @@ end function is_slot_key(k) return slot_map[k] end - + ----------------------------------------------------------------------------------- ----Name: make_empty_item_table(slot) @@ -273,7 +273,7 @@ function update_job_names() player.job = player.main_job..'/'..player.sub_job end - + ----------------------------------------------------------------------------------- ----Name: get_default_slot(k) -- Given a generally known slot key, return the default version of that key. @@ -325,7 +325,7 @@ function set_merge(respect_disable, baseSet, ...) end end end - + return baseSet end @@ -349,7 +349,7 @@ function parse_set_to_keys(str) if type(str) == 'table' then str = table.concat(str, ' ') end - + -- Parsing results get pushed into the result list. local result = L{} @@ -358,7 +358,7 @@ function parse_set_to_keys(str) local stop local sep = '.' local count = 0 - + -- Loop as long as remainder hasn't been nil'd or reduced to 0 characters, but only to a maximum of 30 tries. while remainder ~= "" and count < 30 do -- Try aaa.bbb set names first @@ -369,7 +369,7 @@ function parse_set_to_keys(str) -- "remainder" is everything after that result:append(key) end - + -- Then try aaa['bbb'] set names. -- Be sure to account for both single and double quote enclosures. -- Ignore periods contained within quote strings. @@ -397,7 +397,7 @@ function parse_set_to_keys(str) end result:append(key) end - + count = count +1 end @@ -444,11 +444,11 @@ end function initialize_arrow_offset(mob_table) local backtab = {} local arrow = windower.ffxi.get_info().target_arrow - + if arrow.x == 0 and arrow.y == 0 and arrow.z == 0 then return arrow end - + backtab.x = arrow.x-mob_table.x backtab.y = arrow.y-mob_table.y backtab.z = arrow.z-mob_table.z @@ -473,11 +473,11 @@ function assemble_action_packet(target_id,target_index,category,spell_id,arrow_o outstr = outstr..string.char( (target_id%256), math.floor(target_id/256)%256, math.floor( (target_id/65536)%256) , math.floor( (target_id/16777216)%256) ) outstr = outstr..string.char( (target_index%256), math.floor(target_index/256)%256) outstr = outstr..string.char( (category%256), math.floor(category/256)%256) - + if category == 16 then spell_id = 0 end - + outstr = outstr..string.char( (spell_id%256), math.floor(spell_id/256)%256)..string.char(0,0) .. 'fff':pack(arrow_offset.x,arrow_offset.z,arrow_offset.y) return outstr end @@ -524,7 +524,7 @@ end function assemble_menu_item_packet(target_id,target_index,...) local outstr = string.char(0x36,0x20,0,0) -- Message is coming out too short by 12 characters - + -- Target ID outstr = outstr.."I":pack(target_id) local item_ids,counts,count = {...},{},0 @@ -534,7 +534,7 @@ function assemble_menu_item_packet(target_id,target_index,...) count = count + 1 end end - + local unique_items = 0 for i,v in pairs(counts) do outstr = outstr.."I":pack(v) @@ -547,9 +547,9 @@ function assemble_menu_item_packet(target_id,target_index,...) while #outstr < 0x30 do outstr = outstr..string.char(0) end - + -- Inventory Index for the one unit - + for i,v in pairs(counts) do inventory_index = find_inventory_item(i) if inventory_index then @@ -685,7 +685,7 @@ function filter_pretarget(action) msg.debugging("Unable to execute command. You do not have access to that monsterskill ("..(res.monster_skills[action.id][language] or action.id)..")") return false end - + if err then msg.debugging(err) end @@ -705,9 +705,15 @@ end ---- false if the spell is not currently accessible ----------------------------------------------------------------------------------- function check_spell(available_spells,spell) - -- Filter for spells that you do not know. Exclude Impact / Dispelga. + -- Filter for spells that you do not know. + -- Exclude Impact / Dispelga / Honor March if the respective slots are enabled. + -- Need to add logic to check whether the equipment is already on local spell_jobs = copy_entry(res.spells[spell.id].levels) - if not available_spells[spell.id] and not (spell.id == 503 or spell.id == 417 or spell.id == 360) then + if not available_spells[spell.id] and not ( + (not disable_table[5] and not disable_table[4] and spell.id == 503) or -- Body + Head + Impact + (not disable_table[2] and spell.id == 417) or -- Range + Honor March + ((not disable_table[0] or not disable_table[1]) and spell.id == 360) -- Main or Sub + Dispelga + ) then return false,"Unable to execute command. You do not know that spell ("..(res.spells[spell.id][language] or spell.id)..")" -- Filter for spells that you know, but do not currently have access to elseif (not spell_jobs[player.main_job_id] or not (spell_jobs[player.main_job_id] <= player.main_job_level or @@ -883,7 +889,7 @@ end function cmd_reg:find_by_time(target_time) local time_stamp,ts target_time = target_time or os.time() - + -- Iterate over command_registry looking for the spell with the closest timestamp. -- Call aftercast with this spell's information (interrupted) if one is found. for i,v in pairs(self) do @@ -951,14 +957,14 @@ 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 == 12 or act.category == 2 then spell = copy_entry(resources_ranged_attack) else @@ -975,13 +981,13 @@ function get_spell(act) else spell = {name=tostring(msg_ID)} end - + return spell end - + local fields = fieldsearch(res.action_messages[msg_ID].english) -- ENGLISH - + if table.contains(fields,'spell') then spell = copy_entry(res.spells[abil_ID]) if act.category == 4 then spell.recast = act.recast end @@ -1011,7 +1017,7 @@ function get_spell(act) elseif msg_ID == 328 then spell = copy_entry(res.job_abilities[effect_val]) -- BPs that are out of range end - + if table.contains(fields,'item') then if spell then @@ -1023,12 +1029,12 @@ function get_spell(act) spell = spell_complete(spell) end end - + if spell then spell.name = spell[language] spell.interrupted = false end - + return spell end @@ -1054,7 +1060,7 @@ function spell_complete(rline) -- Entrust allows Indi- spells to be cast on party members rline.targets.Party = true end - + if rline == nil then return {tpaftercast = player.tp, mpaftercast = player.mp, mppaftercast = player.mpp} end @@ -1064,18 +1070,18 @@ function spell_complete(rline) elseif not rline.tp_cost or rline.tp_cost == -1 then rline.tp_cost = 0 end - + if rline.skill and tonumber(rline.skill) then rline.skill = res.skills[rline.skill][language] end - + if rline.element and tonumber(rline.element) then rline.element = res.elements[rline.element][language] end - + if rline.tp_cost == 0 then rline.tpaftercast = player.tp else rline.tpaftercast = player.tp - rline.tp_cost end - + if rline.mp_cost == 0 then rline.mpaftercast = player.mp rline.mppaftercast = player.mpp @@ -1083,7 +1089,7 @@ function spell_complete(rline) rline.mpaftercast = player.mp - rline.mp_cost rline.mppaftercast = (player.mp - rline.mp_cost)/player.max_mp end - + return rline end From c384750ac2e4201040fcc730b09f464c6f266b5c Mon Sep 17 00:00:00 2001 From: Byrth Date: Sat, 7 Jan 2023 13:33:12 -0500 Subject: [PATCH 0893/1002] I just deleted dead code --- addons/GearSwap/flow.lua | 81 ++++++++++++---------------------------- 1 file changed, 24 insertions(+), 57 deletions(-) diff --git a/addons/GearSwap/flow.lua b/addons/GearSwap/flow.lua index ef5a1eecd1..dcc3459b33 100644 --- a/addons/GearSwap/flow.lua +++ b/addons/GearSwap/flow.lua @@ -47,16 +47,16 @@ function equip_sets(swap_type,ts,...) local val2 = var_inps[2] table.reassign(_global,command_registry[ts] or {pretarget_cast_delay = 0,precast_cast_delay=0,cancel_spell = false, new_target=false,target_arrow={x=0,y=0,z=0}}) _global.current_event = tostring(swap_type) - + if _global.current_event == 'precast' and val1 and val1.english and val1.english:find('Geo-') then _global.target_arrow = initialize_arrow_offset(val1.target) end - + windower.debug(tostring(swap_type)..' enter') if showphase or debugging.general then msg.debugging(8,windower.to_shift_jis(tostring(swap_type))..' enter') end - + local cur_equip = table.reassign({},update_equipment()) - + table.reassign(equip_list,{}) table.reassign(player.equipment,to_names_set(cur_equip)) for i,v in pairs(slot_map) do @@ -64,7 +64,7 @@ function equip_sets(swap_type,ts,...) player.equipment[i] = player.equipment[toslotname(v)] end end - + logit('\n\n'..tostring(os.clock)..'(15) equip_sets: '..tostring(swap_type)) if val1 then if type(val1) == 'table' and val1.english then @@ -83,20 +83,20 @@ function equip_sets(swap_type,ts,...) else logit(' : nil-or-false') end - + if type(swap_type) == 'string' then msg.debugging("Entering "..swap_type) else msg.debugging("Entering User Event "..tostring(swap_type)) end - + if not val1 then val1 = {} if debugging.general then msg.debugging(8,'val1 error') end end - + if type(swap_type) == 'function' then results = { pcall(swap_type,...) } if not table.remove(results,1) then error('\nUser Event Error: '..results[1]) end @@ -105,48 +105,15 @@ function equip_sets(swap_type,ts,...) else user_pcall(swap_type,...) end - ---[[ local c - if type(swap_type) == 'function' then - c = coroutine.create(swap_type) - elseif swap_type == 'equip_command' then - equip(val1) - elseif type(swap_type) == 'string' and user_env[swap_type] and type(user_env[swap_type]) == 'function' then - c = coroutine.create(user_env[swap_type]) - elseif type(swap_type) == 'string' and user_env[swap_type] then - msg.addon_msg(123,windower.to_shift_jis(tostring(str))..'() exists but is not a function') - end - - if c then - while coroutine.status(c) == 'suspended' do - local err, typ, val = coroutine.resume(c,unpack(var_inputs)) - if not err then - error('\nGearSwap has detected an error in the user function '..tostring(swap_type)..':\n'..typ) - elseif typ then - if typ == 'sleep' and type(val) == 'number' and val >= 0 then - -- coroutine slept - err, typ, val = coroutine.schedule(c,val) - else - -- Someone yielded or slept with a nonsensical argument. - err, typ, val = coroutine.resume(c) - end - else - -- coroutine finished - end - end - end]] - - + if type(swap_type) == 'string' and (swap_type == 'pretarget' or swap_type == 'filtered_action') then -- Target may just have been changed, so make the ind now. ts = command_registry:new_entry(val1) --- elseif type(swap_type) == 'string' and swap_type == 'precast' and not command_registry[ts] and debugging.command_registry then --- print_set(spell,'precast nil error') -- spell's scope changed to local end - + if player.race ~= 'Precomposed NPC' then -- Short circuits the routine and gets out before equip processing -- if there's no swapping to be done because the user is a monster. - + for v,i in pairs(default_slot_map) do if equip_list[i] and encumbrance_table[v] then not_sent_out_equip[i] = equip_list[i] @@ -154,19 +121,19 @@ function equip_sets(swap_type,ts,...) msg.debugging(i..' slot was not equipped because you are encumbered.') end end - + table.update(equip_list_history,equip_list) - + -- Attempts to identify the player-specified item in inventory -- Starts with (i=slot name, v=item name) -- Ends with (i=slot id and v={bag_id=bag_id, slot=inventory slot}). local equip_next,priorities = unpack_equip_list(equip_list,cur_equip) - + if (_settings.show_swaps and table.length(equip_next) > 0) or _settings.demo_mode then --and table.length(equip_next)>0 then local tempset = to_names_set(equip_next) print_set(tempset,tostring(swap_type)) end - + if (buffactive.charm or player.charmed) or (player.status == 2 or player.status == 3) then -- dead or engaged dead statuses local failure_reason if (buffactive.charm or player.charmed) then @@ -208,13 +175,13 @@ function equip_sets(swap_type,ts,...) windower.packets.inject_outgoing(command_registry[ts].proposed_packet:byte(1),command_registry[ts].proposed_packet) end end - + windower.debug(tostring(swap_type)..' exit') - + if type(swap_type) == 'function' then return unpack(results) end - + return equip_sets_exit(swap_type,ts,val1) end @@ -236,7 +203,7 @@ function equip_sets_exit(swap_type,ts,val1) end if type(swap_type) == 'string' then if swap_type == 'pretarget' then - + if command_registry[ts].cancel_spell then msg.debugging("Action canceled ("..storedcommand..' '..val1.target.raw..")") storedcommand = nil @@ -246,11 +213,11 @@ function equip_sets_exit(swap_type,ts,val1) msg.debugging('This case should not be hittable - 1') return true end - + if command_registry[ts].new_target then val1.target = command_registry[ts].new_target -- Switch target, if it is requested. end - + -- Compose a proposed packet for the given action (this should be possible after pretarget) command_registry[ts].spell = val1 if val1.target and val1.target.id and val1.target.index and val1.prefix and unify_prefix[val1.prefix] then @@ -275,7 +242,7 @@ function equip_sets_exit(swap_type,ts,val1) command_registry[ts].proposed_packet = assemble_action_packet(val1.target.id,val1.target.index,outgoing_action_category_table[unify_prefix[val1.prefix]],val1.id,command_registry[ts].target_arrow) if not command_registry[ts].proposed_packet then command_registry:delete_entry(ts) - + msg.debugging("Unable to create a packet for this command because the target is still invalid after pretarget ("..storedcommand..' '..val1.target.raw..")") storedcommand = nil return storedcommand..' '..val1.target.raw @@ -285,7 +252,7 @@ function equip_sets_exit(swap_type,ts,val1) msg.debugging(8,"Hark, what weird prefix through yonder window breaks? "..tostring(val1.prefix)) end end - + if ts and command_registry[ts] and val1.target then if st_targs[val1.target.raw] then -- st targets @@ -439,4 +406,4 @@ end function send_action(ts) command_registry[ts].midaction = true equip_sets('midcast',ts,command_registry[ts].spell) -end \ No newline at end of file +end From d7f61c16cb5ccd50c8d098d9b967018531b83113 Mon Sep 17 00:00:00 2001 From: Byrth Date: Sat, 7 Jan 2023 13:40:54 -0500 Subject: [PATCH 0894/1002] un-disable buff_refresh events --- addons/GearSwap/packet_parsing.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/GearSwap/packet_parsing.lua b/addons/GearSwap/packet_parsing.lua index 3b9541d889..7991a67195 100644 --- a/addons/GearSwap/packet_parsing.lua +++ b/addons/GearSwap/packet_parsing.lua @@ -518,7 +518,7 @@ parse.i[0x063] = function (data) end local buff_name = res.buffs[new.id][language] windower.debug('refresh buff '..buff_name..' ('..tostring(new.id)..')') - if false and not gearswap_disabled then + if not gearswap_disabled then refresh_globals() equip_sets('buff_refresh',nil,buff_name,new) end From 76ed5a3d091b55e8b866bd66f1748667b3c1006a Mon Sep 17 00:00:00 2001 From: Byrth Date: Sat, 7 Jan 2023 13:54:33 -0500 Subject: [PATCH 0895/1002] add comment --- addons/GearSwap/packet_parsing.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/GearSwap/packet_parsing.lua b/addons/GearSwap/packet_parsing.lua index 7991a67195..3f042a07b1 100644 --- a/addons/GearSwap/packet_parsing.lua +++ b/addons/GearSwap/packet_parsing.lua @@ -531,6 +531,8 @@ parse.i[0x063] = function (data) windower.debug('gain buff '..buff_name..' ('..tostring(new.id)..')') -- Need to figure out what I'm going to do with this: if T{'terror','sleep','stun','petrification','charm','weakness','lullaby'}:contains(buff_name:lower()) then + --Weakness is technically incorrect, because monsters can afflict players with weakness without killing them. + --However, it is being used to detect when players die so for the moment it must stay. for ts,v in pairs(command_registry) do if v.midaction then command_registry:delete_entry(ts) From f9738e46f790d335b083aa97af0ec2384669a33e Mon Sep 17 00:00:00 2001 From: Byrth Date: Thu, 12 Jan 2023 07:18:07 -0500 Subject: [PATCH 0896/1002] Make send no longer error when logged out --- addons/send/send.lua | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/addons/send/send.lua b/addons/send/send.lua index 8df543b72c..7289c78f71 100644 --- a/addons/send/send.lua +++ b/addons/send/send.lua @@ -15,7 +15,7 @@ windower.register_event('addon command',function (...) local qual = table.remove(broken_init,1) local player = windower.ffxi.get_player() - if qual:lower()==player['name']:lower() then + if player and qual:lower()==player['name']:lower() then if broken_init ~= nil then relevant_msg(table.concat(broken_init,' ')) end @@ -41,12 +41,12 @@ windower.register_event('ipc message',function (msg) local qual = table.remove(broken,1) local player = windower.ffxi.get_player() - if qual:lower()==player.name:lower() then + if player and qual:lower()==player.name:lower() then relevant_msg(table.concat(broken,' ')) end if string.char(qual:byte(1)) == '@' then local arg = string.char(qual:byte(2, qual:len())) - if arg:upper() == player.main_job:upper() then + if player and arg:upper() == player.main_job:upper() then if broken ~= nil then relevant_msg(table.concat(broken,' ')) end @@ -85,8 +85,6 @@ function split(msg, match) end function relevant_msg(msg) - local player = windower.ffxi.get_player() - if msg:sub(1,2)=='//' then windower.send_command(msg:sub(3)) elseif msg:sub(1,1)=='/' then From 586871f268fd9bbd1cc7847438937f946abec5e1 Mon Sep 17 00:00:00 2001 From: Posimagi Date: Wed, 18 Jan 2023 23:29:10 -0800 Subject: [PATCH 0897/1002] [craft] Upgraded create_recipes.py to python3 and made it robust enough to not break on recipe(s) with unknown ingredients (though the output is not useful--not that it could be crafted anyway). --- addons/craft/create_recipes.py | 34 ++++++++++++++++++++-------------- addons/craft/slpp.py | 20 ++++++++++++++------ 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/addons/craft/create_recipes.py b/addons/craft/create_recipes.py index 9a424ff667..cc02c28158 100644 --- a/addons/craft/create_recipes.py +++ b/addons/craft/create_recipes.py @@ -1,4 +1,4 @@ -import urllib2 +import urllib.request from bs4 import BeautifulSoup from slpp import slpp as lua import os @@ -36,22 +36,27 @@ def get_recipe(row): 'Glimmer Crystal', 'Shadow Crystal', ] - y, r, c, i = [ + result, _, recipe = [ td for td in row.findAll('td') ] - name = str(y.findAll('a')[0]['title']) + name = str(result.findAll('a')[0]['title']) crystal = None ingredients = [] - for li in i.findAll('li'): + for li in recipe.findAll('li'): english = str(li.findAll('a')[0]['title']) if english in crystals: crystal = english continue - if li.text[-1].isdigit() and not "Kit" in english: - for n in range(int(li.text[-1])): + try: + if li.text is None: + ingredients.append("unknown") # ingredient is "Question Mark", e.g. for Pagodite + elif li.text[-1].isdigit() and not "Kit" in english: + for n in range(int(li.text[-1])): + ingredients.append(english) + else: ingredients.append(english) - else: - ingredients.append(english) + except IndexError: + return None return [(name, crystal, ingredients)] def get_sphere_recipe(row): @@ -99,7 +104,7 @@ def get_recipes_from_rows(rows, spheres=False): def get_recipes_from_soup(soup, spheres=False): string = "Sphere Obtained" if spheres else "Synthesis Information" - lengths = [4, 5, 6, 7] if spheres else [4] + lengths = [4, 5, 6, 7] if spheres else [3] subtables = [ descendant.parent.parent.parent for descendant in soup.descendants @@ -188,6 +193,7 @@ def fix_recipes(recipes): sorted.append(inverted[ingredient]) else: sorted.append(get_item(ingredient, inverted)) + sorted = list(filter(lambda item: item is not None, sorted)) sorted.sort() ingredients = [ items[ingredient]['en'] @@ -205,7 +211,7 @@ def build_recipe_string(name, crystal, ingredients): def save_recipes(recipes): with open('recipes.lua', 'w') as fd: fd.write("return {\n") - for key in sorted(recipes.iterkeys()): + for key in sorted(recipes.keys()): fd.write(build_recipe_string(key, *recipes[key])) fd.write("}\n") @@ -213,12 +219,12 @@ def get_recipes(craft, spheres=False): base = "https://www.bg-wiki.com/bg/" name = "%s.html" % craft if not os.path.exists(name): - req = urllib2.Request(base + craft, headers=hdr) + req = urllib.request.Request(base + craft, headers=hdr) try: - page = urllib2.urlopen(req).read() - except urllib2.HTTPError, e: + page = urllib.request.urlopen(req).read() + except urllib.request.HTTPError: return - with open(name, 'w') as fd: + with open(name, 'wb') as fd: fd.write(page) with open(name, 'r') as fd: page = fd.read() diff --git a/addons/craft/slpp.py b/addons/craft/slpp.py index 3da97b8199..ea9c4279b9 100644 --- a/addons/craft/slpp.py +++ b/addons/craft/slpp.py @@ -48,6 +48,10 @@ def __init__(self): self.tab = '\t' def decode(self, text): + try: + basestring + except NameError: + basestring = str if not text or not isinstance(text, basestring): return #FIXME: only short comments removed @@ -71,18 +75,22 @@ def __encode(self, obj): tp = type(obj) if isinstance(obj, str): s += '"%s"' % obj.replace(r'"', r'\"') - if isinstance(obj, unicode): + if isinstance(obj, str): s += '"%s"' % obj.encode('utf-8').replace(r'"', r'\"') - elif tp in [int, float, long, complex]: + elif tp in [int, float, complex]: s += str(obj) elif tp is bool: s += str(obj).lower() elif obj is None: s += 'nil' elif tp in [list, tuple, dict]: + try: + basestring + except NameError: + basestring = str self.depth += 1 if len(obj) == 0 or ( tp is not dict and len(filter( - lambda x: type(x) in (int, float, long) \ + lambda x: type(x) in (int, float) \ or (isinstance(x, basestring) and len(x) < 10), obj )) == len(obj) ): newline = tab = '' @@ -148,7 +156,7 @@ def string(self, end=None): if self.ch != end: s += '\\' s += self.ch - print ERRORS['unexp_end_string'] + print(ERRORS['unexp_end_string']) def object(self): o = {} @@ -174,7 +182,7 @@ def object(self): self.next_chr() if k is not None: o[idx] = k - if not numeric_keys and len([ key for key in o if isinstance(key, (str, unicode, float, bool, tuple))]) == 0: + if not numeric_keys and len([ key for key in o if isinstance(key, (str, float, bool, tuple))]) == 0: ar = [] for key in o: ar.insert(key, o[key]) @@ -200,7 +208,7 @@ def object(self): o[idx] = k idx += 1 k = None - print ERRORS['unexp_end_table'] #Bad exit here + print(ERRORS['unexp_end_table']) #Bad exit here words = {'true': True, 'false': False, 'nil': None} def word(self): From 85ef3ed9253a2bdf1b1a066ef7d4fffeb5e62b5f Mon Sep 17 00:00:00 2001 From: Posimagi Date: Sun, 18 Dec 2022 17:11:28 -0800 Subject: [PATCH 0898/1002] [craft] Move multi-recipes (those that use Bundling Twine, Spindle, etc.) to higher recipe numbers than the standard recipe that makes the basic quantity. Fix issues with several recipes that erroneously show multiple copies of the bundling guild item. --- addons/craft/recipes.lua | 82 +++++++++++++--------------------------- 1 file changed, 26 insertions(+), 56 deletions(-) diff --git a/addons/craft/recipes.lua b/addons/craft/recipes.lua index 04b3f19dd9..9499442071 100644 --- a/addons/craft/recipes.lua +++ b/addons/craft/recipes.lua @@ -1219,15 +1219,15 @@ return { ["crystal"] = "Wind Crystal", ["ingredients"] = { "Petrified Log", - "Petrified Log", - "Petrified Log", - "Bundling Twine", }, }, ["Ancient Lumber 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { "Petrified Log", + "Petrified Log", + "Petrified Log", + "Bundling Twine", }, }, ["Anelace"] = { @@ -3330,15 +3330,15 @@ return { ["crystal"] = "Wind Crystal", ["ingredients"] = { "Beech Log", - "Beech Log", - "Beech Log", - "Bundling Twine", }, }, ["Beech Lumber 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { "Beech Log", + "Beech Log", + "Beech Log", + "Bundling Twine", }, }, ["Beef Paella"] = { @@ -7527,11 +7527,6 @@ return { ["Chapuli Fltchg. 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", "Zephyr Thread", "Chapuli Wing", "Chapuli Wing", @@ -8436,11 +8431,6 @@ return { ["Colibri Fletchings 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", "Zephyr Thread", "Colibri Feather", "Colibri Feather", @@ -11134,15 +11124,15 @@ return { ["crystal"] = "Wind Crystal", ["ingredients"] = { "Divine Log", - "Divine Log", - "Divine Log", - "Bundling Twine", }, }, ["Divine Lumber 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { "Divine Log", + "Divine Log", + "Divine Log", + "Bundling Twine", }, }, ["Divine Sap"] = { @@ -14317,11 +14307,6 @@ return { "G. Bird Plume", "G. Bird Plume", "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", }, }, ["Gilded Chest"] = { @@ -15135,11 +15120,6 @@ return { ["ingredients"] = { "Moko Grass", "Moko Grass", - "Moko Grass", - "Moko Grass", - "Moko Grass", - "Moko Grass", - "Spindle", }, }, ["Grass Thread 2"] = { @@ -15147,6 +15127,11 @@ return { ["ingredients"] = { "Moko Grass", "Moko Grass", + "Moko Grass", + "Moko Grass", + "Moko Grass", + "Moko Grass", + "Spindle", }, }, ["Grasshopper Broth"] = { @@ -19268,15 +19253,15 @@ return { ["crystal"] = "Wind Crystal", ["ingredients"] = { "Lacquer Tree Log", - "Lacquer Tree Log", - "Lacquer Tree Log", - "Bundling Twine", }, }, ["Lacquer Tree Lumber 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { "Lacquer Tree Log", + "Lacquer Tree Log", + "Lacquer Tree Log", + "Bundling Twine", }, }, ["Lacquer Tree Sap"] = { @@ -19382,15 +19367,15 @@ return { ["crystal"] = "Wind Crystal", ["ingredients"] = { "Lancewood Log", - "Lancewood Log", - "Lancewood Log", - "Bundling Twine", }, }, ["Lancewood Lumber 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { "Lancewood Log", + "Lancewood Log", + "Lancewood Log", + "Bundling Twine", }, }, ["Lanner Bow"] = { @@ -24442,11 +24427,6 @@ return { ["Peapuk Fletchings 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", "Zephyr Thread", "Peapuk Wing", "Peapuk Wing", @@ -25853,11 +25833,6 @@ return { ["Puk Fletchings 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", "Zephyr Thread", "Puk Wing", "Puk Wing", @@ -32704,15 +32679,15 @@ return { ["Teak Lumber"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Bundling Twine", - "Teak Log", - "Teak Log", "Teak Log", }, }, ["Teak Lumber 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { + "Bundling Twine", + "Teak Log", + "Teak Log", "Teak Log", }, }, @@ -33734,11 +33709,6 @@ return { ["Tulfaire Fletchings 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", "Zephyr Thread", "Tulfaire Feather", "Tulfaire Feather", @@ -34186,15 +34156,15 @@ return { ["Urunday Lumber"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Bundling Twine", - "Urunday Log", - "Urunday Log", "Urunday Log", }, }, ["Urunday Lumber 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { + "Bundling Twine", + "Urunday Log", + "Urunday Log", "Urunday Log", }, }, From ff9f951509914a1075fa732e1c7449cbc76896df Mon Sep 17 00:00:00 2001 From: Posimagi Date: Wed, 18 Jan 2023 23:46:14 -0800 Subject: [PATCH 0899/1002] [craft] generate new recipes.lua --- addons/craft/recipes.lua | 357 +++++++++++++++++++++++++++++++-------- 1 file changed, 288 insertions(+), 69 deletions(-) diff --git a/addons/craft/recipes.lua b/addons/craft/recipes.lua index 9499442071..10ee9fb487 100644 --- a/addons/craft/recipes.lua +++ b/addons/craft/recipes.lua @@ -674,7 +674,6 @@ return { ["crystal"] = "Earth Crystal", ["ingredients"] = { "Platinum Ingot", - "Wool Thread", "Gold Thread", "Gold Thread", "Silk Cloth", @@ -1818,7 +1817,6 @@ return { "Silver Chain", "Velvet Cloth", "Velvet Cloth", - "Velvet Cloth", "Sheep Leather", "Sheep Leather", "Eltoro Leather", @@ -4740,7 +4738,7 @@ return { "Hallowed Water", }, }, - ["Blessed Briault"] = { + ["Blessed Bliaut"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { "Silver Thread", @@ -4953,6 +4951,7 @@ return { "Gold Thread", "Gold Thread", "Silk Cloth", + "Rainbow Cloth", "Saruta Cotton", "Saruta Cotton", "Dragon Blood", @@ -5674,6 +5673,14 @@ return { "Teak Lumber", }, }, + ["Bongo Drum"] = { + ["crystal"] = "Earth Crystal", + ["ingredients"] = { + "Bamboo Stick", + "Dhalmel Hide", + "Buffalo Leather", + }, + }, ["Book Holder"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -6671,6 +6678,7 @@ return { ["Bug Broth"] = { ["crystal"] = "Water Crystal", ["ingredients"] = { + "Lugworm", "Lugworm", "Shell Bug", "Shell Bug", @@ -7129,6 +7137,7 @@ return { ["ingredients"] = { "Gelatin", "Hare Meat", + "Hare Meat", "Rotten Meat", }, }, @@ -7723,6 +7732,14 @@ return { "Rosewood Lbr.", }, }, + ["Chikuwa"] = { + ["crystal"] = "Earth Crystal", + ["ingredients"] = { + "Rock Salt", + "Bastore Bream", + "Tiger Cod", + }, + }, ["Chimera Blood"] = { ["crystal"] = "Lightng. Crystal", ["ingredients"] = { @@ -7889,6 +7906,9 @@ return { ["ingredients"] = { "Maple Sugar", "Kukuru Bean", + "Kukuru Bean", + "Kukuru Bean", + "Kukuru Bean", "Honey", "Selbina Milk", "Distilled Water", @@ -8473,18 +8493,6 @@ return { "Gigant Axe", }, }, - ["Comaa Belt"] = { - ["crystal"] = "Earth Crystal", - ["ingredients"] = { - "Thought Crystal", - "Hope Crystal", - "Fulfillment Crystal", - "Khoma Thread", - "Khoma Thread", - "Khoma Thread", - "Khoma Thread", - }, - }, ["Combat Caster's Axe +1"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -8640,7 +8648,7 @@ return { ["Compression Sphere 5"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Dark Card", + "Dark Crest Card", }, }, ["Console"] = { @@ -9989,13 +9997,13 @@ return { "Dk. Ixion Ferrule", }, }, - ["Dagger"] = { + ["Dagger (Weapon)"] = { ["crystal"] = "Light Crystal", ["ingredients"] = { "Rusty Dagger", }, }, - ["Dagger 2"] = { + ["Dagger (Weapon) 2"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { "Bronze Ingot", @@ -10950,7 +10958,7 @@ return { ["Detonation Sphere 5"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Wind Card", + "Wind Crest Card", }, }, ["Devotee's Mitts"] = { @@ -12096,6 +12104,15 @@ return { "Yilanbaligi", }, }, + ["Egg Sandwich"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "Selbina Butter", + "White Bread", + "Hard-boiled Egg", + "Graubg. Lettuce", + }, + }, ["Egg Soup"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -12397,6 +12414,57 @@ return { "Enhancing Mantle", }, }, + ["Enchanted Ink"] = { + ["crystal"] = "Dark Crystal", + ["ingredients"] = { + "Black Ink", + "Magicked Blood", + }, + }, + ["Enfeeblement Kit of Blindness"] = { + ["crystal"] = "Earth Crystal", + ["ingredients"] = { + "Fine Parchment", + "Fine Parchment", + "Enchanted Ink", + "Enchanted Ink", + "Padded Box", + "Blinding Potion", + }, + }, + ["Enfeeblement Kit of Poison"] = { + ["crystal"] = "Earth Crystal", + ["ingredients"] = { + "Fine Parchment", + "Fine Parchment", + "Enchanted Ink", + "Enchanted Ink", + "Padded Box", + "Poison Potion", + }, + }, + ["Enfeeblement Kit of Silence"] = { + ["crystal"] = "Earth Crystal", + ["ingredients"] = { + "Fine Parchment", + "Fine Parchment", + "Enchanted Ink", + "Enchanted Ink", + "Padded Box", + "Silencing Potion", + }, + }, + ["Enfeeblement Kit of Sleep"] = { + ["crystal"] = "Earth Crystal", + ["ingredients"] = { + "Fine Parchment", + "Fine Parchment", + "Enchanted Ink", + "Enchanted Ink", + "Padded Box", + "Sleeping Potion", + }, + }, ["Engetsuto"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -12814,6 +12882,8 @@ return { "Apple Vinegar", "Beastman Blood", "Hecteyes Eye", + "Hecteyes Eye", + "Hecteyes Eye", "Gelatin", "Frost Turnip", "Distilled Water", @@ -13410,6 +13480,7 @@ return { "Apple Vinegar", "Olive Oil", "Tiger Cod", + "Tiger Cod", "Bird Egg", "Moval. Water", }, @@ -14998,7 +15069,7 @@ return { ["Goldsmithing Set 90"] = { ["crystal"] = "Geo Crystal", ["ingredients"] = { - "Gold Ingot", + "Gold Sheet", "Emerald", "Ruby", "Diamond", @@ -15402,19 +15473,6 @@ return { "Distilled Water", }, }, - ["Griffon Leather 3"] = { - ["crystal"] = "Dark Crystal", - ["ingredients"] = { - "Win. Tea Leaves", - "Win. Tea Leaves", - "Win. Tea Leaves", - "Griffon Hide", - "Griffon Hide", - "Griffon Hide", - "Tanning Vat", - "Distilled Water", - }, - }, ["Grilled Hare"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -15500,6 +15558,19 @@ return { "Gysahl Greens", }, }, + ["Gyudon"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "Ginger", + "Tarutaru Rice", + "Soy Stock", + "Wild Onion", + "Buffalo Meat", + "Cotton Tofu", + "Shungiku", + "Shirataki", + }, + }, ["Hachimaki"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { @@ -15746,13 +15817,13 @@ return { ["Hard Leather Ring"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Tiger Leather", + "Leath. Kit 60", }, }, ["Hard Leather Ring 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Leath. Kit 60", + "Tiger Leather", }, }, ["Hard-boiled Egg"] = { @@ -16185,6 +16256,7 @@ return { ["Herb Paste"] = { ["crystal"] = "Water Crystal", ["ingredients"] = { + "Toko. Wildgrass", "Toko. Wildgrass", "La Theine Millet", "Lizard Egg", @@ -17544,7 +17616,7 @@ return { ["Impaction Sphere 5"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Lightning Card", + "Lightning Crest Card", }, }, ["Imperial Cermet"] = { @@ -17650,7 +17722,7 @@ return { ["Induration Sphere 4"] = { ["crystal"] = "Lightng. Crystal", ["ingredients"] = { - "Ice Card", + "Ice Crest Card", }, }, ["Induration Sphere 5"] = { @@ -18344,7 +18416,7 @@ return { }, }, ["Jolt Counter"] = { - ["crystal"] = "Earth Crystal", + ["crystal"] = "Fire Crystal", ["ingredients"] = { "Moonbow Steel", "Moonbow Stone", @@ -18794,6 +18866,18 @@ return { "Khimaira Mane", }, }, + ["Khoma Belt"] = { + ["crystal"] = "Earth Crystal", + ["ingredients"] = { + "Thought Crystal", + "Hope Crystal", + "Fulfillment Crystal", + "Khoma Thread", + "Khoma Thread", + "Khoma Thread", + "Khoma Thread", + }, + }, ["Khoma Cloth"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -19081,6 +19165,14 @@ return { "Bird Egg", }, }, + ["Konjak"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "Seashell", + "Distilled Water", + "Konjak Tuber", + }, + }, ["Konron Hassen"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -19501,7 +19593,7 @@ return { }, }, ["Leather Pot"] = { - ["crystal"] = "Earth Crystal", + ["crystal"] = "Fire Crystal", ["ingredients"] = { "Hickory Lumber", "Karakul Leather", @@ -20013,7 +20105,7 @@ return { ["Liquefaction Sphere 5"] = { ["crystal"] = "Lightng. Crystal", ["ingredients"] = { - "Fire Card", + "Fire Crest Card", }, }, ["Lithic Wyvern Scale"] = { @@ -20287,6 +20379,12 @@ return { "Bkn. Lu Rod", }, }, + ["Lu Shang's Fishing Rod +1"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "B. Lu. Rod +1", + }, + }, ["Lucent Axe"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -20422,6 +20520,15 @@ return { "Lynx Hide", }, }, + ["M. Counteragent"] = { + ["crystal"] = "Water Crystal", + ["ingredients"] = { + "Seashell", + "Salinator", + "Distilled Water", + "Distilled Water", + }, + }, ["Mace"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -21036,14 +21143,6 @@ return { }, }, ["Marbled Drawers"] = { - ["crystal"] = "Earth Crystal", - ["ingredients"] = { - "Bamboo Stick", - "Dhalmel Hide", - "Buffalo Leather", - }, - }, - ["Marbled Drawers 2"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { "Walnut Lumber", @@ -21799,6 +21898,13 @@ return { "Glass Fiber", }, }, + ["Miracle Mulch"] = { + ["crystal"] = "Dark Crystal", + ["ingredients"] = { + "Chocobo Bedding", + "Dung", + }, + }, ["Mirage Stole"] = { ["crystal"] = "Light Crystal", ["ingredients"] = { @@ -22017,6 +22123,14 @@ return { "Raptor Skin", }, }, + ["Mohbwa Cloth"] = { + ["crystal"] = "Earth Crystal", + ["ingredients"] = { + "Mohbwa Thread", + "Mohbwa Thread", + "Mohbwa Thread", + }, + }, ["Mohbwa Sash"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -22232,7 +22346,7 @@ return { "Moonbow Steel", "Moonbow Cloth", "Moonbow Leather", - "Comaa Belt", + "Khoma Belt", }, }, ["Moonbow Whistle"] = { @@ -23523,6 +23637,15 @@ return { "Contortacle", }, }, + ["Oden"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "Fish Stock", + "Konjak", + "Daikon", + "Chikuwa", + }, + }, ["Odorous Knife"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -23607,6 +23730,16 @@ return { "Wamoura Silk", }, }, + ["Omelette Sandwich"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "Selbina Butter", + "White Bread", + "Apkallu Egg", + "Puk Egg", + "Graubg. Lettuce", + }, + }, ["Onyx"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { @@ -23756,6 +23889,7 @@ return { "Selbina Butter", "Maple Sugar", "Saruta Orange", + "Saruta Orange", "Bird Egg", }, }, @@ -24389,6 +24523,8 @@ return { ["Pea Soup"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { + "Blue Peas", + "Blue Peas", "Blue Peas", "Dried Marjoram", "Wild Onion", @@ -24462,6 +24598,7 @@ return { ["Pear au Lait"] = { ["crystal"] = "Water Crystal", ["ingredients"] = { + "Derfland Pear", "Derfland Pear", "Honey", "Selbina Milk", @@ -24991,6 +25128,7 @@ return { "Rock Salt", "Sea Foliage", "Kitron", + "Rarab Tail", }, }, ["Pie Dough"] = { @@ -25585,6 +25723,19 @@ return { "Orichalcum Lance", }, }, + ["Popo. con Queso"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "San d'Or. Flour", + "Selbina Butter", + "Popoto", + "Rock Salt", + "Danceshroom", + "Selbina Milk", + "Wild Onion", + "Chalaimbille", + }, + }, ["Popstar"] = { ["crystal"] = "Light Crystal", ["ingredients"] = { @@ -25896,6 +26047,44 @@ return { "Distilled Water", }, }, + ["Pungent Powder"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Ahriman Lens", + "Silk Cloth", + "Saruta Cotton", + "Glass Fiber", + "Glass Fiber", + "Gelatin", + "Cornstarch", + "Pagodite", + }, + }, + ["Pungent Powder II"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Ahriman Lens", + "Silk Cloth", + "Saruta Cotton", + "Glass Fiber", + "Glass Fiber", + "Revival Root", + "Cornstarch", + "Pagodite", + }, + }, + ["Pungent Powder III"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Ahriman Lens", + "Silk Cloth", + "Saruta Cotton", + "Glass Fiber", + "Glass Fiber", + "Cornstarch", + "Pagodite", + }, + }, ["Pup. Collar"] = { ["crystal"] = "Light Crystal", ["ingredients"] = { @@ -26014,6 +26203,19 @@ return { "Walnut Lumber", }, }, + ["R. Pickled R. Tail"] = { + ["crystal"] = "Dark Crystal", + ["ingredients"] = { + "Apple Vinegar", + "Black Pepper", + "Maple Sugar", + "Rock Salt", + "Ro'Maeve Water", + "Rolanberry", + "Rarab Tail", + "Rarab Tail", + }, + }, ["Ra'Kaznar Arrowheads"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { @@ -27102,7 +27304,7 @@ return { ["Reverberation Sphere 4"] = { ["crystal"] = "Lightng. Crystal", ["ingredients"] = { - "Water Card", + "Water Crest Card", }, }, ["Reverberation Sphere 5"] = { @@ -27300,6 +27502,7 @@ return { ["ingredients"] = { "Rock Salt", "Danceshroom", + "Danceshroom", }, }, ["Roast Mushroom 2"] = { @@ -27307,6 +27510,7 @@ return { ["ingredients"] = { "Rock Salt", "Woozyshroom", + "Woozyshroom", }, }, ["Roast Mushroom 3"] = { @@ -27314,6 +27518,7 @@ return { ["ingredients"] = { "Rock Salt", "Sleepshroom", + "Sleepshroom", }, }, ["Roast Mutton"] = { @@ -28682,7 +28887,7 @@ return { ["Scission Sphere 5"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Earth Card", + "Earth Crest Card", }, }, ["Scope"] = { @@ -28920,6 +29125,19 @@ return { "Coral Fragment", }, }, + ["Seafood Gratin"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "San d'Or. Flour", + "Selbina Butter", + "Rock Salt", + "Danceshroom", + "Selbina Milk", + "Gigant Squid", + "Bastore Sweeper", + "Chalaimbille", + }, + }, ["Seafood Paella"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -29396,6 +29614,7 @@ return { "Rock Salt", "Kazham Pineapl.", "Shall Shell", + "Shall Shell", "Distilled Water", }, }, @@ -30722,7 +30941,7 @@ return { "Cockatrice Skin", }, }, - ["Smithing Set 71"] = { + ["Smithing Set 70"] = { ["crystal"] = "Pyre Crystal", ["ingredients"] = { "Darksteel Ingot", @@ -33536,7 +33755,7 @@ return { ["Transfixion Sphere 5"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Light Card", + "Light Crest Card", }, }, ["Translucent Rock"] = { @@ -34911,22 +35130,6 @@ return { "Hexed Kecks", }, }, - ["Vexed Kote"] = { - ["crystal"] = "Fire Crystal", - ["ingredients"] = { - "Eschite Ore", - "Hexed Tekko -1", - }, - }, - ["Vexed Kote 2"] = { - ["crystal"] = "Fire Crystal", - ["ingredients"] = { - "Cehuetzi Pelt", - "Muut's Vestment", - "Eschite Ore", - "Hexed Tekko", - }, - }, ["Vexed Mitra"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -35007,6 +35210,22 @@ return { "Hexed Sune-Ate", }, }, + ["Vexed Tekko"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "Eschite Ore", + "Hexed Tekko -1", + }, + }, + ["Vexed Tekko 2"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "Cehuetzi Pelt", + "Muut's Vestment", + "Eschite Ore", + "Hexed Tekko", + }, + }, ["Vexed Tights"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { From d7256a96e3ffdbf145f8c06c9cc82af293307cc3 Mon Sep 17 00:00:00 2001 From: Posimagi Date: Sun, 18 Dec 2022 17:02:35 -0800 Subject: [PATCH 0900/1002] [craft] report quantity of items crafted --- addons/craft/craft.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/addons/craft/craft.lua b/addons/craft/craft.lua index f8b89b74d5..020893d35e 100644 --- a/addons/craft/craft.lua +++ b/addons/craft/craft.lua @@ -792,7 +792,12 @@ windower.register_event('incoming chunk', function(id, original, modified, injec local p = packets.parse('incoming',original) if p['Result'] == 0 or p['Result'] == 2 then local item = res.items[p['Item']].english - windower.add_to_chat(121, 'You synthesized: \30\02%s\30\01.':format(item)) + local count = p['Count'] + if count > 1 then + windower.add_to_chat(121, 'You synthesized: \30\02%s\30\01 x%d.':format(item, count)) + else + windower.add_to_chat(121, 'You synthesized: \30\02%s\30\01.':format(item)) + end injected_synth = false end if p['Result'] == 1 or p['Result'] == 5 then From cf92362988b4dd9d2d5adbdc4c94eda349ccdbc5 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Tue, 24 Jan 2023 15:40:32 +0100 Subject: [PATCH 0901/1002] [Slips lib] Update for new items Adding the new items Cornelia's belt, Kni cap and Knit cap +1 --- addons/libs/slips.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 55ee0f3578..7aacfc96bc 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -15,7 +15,7 @@ slips.storages = L{29312, 29313, 29314, 29315, 29316, 29317, 29318, 2931 slips.items = { [slips.storages[1]] = L{16084, 14546, 14961, 15625, 15711, 16085, 14547, 14962, 15626, 15712, 16086, 14548, 14963, 15627, 15713, 16087, 14549, 14964, 15628, 15714, 16088, 14550, 14965, 15629, 15715, 16089, 14551, 14966, 15630, 15716, 16090, 14552, 14967, 15631, 15717, 16091, 14553, 14968, 15632, 15718, 16092, 14554, 14969, 15633, 15719, 16093, 14555, 14970, 15634, 15720, 16094, 14556, 14971, 15635, 15721, 16095, 14557, 14972, 15636, 15722, 16096, 14558, 14973, 15637, 15723, 16097, 14559, 14974, 15638, 15724, 16098, 14560, 14975, 15639, 15725, 16099, 14561, 14976, 15640, 15726, 16100, 14562, 14977, 15641, 15727, 16101, 14563, 14978, 15642, 15728, 16102, 14564, 14979, 15643, 15729, 16103, 14565, 14980, 15644, 15730, 16106, 14568, 14983, 15647, 15733, 16107, 14569, 14984, 15648, 15734, 16108, 14570, 14985, 15649, 15735, 16602, 17741, 18425, 18491, 18588, 18717, 18718, 18850, 18943, 16069, 14530, 14940, 15609, 15695, 16062, 14525, 14933, 15604, 15688, 16064, 14527, 14935, 15606, 15690, 18685, 18065, 17851, 18686, 18025, 18435, 18113, 17951, 17715, 18485, 18408, 18365, 18583, 18417, 18388, 16267, 16268, 16269, 16228, 16229, 15911, 15799, 15800, 15990, 17745, 18121, 16117, 14577, 17857}, -- 168 [slips.storages[2]] = L{12421, 12549, 12677, 12805, 12933, 13911, 14370, 14061, 14283, 14163, 12429, 12557, 12685, 12813, 12941, 13924, 14371, 14816, 14296, 14175, 13934, 14387, 14821, 14303, 14184, 13935, 14388, 14822, 14304, 14185, 13876, 13787, 14006, 14247, 14123, 13877, 13788, 14007, 14248, 14124, 13908, 14367, 14058, 14280, 14160, 13909, 14368, 14059, 14281, 14161, 16113, 14573, 14995, 15655, 15740, 16115, 14575, 14997, 15657, 15742, 16114, 14574, 14996, 15656, 15741, 16116, 14576, 14998, 15658, 15743, 12818, 18198, 12946, 18043, 12690, 17659, 12296, 12434, 15471, 15472, 15473, 15508, 15509, 15510, 15511, 15512, 15513, 15514, 17710, 17595, 18397, 18360, 18222, 17948, 18100, 15475, 15476, 15477, 15488, 15961, 14815, 14812, 14813, 15244, 15240, 14488, 14905, 15576, 15661, 15241, 14489, 14906, 15577, 15662, 13927, 14378, 14076, 14308, 14180, 13928, 14379, 14077, 14309, 14181, 10438, 10276, 10320, 10326, 10367, 10439, 10277, 10321, 10327, 10368, 10440, 10278, 10322, 10328, 10369, 10441, 10279, 10323, 10329, 10370, 25734, 25735, 25736, 25737, 25738, 25739, 25740, 25741, 25742, 25743, 25744}, -- 155 - [slips.storages[3]] = L{16155, 11282, 15021, 16341, 11376, 16156, 11283, 15022, 16342, 11377, 16157, 11284, 15023, 16343, 11378, 16148, 14590, 15011, 16317, 15757, 16143, 14591, 15012, 16318, 15758, 16146, 14588, 15009, 16315, 15755, 16147, 14589, 15010, 16316, 15756, 15966, 15967, 19041, 17684, 17685, 11636, 15844, 15934, 16258, 18735, 18734, 16291, 16292, 19042, 15935, 16293, 16294, 15936, 18618, 11588, 11545, 16158, 16159, 16160, 16149, 14583, 15007, 16314, 15751, 16141, 14581, 15005, 16312, 15749, 16142, 14582, 15006, 16313, 15750, 10876, 10450, 10500, 11969, 10600, 10877, 10451, 10501, 11970, 10601, 10878, 10452, 10502, 11971, 10602, 19132, 18551, 11798, 11362, 11363, 11625, 15959, 16259, 22299, 26414, 21623, 26219, 21886, 23792, 23793, 23794, 23795, 23796, 22032, 22043, 21530, 22044, 26273, 25415, 25416, 25414, 22050, 22302}, -- 117 + [slips.storages[3]] = L{16155, 11282, 15021, 16341, 11376, 16156, 11283, 15022, 16342, 11377, 16157, 11284, 15023, 16343, 11378, 16148, 14590, 15011, 16317, 15757, 16143, 14591, 15012, 16318, 15758, 16146, 14588, 15009, 16315, 15755, 16147, 14589, 15010, 16316, 15756, 15966, 15967, 19041, 17684, 17685, 11636, 15844, 15934, 16258, 18735, 18734, 16291, 16292, 19042, 15935, 16293, 16294, 15936, 18618, 11588, 11545, 16158, 16159, 16160, 16149, 14583, 15007, 16314, 15751, 16141, 14581, 15005, 16312, 15749, 16142, 14582, 15006, 16313, 15750, 10876, 10450, 10500, 11969, 10600, 10877, 10451, 10501, 11970, 10601, 10878, 10452, 10502, 11971, 10602, 19132, 18551, 11798, 11362, 11363, 11625, 15959, 16259, 22299, 26414, 21623, 26219, 21886, 23792, 23793, 23794, 23795, 23796, 22032, 22043, 21530, 22044, 26273, 25415, 25416, 25414, 22050, 22302, 26365}, -- 118 [slips.storages[4]] = L{12511, 12638, 13961, 14214, 14089, 12512, 12639, 13962, 14215, 14090, 13855, 12640, 13963, 14216, 14091, 13856, 12641, 13964, 14217, 14092, 12513, 12642, 13965, 14218, 14093, 12514, 12643, 13966, 14219, 14094, 12515, 12644, 13967, 14220, 14095, 12516, 12645, 13968, 14221, 14096, 12517, 12646, 13969, 14222, 14097, 13857, 12647, 13970, 14223, 14098, 12518, 12648, 13971, 14099, 14224, 13868, 13781, 13972, 14225, 14100, 13869, 13782, 13973, 14226, 14101, 12519, 12649, 13974, 14227, 14102, 12520, 12650, 13975, 14228, 14103, 15265, 14521, 14928, 15600, 15684, 15266, 14522, 14929, 15601, 15685, 15267, 14523, 14930, 15602, 15686, 16138, 14578, 15002, 15659, 15746, 16139, 14579, 15003, 15660, 15747, 16140, 14580, 15004, 16311, 15748, 16678, 17478, 17422, 17423, 16829, 16764, 17643, 16798, 16680, 16766, 17188, 17812, 17771, 17772, 16887, 17532, 17717, 18702, 17858, 19203, 21461, 21124, 20776, 27786, 27926, 28066, 28206, 28346, 27787, 27927, 28067, 28207, 28347}, -- 138 [slips.storages[5]] = L{15225, 14473, 14890, 15561, 15352, 15226, 14474, 14891, 15562, 15353, 15227, 14475, 14892, 15563, 15354, 15228, 14476, 14893, 15564, 15355, 15229, 14477, 14894, 15565, 15356, 15230, 14478, 14895, 15566, 15357, 15231, 14479, 14896, 15567, 15358, 15232, 14480, 14897, 15568, 15359, 15233, 14481, 14898, 15569, 15360, 15234, 14482, 14899, 15570, 15361, 15235, 14483, 14900, 15362, 15571, 15236, 14484, 14901, 15572, 15363, 15237, 14485, 14902, 15573, 15364, 15238, 14486, 14903, 15574, 15365, 15239, 14487, 14904, 15575, 15366, 11464, 11291, 15024, 16345, 11381, 11467, 11294, 15027, 16348, 11384, 11470, 11297, 15030, 16351, 11387, 11475, 11302, 15035, 16357, 11393, 11476, 11303, 15036, 16358, 11394, 11477, 11304, 15037, 16359, 11395}, -- 105 [slips.storages[6]] = L{15072, 15087, 15102, 15117, 15132, 15871, 15073, 15088, 15103, 15118, 15133, 15478, 15074, 15089, 15104, 15119, 15134, 15872, 15075, 15090, 15105, 15120, 15135, 15874, 15076, 15091, 15106, 15121, 15136, 15873, 15077, 15092, 15107, 15122, 15137, 15480, 15078, 15093, 15108, 15123, 15138, 15481, 15079, 15094, 15109, 15124, 15139, 15479, 15080, 15095, 15110, 15125, 15140, 15875, 15081, 15096, 15111, 15126, 15141, 15482, 15082, 15097, 15112, 15127, 15142, 15876, 15083, 15098, 15113, 15128, 15143, 15879, 15084, 15099, 15114, 15129, 15144, 15877, 15085, 15100, 15115, 15130, 15145, 15878, 15086, 15101, 15116, 15131, 15146, 15484, 11465, 11292, 15025, 16346, 11382, 16244, 11468, 11295, 15028, 16349, 11385, 15920, 11471, 11298, 15031, 16352, 11388, 16245, 11478, 11305, 15038, 16360, 11396, 16248, 11480, 11307, 15040, 16362, 11398, 15925}, -- 120 @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757, 25909}, -- 192 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912, 3753, 23806, 3754}, -- 162 SE Skipped an index hence the 0 as one of the items + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912, 3753, 23806, 3754, 23810, 23811}, -- 164 SE Skipped an index hence the 0 as one of the items [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067, 21680, 22071}, -- 177 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, -- 115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, -- 115 From 0630cd753e7dcfc9f8bef56b5457ca29ce529faa Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Tue, 31 Jan 2023 16:44:17 +0100 Subject: [PATCH 0902/1002] [Battlemod] Antidedupliction fix Antideduplication fix when buffs with the same name wear off at the same time. Some more minor fixes. --- addons/battlemod/battlemod.lua | 95 +++++++++++++++++++++--- addons/battlemod/generic_helpers.lua | 2 +- addons/battlemod/parse_action_packet.lua | 48 ++++++++---- addons/battlemod/statics.lua | 41 +++++++--- 4 files changed, 146 insertions(+), 40 deletions(-) diff --git a/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index 5ae3426899..9a0b17a7e4 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -7,12 +7,13 @@ res = require 'resources' require 'actions' require 'pack' bit = require 'bit' +packets = require('packets') require 'generic_helpers' require 'parse_action_packet' require 'statics' -_addon.version = '3.31' +_addon.version = '3.32' _addon.name = 'BattleMod' _addon.author = 'Byrth, maintainer: SnickySnacks' _addon.commands = {'bm','battlemod'} @@ -170,6 +171,17 @@ windower.register_event('incoming text',function (original, modified, color, col elseif original:endswith(endline) and string.find(original, item) then --block items action messages return true end + elseif color == 191 then + local endline = string.char(0x7F, 0x31) + if original:endswith(endline) and string.find(original, 'effect wears off.') then --deduplication blocking fix + local status = string.match(original, '\'s (.+) effect wears off') or string.match(original, '\' (.+) effect wears off') + if antideduplication_table[status] and string.find(original, antideduplication_table[status].message) then + packet_inject(antideduplication_table[status].packet_table) + return true + end + elseif string.find(original, 'dummy'..endline) then --block sideeffect of setting the message to 0 in injected 0x029 packet + return true + end end return modified,color @@ -250,12 +262,12 @@ function filterload(job) 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) + --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) + --config.save(filter) windower.add_to_chat(4,'Loaded default Battlemod filters') end current_job = job @@ -305,11 +317,13 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec 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.param_2 = original:unpack('I',0x11) + --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 + am.message_id = original:unpack('H',0x19) + --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) @@ -347,12 +361,29 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec :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 + elseif (am.message_id == 206 or am.message_id == 204) and condensetargets then -- Wears off and is no longer 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) + if not is_injected and am.message_id == 206 then + 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 + + antideduplication(outstr, am) + end + + if enfeebling:contains(am.param_1) and res.buffs[am.param_1] then + if log_form_messages:contains(am.message_id) then + status = color_it(res.buffs[am.param_1].english_log,color_arr.enfeebcol) + else + status = color_it(res.buffs[am.param_1][language],color_arr.enfeebcol) + end elseif color_arr.statuscol == rcol then status = color_it(res.buffs[am.param_1][language],string.char(0x1F,191)) else @@ -375,10 +406,17 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec multi_targs[status][1] = target multi_packet(status) end + if is_injected then + local parsed = packets.parse('incoming', original) + parsed['Message'] = 0 + local rebuilt = packets.build(parsed) + return rebuilt + 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] + local color = color_filt(res.action_messages[am.message_id].color, am.actor_id==Self.id) if plural_entities:contains(am.actor_id) then outstr = plural_actor(outstr, am.message_id) end @@ -386,6 +424,8 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec outstr = plural_target(outstr, am.message_id) end + if am.message_id == 206 and not is_injected then antideduplication(outstr, am) end + local fields = fieldsearch(outstr) if fields.status then @@ -447,14 +487,20 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec :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) + windower.add_to_chat(color,outstr) + if am.message_id == 206 and is_injected then + local parsed = packets.parse('incoming', original) + parsed['Message'] = 0 + local rebuilt = packets.build(parsed) + return rebuilt + end 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) + print('debug_EAM#'..am.message_id..': '..res.action_messages[am.message_id][language]..' '..am.param_1..' '..am.param_2) elseif debugging then - print('debug_EAM#'..am.message_id..': '..'Unknown'..' '..am.param_1..' '..am.param_2..' '..am.param_3) + print('debug_EAM#'..am.message_id..': '..'Unknown'..' '..am.param_1..' '..am.param_2) end if not am.message_id then return true @@ -506,3 +552,28 @@ function multi_packet(...) multi_msg[ind] = nil multi_actor[ind] = nil end + +function antideduplication(msg, data) + local status = res.buffs[data.param_1].en + local actor = player_info(data.actor_id) + local target = player_info(data.target_id) + local target_article = common_nouns:contains(data.target_id) and 'The ' or '' + msg = (clean_msg(msg + :gsub('${status}',status) + :gsub('${target}\'s',target_article..target.name ..'\'s') + :gsub('${target}',target_article..target.name))) + antideduplication_table[status] = {message = msg, packet_table = data} +end + +function packet_inject(data) + packets.inject(packets.new('incoming', 0x029, { + ['Actor'] = data.actor_id, + ['Target'] = data.target_id, + ['Param 1'] = data.param_1, + ['Param 2'] = data.param_2, + ['Actor Index'] = data.actor_index, + ['Target Index'] = data.target_index, + ['Message'] = 206, + ['_unknown1'] = 0 + })) +end diff --git a/addons/battlemod/generic_helpers.lua b/addons/battlemod/generic_helpers.lua index 1f015ae554..108ed1dc5f 100644 --- a/addons/battlemod/generic_helpers.lua +++ b/addons/battlemod/generic_helpers.lua @@ -1,4 +1,4 @@ ---Copyright © 2013, Byrthnoth +--Copyright © 2023, Byrthnoth --All rights reserved. --Redistribution and use in source and binary forms, with or without diff --git a/addons/battlemod/parse_action_packet.lua b/addons/battlemod/parse_action_packet.lua index f7736d703d..868d77d53a 100644 --- a/addons/battlemod/parse_action_packet.lua +++ b/addons/battlemod/parse_action_packet.lua @@ -266,7 +266,7 @@ function parse_action_packet(act) elseif T{78,198,328}:contains(m.message) then m.simp_name = '(Too Far)' end - local msg,numb = simplify_message(m.message) + 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 @@ -562,24 +562,35 @@ end function assemble_targets(actor,targs,category,msg,add_effect) local targets = {} local samename = {} - local total = 0 + local targets_list = T{} 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 + if (samename[v.name] or samename[v.index]) and condensetargetname then + if v.index < 1024 then + samename[v.name] = samename[v.name] + 1 + else + samename[v.index] = samename[v.index] + 1 + end + else targets[#targets+1] = v - samename[v.name] = 1 + if v.index < 1024 then + samename[v.name] = 1 + else + samename[v.index] = 1 + end + end + if not targets_list:contains(v.index) then + table.insert(targets_list, v.index) end - total = total + 1 end if add_effect then break end end local out_str - if targetnumber and total > 1 then - out_str = '{'..total..'}: ' + + if targetnumber and #targets_list > 1 then + out_str = '{'..#targets_list..'}: ' else out_str = '' end @@ -587,17 +598,18 @@ function assemble_targets(actor,targs,category,msg,add_effect) 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 '' + local numb = condensetargetname and samename[v.name] and samename[v.name] > 1 and ' {'..samename[v.name]..'}' or (condensetargetname or msg == 206 or msg == 204) and samename[v.index] and samename[v.index] > 1 and ' {'..samename[v.index]..'}' 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 + name = color_it(name,color_arr[v.owner or v.type]) + if (samename[v.name] and samename[v.name] > 1) or (samename[v.index] and samename[v.index] > 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 + name = name..(plural_entities:contains(v.id) and '\'' or '\'s') end targets_condensed = false end + name = name..v.owner_name out_str = out_str..article..name..numb else targets_condensed = true @@ -622,7 +634,7 @@ function player_info(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} + return {name=nil,id=nil,index=nil,is_npc=nil,type='debug',damage=nil,owner=nil, owner_name=nil,race=nil} end for i,v in pairs(windower.ffxi.get_party()) do @@ -701,7 +713,7 @@ function player_info(id) 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} + return {name=player_table.monstrosity_name or player_table.name,id=player_table.id,index=player_table.index,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) @@ -902,6 +914,12 @@ function color_filt(col,is_me) else return 63 end + elseif col == 36 then -- Defeats + if is_me then + return 36 + else + return 37 + end else return col end diff --git a/addons/battlemod/statics.lua b/addons/battlemod/statics.lua index 8abe43eb63..03262651df 100644 --- a/addons/battlemod/statics.lua +++ b/addons/battlemod/statics.lua @@ -1,4 +1,4 @@ - --Copyright © 2013, Byrthnoth + --Copyright © 2023, Byrthnoth --All rights reserved. --Redistribution and use in source and binary forms, with or without @@ -33,9 +33,10 @@ targets_condensed = false common_nouns = T{} plural_entities = T{} item_quantity = {id = 0, count = ''} +antideduplication_table = {} 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} +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,241,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} @@ -223,7 +224,7 @@ message_map[75] = T{283} -- No Effect: Spell, Target 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[82] = T{230,236,237,267,268,270,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 @@ -298,7 +299,6 @@ default_filters = [[ false false false - true @@ -312,6 +312,7 @@ default_filters = [[ false false false + false false @@ -324,6 +325,7 @@ default_filters = [[ false false false + false false @@ -336,6 +338,7 @@ default_filters = [[ false false false + false false @@ -346,6 +349,7 @@ default_filters = [[ false false false + false false @@ -356,6 +360,7 @@ default_filters = [[ false false false + false false @@ -366,6 +371,7 @@ default_filters = [[ false false false + false @@ -601,14 +607,25 @@ my_pet={melee=false,ranged=false,damage=false,healing=false,misses=false,readies 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}} } +me={melee=false,ranged=false,damage=false,healing=false,misses=false,items=false,uses=false,readies=false,casting=false,all=false}, +party={melee=false,ranged=false,damage=false,healing=false,misses=false,items=false,uses=false,readies=false,casting=false,all=false}, +alliance={melee=false,ranged=false,damage=false,healing=false,misses=false,items=false,uses=false,readies=false,casting=false,all=false}, +others={melee=false,ranged=false,damage=false,healing=false,misses=false,items=false,uses=false,readies=false,casting=false,all=false}, +my_pet={melee=false,ranged=false,damage=false,healing=false,misses=false,items=false,uses=false,readies=false,casting=false,all=false}, +my_fellow={melee=false,ranged=false,damage=false,healing=false,misses=false,items=false,uses=false,readies=false,casting=false,all=false}, +other_pets={melee=false,ranged=false,damage=false,healing=false,misses=false,items=false,uses=false,readies=false,casting=false,all=false}, +enemies={melee=false,ranged=false,damage=false,healing=false,misses=false,items=false,uses=false,readies=false,casting=false,all=false}, +monsters={melee=false,ranged=false,damage=false,healing=false,misses=false,items=false,uses=false,readies=false,casting=false,all=false}}, +enemies = { +me={melee=false,ranged=false,damage=false,healing=false,misses=false,items=false,uses=false,readies=false,casting=false,all=false}, +party={melee=false,ranged=false,damage=false,healing=false,misses=false,items=false,uses=false,readies=false,casting=false,all=false}, +alliance={melee=false,ranged=false,damage=false,healing=false,misses=false,items=false,uses=false,readies=false,casting=false,all=false}, +others={melee=false,ranged=false,damage=false,healing=false,misses=false,items=false,uses=false,readies=false,casting=false,all=false}, +my_pet={melee=false,ranged=false,damage=false,healing=false,misses=false,items=false,uses=false,readies=false,casting=false,all=false}, +my_fellow={melee=false,ranged=false,damage=false,healing=false,misses=false,items=false,uses=false,readies=false,casting=false,all=false}, +other_pets={melee=false,ranged=false,damage=false,healing=false,misses=false,items=false,uses=false,readies=false,casting=false,all=false}, +enemies={melee=false,ranged=false,damage=false,healing=false,misses=false,items=false,uses=false,readies=false,casting=false,all=false}, +monsters={melee=false,ranged=false,damage=false,healing=false,misses=false,items=false,uses=false,readies=false,casting=false,all=false}} } default_settings = [[ From 4714e5658885002829989884c9156538aa4c1194 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Wed, 1 Feb 2023 17:18:42 +0100 Subject: [PATCH 0903/1002] Fix for unsimplified Resist! messages Fix for unsimplified Resist! messages --- addons/battlemod/parse_action_packet.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/battlemod/parse_action_packet.lua b/addons/battlemod/parse_action_packet.lua index 868d77d53a..c65ad0200a 100644 --- a/addons/battlemod/parse_action_packet.lua +++ b/addons/battlemod/parse_action_packet.lua @@ -927,6 +927,7 @@ 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,2)==2 and (message==85 or message==284) and not simplify and 'Resist! ' 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 From 7a31275a79a9a0c7fd4a354771e107e7b47b97fa Mon Sep 17 00:00:00 2001 From: Imisnew Date: Sat, 4 Feb 2023 20:42:17 +0900 Subject: [PATCH 0904/1002] Update 0x03C to have starting index field. --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index ac65ce1666..4813bed35b 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2243,7 +2243,7 @@ types.shop_item = L{ -- Shop fields.incoming[0x03C] = L{ - {ctype='unsigned short', label='_zero1', const=0x0000}, -- 04 + {ctype='unsigned short', label='Starting Index'}, -- 04 {ctype='unsigned short', label='_padding1'}, -- 06 {ref=types.shop_item, label='Item', count='*'}, -- 08 - * } From 467957a09ea271c5b1d25c318950c0358cbdeed1 Mon Sep 17 00:00:00 2001 From: Byrth Date: Fri, 10 Feb 2023 04:58:37 -0500 Subject: [PATCH 0905/1002] Update slips for the 2023-02 update --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 7aacfc96bc..81963981ae 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757, 25909}, -- 192 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912, 3753, 23806, 3754, 23810, 23811}, -- 164 SE Skipped an index hence the 0 as one of the items + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912, 3753, 23806, 3754, 23810, 23811, 3755}, -- 164 SE Skipped an index hence the 0 as one of the items [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067, 21680, 22071}, -- 177 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, -- 115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, -- 115 From 96c78a526abe9790307f106561f99e7f18370c2a Mon Sep 17 00:00:00 2001 From: Byrth Date: Sat, 7 Jan 2023 13:26:54 -0500 Subject: [PATCH 0906/1002] Add queue library --- addons/GearSwap/gearswap.lua | 15 +++-- addons/GearSwap/refresh.lua | 120 +++++++++++++++++------------------ 2 files changed, 68 insertions(+), 67 deletions(-) diff --git a/addons/GearSwap/gearswap.lua b/addons/GearSwap/gearswap.lua index 2d5d37129a..4d23192210 100644 --- a/addons/GearSwap/gearswap.lua +++ b/addons/GearSwap/gearswap.lua @@ -48,6 +48,7 @@ require 'logger' error = _raw.error require 'lists' +require 'queues' require 'sets' @@ -134,7 +135,7 @@ initialize_packet_parsing() windower.register_event('load',function() windower.debug('load') refresh_globals() - + if world.logged_in then refresh_user_env() if debugging.general then windower.send_command('@unload spellcast;') end @@ -152,11 +153,11 @@ windower.register_event('addon command',function (...) logit('\n\n'..tostring(os.clock)..table.concat({...},' ')) local splitup = {...} if not splitup[1] then return end -- handles //gs - + for i,v in pairs(splitup) do splitup[i] = windower.from_shift_jis(windower.convert_auto_trans(v)) end local cmd = table.remove(splitup,1):lower() - + if cmd == 'c' then if gearswap_disabled then return end if splitup[1] then @@ -278,7 +279,7 @@ end function incoming_chunk(id,data,modified,injected,blocked) windower.debug('incoming chunk '..id) - + if next_packet_events and next_packet_events.sequence_id ~= data:unpack('H',3) then if not next_packet_events.globals_update or next_packet_events.globals_update ~= data:unpack('H',3) then refresh_globals() @@ -301,7 +302,7 @@ function incoming_chunk(id,data,modified,injected,blocked) next_packet_events = nil end end - + if not injected and parse.i[id] then parse.i[id](data,blocked) end @@ -309,7 +310,7 @@ end function outgoing_chunk(id,original,data,injected,blocked) windower.debug('outgoing chunk '..id) - + if not blocked and parse.o[id] then parse.o[id](data,injected) end @@ -321,7 +322,7 @@ windower.register_event('outgoing chunk',outgoing_chunk) windower.register_event('status change',function(new,old) windower.debug('status change '..new) if gearswap_disabled or T{2,3,4}:contains(old) or T{2,3,4}:contains(new) then return end - + refresh_globals() equip_sets('status_change',nil,res.statuses[new].english,res.statuses[old].english) end) diff --git a/addons/GearSwap/refresh.lua b/addons/GearSwap/refresh.lua index 9fb5e95607..fd5798786d 100644 --- a/addons/GearSwap/refresh.lua +++ b/addons/GearSwap/refresh.lua @@ -61,38 +61,38 @@ end ----------------------------------------------------------------------------------- function load_user_files(job_id,user_file) job_id = tonumber(job_id) - + if current_file then user_pcall('file_unload',current_file) end - + for i in pairs(registered_user_events) do unregister_event_user(i) end - + for i in pairs(__raw.text.registry) do windower.text.delete(i) end - + for i in pairs(__raw.prim.registry) do windower.prim.delete(i) end - + current_file = nil sets = nil user_env = nil unhandled_command_events = {} --registered_user_events = {} include_user_path = nil - + language = 'english' -- Reset language to english when changing job files. refresh_globals() - + if job_id and res.jobs[job_id] then player.main_job_id = job_id update_job_names() end - + local path,base_dir,filename path,base_dir,filename = pathsearch({user_file}) @@ -104,7 +104,7 @@ function load_user_files(job_id,user_file) player.name..'.lua',short_job..'.lua',long_job..'.lua','default.lua'} path,base_dir,filename = pathsearch(tab) end - + if not path then current_file = nil sets = nil @@ -120,18 +120,18 @@ function load_user_files(job_id,user_file) show_swaps = show_swaps,debug_mode=debug_mode,include_path=user_include_path, register_unhandled_command=user_unhandled_command,move_spell_target=move_spell_target, language=language, - + -- Library functions - string=string,math=math,table=table,set=set,list=list,T=T,S=S,L=L,pack=pack,functions=functions, + string=string,math=math,table=table,set=set,list=list,queue=queue,T=T,S=S,L=L,Q=Q,pack=pack,functions=functions, os=os,texts=texts,bit=bit,type=type,tostring=tostring,tonumber=tonumber,pairs=pairs, ipairs=ipairs, print=print, add_to_chat=add_to_chat_user,unpack=unpack,next=next, select=select,lua_base_path=windower.addon_path,empty=empty,file=file, loadstring=loadstring,assert=assert,error=error,pcall=pcall,io=io,dofile=dofile, - + debug=debug,coroutine=coroutine,setmetatable=setmetatable,getmetatable=getmetatable, rawset=rawset,rawget=rawget,require=include_user, _libs=_libs, - + -- Player environment things buffactive=buffactive, player=player, @@ -145,12 +145,12 @@ function load_user_files(job_id,user_file) body=empty,hands=empty,ring1=empty,ring2=empty, back=empty,waist=empty,legs=empty,feet=empty}} } - + user_env['_G'] = user_env - + -- Try to load data/_
    .lua local funct, err = loadfile(path) - + -- If the file cannot be loaded, print the error and load the default. if funct == nil then print('User file problem: '..err) @@ -161,24 +161,24 @@ function load_user_files(job_id,user_file) current_file = filename print('GearSwap: Loaded your '..current_file..' file!') end - + setfenv(funct, user_env) - + -- Verify that funct contains functions. local status, plugin = pcall(funct) - + if not status then error('GearSwap: File failed to load: \n'..plugin) sets = nil return nil end - + _global.pretarget_cast_delay = 0 _global.precast_cast_delay = 0 _global.cancel_spell = false _global.current_event = 'get_sets' user_pcall('get_sets') - + gearswap_disabled = false sets = user_env.sets end @@ -204,10 +204,10 @@ function refresh_player(dt,user_event_flag) if not user_event_flag or dt > 0.5 then pl = windower.ffxi.get_player() if not pl or not pl.vitals then return end - + player_mob_table = windower.ffxi.get_mob_by_index(pl.index) if not player_mob_table then return end - + table.reassign(player,pl) for i,v in pairs(player.vitals) do player[i]=v @@ -221,7 +221,7 @@ function refresh_player(dt,user_event_flag) end player.nation_id = player.nation player.nation = res.regions[player.nation_id][language] or 'None' - + for i,v in pairs(player_mob_table) do if i == 'name' then player.mob_name = v @@ -229,12 +229,12 @@ function refresh_player(dt,user_event_flag) player[i] = v end end - + if player_mob_table.race ~= nil then player.race_id = player.race player.race = res.races[player.race][language] end - + -- If we have a pet, create or update the table info. if player_mob_table and player_mob_table.pet_index then local player_pet_table = windower.ffxi.get_mob_by_index(player_mob_table.pet_index) @@ -244,7 +244,7 @@ function refresh_player(dt,user_event_flag) pet.is_npc = nil pet.isvalid = true if pet.tp then pet.tp = pet.tp/10 end - + if avatar_element[pet.name] then pet.element = res.elements[avatar_element[pet.name]][language] else @@ -256,12 +256,12 @@ function refresh_player(dt,user_event_flag) else table.reassign(pet, {isvalid=false}) end - + if player.main_job_id == 18 or player.sub_job_id == 18 then local auto_tab if player.main_job_id == 18 then auto_tab = windower.ffxi.get_mjob_data() else auto_tab = windower.ffxi.get_sjob_data() end - + if auto_tab.name then for i,v in pairs(auto_tab) do if not T{'available_heads','attachments','available_frames','available_attachments','frame','head'}:contains(i) then @@ -298,7 +298,7 @@ function refresh_player(dt,user_event_flag) pet.attachments[res.items[id][language]] = true end end - + if pet.max_mp ~= 0 then pet.mpp = math.floor(pet.mp/pet.max_mp*100) else @@ -308,7 +308,7 @@ function refresh_player(dt,user_event_flag) elseif player.main_job_id == 23 then local species_id = windower.ffxi.get_mjob_data().species -- Should add instincts when they become available - + if species_id then player.species = {} for i,v in pairs(res.monstrosity[species_id]) do @@ -326,15 +326,15 @@ function refresh_player(dt,user_event_flag) player.species = nil end end - + -- This being nil does not cause a return, but items should not really be changing when zoning. local cur_equip = table.reassign({},items.equipment) - + -- Assign player.equipment to be the gear that has been sent out and the server currently thinks -- you are wearing. (the sent_out_equip for loop above). player.equipment = make_user_table() table.reassign(player.equipment,to_names_set(cur_equip)) - + -- Assign player.inventory to be keyed to item.inventory[i][language] and to have a value of count, similar to buffactive for i,bag in pairs(res.bags) do local bag_name = to_windower_bag_api(bag.en) @@ -345,18 +345,18 @@ function refresh_player(dt,user_event_flag) player.target = target_complete(windower.ffxi.get_mob_by_target('t')) player.subtarget = target_complete(windower.ffxi.get_mob_by_target('st')) player.last_subtarget = target_complete(windower.ffxi.get_mob_by_target('lastst')) + - - + table.reassign(fellow,target_complete(windower.ffxi.get_mob_by_target(''))) if fellow.name then fellow.isvalid = true else fellow.isvalid=false end - + table.reassign(buffactive,convert_buff_list(player.buffs)) - + for global_variable_name,extradatatable in pairs(_ExtraData) do if _G[global_variable_name] then for sub_variable_name,value in pairs(extradatatable) do @@ -396,7 +396,7 @@ function refresh_ffxi_info(dt,user_event_flag) world[i] = v end end - + for global_variable_name,extradatatable in pairs(_ExtraData) do if _G[global_variable_name] then for sub_variable_name,value in pairs(extradatatable) do @@ -477,25 +477,25 @@ function refresh_group_info(dt,user_event_flag) if not alliance or #alliance == 0 then alliance = make_alliance() end - + local c_alliance = make_alliance() - + local j = windower.ffxi.get_party() or {} - + c_alliance.leader = j.alliance_leader -- Test whether this works c_alliance[1].leader = j.party1_leader c_alliance[2].leader = j.party2_leader c_alliance[3].leader = j.party3_leader - + for i,v in pairs(j) do if type(v) == 'table' and v.mob and v.mob.race then v.mob.race_id = v.mob.race v.mob.race = res.races[v.mob.race][language] end - + local allyIndex local partyIndex - + -- For 'p#', ally index is 1, party index is the second char if i:sub(1,1) == 'p' and tonumber(i:sub(2)) then allyIndex = 1 @@ -505,7 +505,7 @@ function refresh_group_info(dt,user_event_flag) allyIndex = tonumber(i:sub(2,2))+1 partyIndex = tonumber(i:sub(3))+1 end - + if allyIndex and partyIndex then if v.mob and partybuffs[v.mob.index] then v.buffactive = convert_buff_list(partybuffs[v.mob.index].buffs) @@ -515,7 +515,7 @@ function refresh_group_info(dt,user_event_flag) c_alliance[allyIndex][partyIndex] = v c_alliance[allyIndex].count = c_alliance[allyIndex].count + 1 c_alliance.count = c_alliance.count + 1 - + if v.mob then if v.mob.id == c_alliance[1].leader then c_alliance[1].leader = v @@ -524,14 +524,14 @@ function refresh_group_info(dt,user_event_flag) elseif v.mob.id == c_alliance[3].leader then c_alliance[3].leader = v end - + if v.mob.id == c_alliance.leader then c_alliance.leader = v end end end end - + -- Clear the old structure while maintaining the party references: for ally_party = 1,3 do @@ -542,7 +542,7 @@ function refresh_group_info(dt,user_event_flag) end alliance.count = 0 alliance.leader = nil - + -- Reassign to the new structure table.reassign(alliance[1],c_alliance[1]) table.reassign(alliance[2],c_alliance[2]) @@ -582,15 +582,15 @@ end ----------------------------------------------------------------------------------- function convert_buff_list(bufflist) local buffarr = {} - for i,id in pairs(bufflist) do - if res.buffs[id] then -- For some reason we always have buff 255 active, which doesn't have an entry. + for _,id in pairs(bufflist) do + if res.buffs[id] then local buff = res.buffs[id][language]:lower() if buffarr[buff] then buffarr[buff] = buffarr[buff] +1 else buffarr[buff] = 1 end - + if buffarr[id] then buffarr[id] = buffarr[id] +1 else @@ -656,7 +656,7 @@ end function refresh_user_env(job_id) refresh_globals() if not job_id then job_id = windower.ffxi.get_player().main_job_id end - + if not job_id then windower.send_command('@wait 1;lua i '.._addon.name..' refresh_user_env') else @@ -678,17 +678,17 @@ function pathsearch(files_list) -- base directory search order: -- windower -- %appdata%/Windower/GearSwap - + -- sub directory search order: -- libs-dev (only in windower addon path) -- libs (only in windower addon path) -- data/player.name -- data/common -- data - + local gearswap_data = windower.addon_path .. 'data/' local gearswap_appdata = (os.getenv('APPDATA') or '') .. '/Windower/GearSwap/' - + local search_path = { [1] = windower.addon_path .. 'libs-dev/', [2] = windower.addon_path .. 'libs/', @@ -700,7 +700,7 @@ function pathsearch(files_list) [8] = gearswap_appdata, [9] = windower.windower_path .. 'addons/libs/' } - + local user_path local normal_path @@ -712,7 +712,7 @@ function pathsearch(files_list) user_path = basepath .. include_user_path .. '/' .. v end normal_path = basepath .. v - + if user_path and windower.file_exists(user_path) then return user_path,basepath,v elseif normal_path and windower.file_exists(normal_path) then @@ -722,6 +722,6 @@ function pathsearch(files_list) end end end - + return false end From b0ebde6ffc8f95918f7b7e59f3ba389d3b4d2218 Mon Sep 17 00:00:00 2001 From: Byrth Date: Sat, 7 Jan 2023 13:29:48 -0500 Subject: [PATCH 0907/1002] Batch buff_details and add for party members --- addons/GearSwap/packet_parsing.lua | 132 +++++++++++++++++------------ addons/GearSwap/refresh.lua | 5 +- addons/GearSwap/statics.lua | 40 ++++----- 3 files changed, 101 insertions(+), 76 deletions(-) diff --git a/addons/GearSwap/packet_parsing.lua b/addons/GearSwap/packet_parsing.lua index 410ea7613c..3b9541d889 100644 --- a/addons/GearSwap/packet_parsing.lua +++ b/addons/GearSwap/packet_parsing.lua @@ -33,7 +33,7 @@ parse.i[0x00A] = function (data) windower.debug('zone change') command_registry = Command_Registry.new() table.clear(not_sent_out_equip) - + player.id = data:unpack('I',0x05) player.index = data:unpack('H',0x09) if player.main_job_id and player.main_job_id ~= data:byte(0xB5) and player.name and player.name == data:unpack('z',0x85) and not gearswap_disabled then @@ -49,7 +49,7 @@ parse.i[0x00A] = function (data) player.max_hp = data:unpack('I',0xE9) player.max_mp = data:unpack('I',0xED) update_job_names() - + world.zone_id = data:unpack('H',0x31) _ExtraData.world.conquest = false for i,v in pairs(region_to_zone_map) do @@ -63,9 +63,9 @@ parse.i[0x00A] = function (data) end weather_update(data:byte(0x69)) world.logged_in = true - + _ExtraData.world.in_mog_house = data:byte(0x81) == 1 - + _ExtraData.player.base_str = data:unpack('H',0xCD) _ExtraData.player.base_dex = data:unpack('H',0xCF) _ExtraData.player.base_vit = data:unpack('H',0xD1) @@ -80,7 +80,7 @@ parse.i[0x00A] = function (data) _ExtraData.player.add_int = data:unpack('h',0xE3) _ExtraData.player.add_mnd = data:unpack('h',0xE5) _ExtraData.player.add_chr = data:unpack('h',0xE7) - + _ExtraData.player.str = _ExtraData.player.base_str + _ExtraData.player.add_str _ExtraData.player.dex = _ExtraData.player.base_dex + _ExtraData.player.add_dex _ExtraData.player.vit = _ExtraData.player.base_vit + _ExtraData.player.add_vit @@ -89,7 +89,7 @@ parse.i[0x00A] = function (data) _ExtraData.player.mnd = _ExtraData.player.base_mnd + _ExtraData.player.add_mnd _ExtraData.player.chr = _ExtraData.player.base_chr + _ExtraData.player.add_chr refresh_ffxi_info() - + blank_0x063_v9_inc = true end @@ -115,7 +115,7 @@ parse.i[0x01B] = function (data) for job_id = 1,23 do player.jobs[to_windower_api(res.jobs[job_id].english)] = data:byte(job_id + 72) end - + local enc = data:unpack('H',0x61) local tab = {} for slot_id,slot_name in pairs(default_slot_map) do @@ -243,12 +243,12 @@ function parse_equip_chunk(chunk) if inv_slot == 0 then -- Unequipping local bag_id = items.equipment[equip_slot].bag_id inv_slot = items.equipment[equip_slot].slot - + if inv_slot == empty then return end -- unequipping something that was already unequipped? - + local inv = items[to_windower_compact(res.bags[bag_id].english)] if not inv[inv_slot] then inv[inv_slot] = make_empty_item_table(inv_slot) end - + inv[inv_slot].status = 0 -- Set the status to "unequipped" items.equipment[equip_slot] = {slot=empty,bag_id=0} else @@ -380,7 +380,7 @@ parse.i[0x061] = function (data) player.max_mp = data:unpack('I',9) player.main_job_id = data:byte(13) player.main_job_level = data:byte(14) - + _ExtraData.player.nation_id = data:byte(0x51) _ExtraData.player.nation = res.regions[_ExtraData.player.nation_id][language] or 'None' _ExtraData.player.base_str = data:unpack('H',0x15) @@ -407,7 +407,7 @@ parse.i[0x061] = function (data) _ExtraData.player.earth_resistance = data:unpack('h',0x3F) _ExtraData.player.water_resistance = data:unpack('h',0x41) _ExtraData.player.dark_resistance = data:unpack('h',0x43) - + _ExtraData.player.str = _ExtraData.player.base_str + _ExtraData.player.add_str _ExtraData.player.dex = _ExtraData.player.base_dex + _ExtraData.player.add_dex _ExtraData.player.vit = _ExtraData.player.base_vit + _ExtraData.player.add_vit @@ -415,7 +415,7 @@ parse.i[0x061] = function (data) _ExtraData.player.int = _ExtraData.player.base_int + _ExtraData.player.add_int _ExtraData.player.mnd = _ExtraData.player.base_mnd + _ExtraData.player.add_mnd _ExtraData.player.chr = _ExtraData.player.base_chr + _ExtraData.player.add_chr - + if player.sub_job_id ~= data:byte(15) then -- Subjob change event local temp_sub = player.sub_job @@ -463,7 +463,7 @@ parse.i[0x063] = function (data) newbuffs[i] = setmetatable({ name=res.buffs[buff_id].name, buff=copy_entry(res.buffs[buff_id]), - id = buff_id, + id=buff_id, time=t, date=os.date('*t',t), }, @@ -489,7 +489,7 @@ parse.i[0x063] = function (data) end end end - + -- Look for time-independent matches, which are assumedly a spell overwriting itself for n,new in pairs(newbuffs) do newbuffs[n].matched_imprecisely = nil @@ -504,7 +504,8 @@ parse.i[0x063] = function (data) end end end - + + local batch = L{} for n,new in pairs(newbuffs) do if new.matched_exactly then newbuffs[n].matched_exactly = nil @@ -517,7 +518,7 @@ parse.i[0x063] = function (data) end local buff_name = res.buffs[new.id][language] windower.debug('refresh buff '..buff_name..' ('..tostring(new.id)..')') - if not gearswap_disabled then + if false and not gearswap_disabled then refresh_globals() equip_sets('buff_refresh',nil,buff_name,new) end @@ -529,17 +530,14 @@ parse.i[0x063] = function (data) local buff_name = res.buffs[new.id][language] windower.debug('gain buff '..buff_name..' ('..tostring(new.id)..')') -- Need to figure out what I'm going to do with this: - if T{'terror','sleep','stun','petrification','charm','weakness'}:contains(buff_name:lower()) then + if T{'terror','sleep','stun','petrification','charm','weakness','lullaby'}:contains(buff_name:lower()) then for ts,v in pairs(command_registry) do if v.midaction then command_registry:delete_entry(ts) end end end - if not gearswap_disabled then - refresh_globals() - equip_sets('buff_change',nil,buff_name,true,new) - end + batch:append({name=buff_name,gain=true,tab=new}) end end for i,old in pairs(_ExtraData.player.buff_details) do @@ -550,10 +548,13 @@ parse.i[0x063] = function (data) end local buff_name = res.buffs[old.id][language] windower.debug('lose buff '..buff_name..' ('..tostring(old.id)..')') - if not gearswap_disabled then - refresh_globals() - equip_sets('buff_change',nil,buff_name,false,old) - end + batch:append({name=buff_name,gain=false,tab=old}) + end + end + if not gearswap_disabled and #batch > 0 then + refresh_globals() + for v,_ in batch:it() do + equip_sets('buff_change',nil,v.name,v.gain,v.tab) end end end @@ -575,29 +576,33 @@ parse.i[0x067] = function (data) end parse.i[0x068] = function (data) - if player.index == data:unpack('H',0x07) then -- You are the owner _ExtraData.pet.tp = data:unpack('H',0x11) end end parse.i[0x076] = function (data) - partybuffs = {} + _ExtraPartyData.buffs = {} + _ExtraPartyData.buff_details = {} for i = 0,4 do if data:unpack('I',i*48+5) == 0 then break else local index = data:unpack('H',i*48+5+4) - partybuffs[index] = { - id = data:unpack('I',i*48+5+0), - index = data:unpack('H',i*48+5+4), - buffs = {} - } + _ExtraPartyData.buffs[index] = {} + _ExtraPartyData.buff_details[index] = {} for n=1,32 do - partybuffs[index].buffs[n] = data:byte(i*48+5+16+n-1) + 256*( math.floor( data:byte(i*48+5+8+ math.floor((n-1)/4)) / 4^((n-1)%4) )%4) + local buff_id = data:byte(i*48+5+16+n-1) + 256*( math.floor( data:byte(i*48+5+8+ math.floor((n-1)/4)) / 4^((n-1)%4) )%4) + if buff_id ~= 255 and buff_id ~= 0 then + _ExtraPartyData.buffs[index][n] = buff_id + _ExtraPartyData.buff_details[index][n] = { + name=res.buffs[buff_id].name, + buff=copy_entry(res.buffs[buff_id]), + id=buff_id, + } + end end - - + if alliance[1] then local cur_player for n,m in pairs(alliance[1]) do @@ -606,17 +611,26 @@ parse.i[0x076] = function (data) break end end - local new_buffs = convert_buff_list(partybuffs[index].buffs) - if cur_player and cur_player.buffactive and not gearswap_disabled then + local new_buffs = convert_buff_list(_ExtraPartyData.buffs[index]) + if index == 1464 then + local newbuff_count = 0 + for _,v in pairs(new_buffs) do + newbuff_count = newbuff_count + 1 + end + end + if cur_player and cur_player.buffactive and not gearswap_disabled and + user_env and type(user_env['party_buff_change']) == 'function' then + -- Make sure the character existed before (with a buffactive list) - Avoids zoning. + -- This is also the heaviest event, so make sure the user is using it. local old_buffs = cur_player.buffactive - -- Make sure the character existed before (with a buffactive list) - Avoids zoning. + local batch = L{} for n,m in pairs(new_buffs) do if type(n) == 'number' and m ~= old_buffs[n] then if not old_buffs[n] or m > old_buffs[n] then -- gaining buff - equip_sets('party_buff_change',nil,cur_player,res.buffs[n][language],true,copy_entry(res.buffs[n])) + batch:append({player=cur_player,name=res.buffs[n][language],gain=true,tab=copy_entry(res.buffs[n])}) old_buffs[n] = nil else -- losing buff - equip_sets('party_buff_change',nil,cur_player,res.buffs[n][language],false,copy_entry(res.buffs[n])) + batch:append({player=cur_player,name=res.buffs[n][language],gain=false,tab=copy_entry(res.buffs[n])}) old_buffs[n] = nil end elseif type(n) ~= 'number' then @@ -624,18 +638,34 @@ parse.i[0x076] = function (data) old_buffs[n] = nil end end - + for n,m in pairs(old_buffs) do if type(n) == 'number' and m ~= new_buffs[n] then-- losing buff - equip_sets('party_buff_change',nil,cur_player,res.buffs[n][language],false,copy_entry(res.buffs[n])) + batch:append({player=cur_player,name=res.buffs[n][language],gain=false,tab=copy_entry(res.buffs[n])}) + end + end + if #batch > 0 then + refresh_globals() + for v,_ in batch:it() do + equip_sets('party_buff_change',nil,v.player,v.name,v.gain,v.tab) end end end if cur_player then - cur_player.buffactive = new_buffs + if cur_player.buffactive then + table.reassign(cur_player.buffactive, new_buffs) + else + cur_player.buffactive = new_buffs + end + end + if cur_player and cur_player.id ~= player.id then + if cur_player.buff_details then + table.reassign(cur_player.buff_details,_ExtraPartyData.buff_details[index]) + else + cur_player.buff_details = _ExtraPartyData.buff_details[index] + end end end - end end end @@ -647,7 +677,7 @@ function update_vitals(id, hp, mp, tp, hpp, mpp) player.vitals.tp = tp player.vitals.hpp = hpp player.vitals.mpp = mpp - + player.hp = hp player.mp = mp player.tp = tp @@ -702,9 +732,9 @@ parse.o[0x100] = function(data) local newmain = data:byte(5) if res.jobs[newmain] and newmain ~= 0 and newmain ~= player.main_job_id then windower.debug('job change') - + command_registry = Command_Registry.new() - + table.clear(not_sent_out_equip) table.clear(equip_list_history) table.clear(equip_list) @@ -716,10 +746,9 @@ parse.o[0x100] = function(data) end windower.send_command('lua i '.._addon.name..' load_user_files '..newmain) end - - + if gearswap_disabled then return end - + local newmain = data:byte(5) if res.jobs[newmain] and newmain ~= player.main_job_id then command_enable('main','sub','range','ammo','head','neck','lear','rear','body','hands','lring','rring','back','waist','legs','feet') -- enable all slots @@ -735,7 +764,6 @@ function initialize_packet_parsing() end if i == 0x63 and lastpacket and lastpacket:byte(5) ~= 9 then -- Not receiving an accurate buff line on load because the wrong 0x063 packet was sent last - end end end diff --git a/addons/GearSwap/refresh.lua b/addons/GearSwap/refresh.lua index fd5798786d..18040d1824 100644 --- a/addons/GearSwap/refresh.lua +++ b/addons/GearSwap/refresh.lua @@ -507,8 +507,9 @@ function refresh_group_info(dt,user_event_flag) end if allyIndex and partyIndex then - if v.mob and partybuffs[v.mob.index] then - v.buffactive = convert_buff_list(partybuffs[v.mob.index].buffs) + if v.mob and _ExtraPartyData.buffs[v.mob.index] then + v.buffactive = convert_buff_list(_ExtraPartyData.buffs[v.mob.index]) + v.buff_details = _ExtraPartyData.buff_details[v.mob.index] elseif v.mob and v.mob.index == player.index then v.buffactive = buffactive end diff --git a/addons/GearSwap/statics.lua b/addons/GearSwap/statics.lua index a81f428bee..b0fd4a0587 100644 --- a/addons/GearSwap/statics.lua +++ b/addons/GearSwap/statics.lua @@ -25,7 +25,7 @@ --SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- Convert the spells and job abilities into a referenceable list of aliases -- - + unify_prefix = {['/ma'] = '/ma', ['/magic']='/ma',['/jobability'] = '/ja',['/ja']='/ja',['/item']='/item',['/song']='/ma', ['/so']='/ma',['/ninjutsu']='/ma',['/weaponskill']='/ws',['/ws']='/ws',['/ra']='/ra',['/rangedattack']='/ra',['/nin']='/ma', ['/throw']='/ra',['/range']='/ra',['/shoot']='/ra',['/monsterskill']='/ms',['/ms']='/ms',['/pet']='/ja',['Monster']='Monster',['/bstpet']='/ja'} @@ -37,16 +37,16 @@ action_type_map = {['/ja']='Ability',['/jobability']='Ability',['/so']='Magic',[ equippable_item_bags = {res.bags:equippable(true):extract()} usable_item_bags = {res.bags:with('command','temporary'), table.extract(equippable_item_bags)} - + bag_string_lookup = {} for i,v in pairs(res.bags) do bag_string_lookup[to_windower_bag_api(v.en)]=i end - + bstpet_range = {min=672,max=798} -- Range of the JA resource devoted to BST jugpet abilities - + delay_map_to_action_type = {['Ability']=3,['Magic']=20,['Ranged Attack']=10,['Item']=10,['Monster Move']=10,['Interruption']=3} - + validabils = {} validabils['english'] = {['/ma'] = {}, ['/ja'] = {}, ['/ws'] = {}, ['/item'] = {}, ['/ra'] = {}, ['/ms'] = {}, ['/pet'] = {}, ['/trig'] = {}, ['/echo'] = {}} validabils['french'] = {['/ma'] = {}, ['/ja'] = {}, ['/ws'] = {}, ['/item'] = {}, ['/ra'] = {}, ['/ms'] = {}, ['/pet'] = {}, ['/trig'] = {}, ['/echo'] = {}} @@ -92,7 +92,7 @@ for i,v in pairs(res.items) do make_entry(v,i) end end - + -- Should transition these slot maps to be based off res.slots, but it's very unlikely to change. default_slot_map = T{'sub','range','ammo','head','body','hands','legs','feet','neck','waist', 'left_ear', 'right_ear', 'left_ring', 'right_ring','back'} @@ -126,14 +126,14 @@ encumbrance_map[0] = 0x79 -- Slots mapped onto encumbrance byte values. addendum_white = {[14]="Poisona",[15]="Paralyna",[16]="Blindna",[17]="Silena",[18]="Stona",[19]="Viruna",[20]="Cursna", [143]="Erase",[13]="Raise II",[140]="Raise III",[141]="Reraise II",[142]="Reraise III",[135]="Reraise"} - + addendum_black = {[253]="Sleep",[259]="Sleep II",[260]="Dispel",[162]="Stone IV",[163]="Stone V",[167]="Thunder IV", [168]="Thunder V",[157]="Aero IV",[158]="Aero V",[152]="Blizzard IV",[153]="Blizzard V",[147]="Fire IV",[148]="Fire V", [172]="Water IV",[173]="Water V",[255]="Break"} resources_ranged_attack = {id="0",index="0",prefix="/range",english="Ranged",german="Fernwaffe",french="Attaque à dist.",japanese="飛び道具",type="Misc",element="None",targets=S{"Enemy"}} - + -- _globals -- user_data_table = { __newindex = function(tab, key, val) @@ -145,16 +145,6 @@ user_data_table = { end } ---[[eq_data_table = { - __newindex = function(tab, key, val) - rawset(tab, slot_map[user_key_filter(key)], newtab) - end, - - __index = function(tab, key) - return rawget(tab, slot_map[user_key_filter(key)]) - end - }]] - slot_map = make_user_table() slot_map.main = 0 @@ -232,6 +222,12 @@ _ExtraData = { pet = {}, world = {in_mog_house = false,conquest=false}, } +-- _ExtraPartyData is the same, but for the party. +-- These structures are necessarily indexed by player index. +_ExtraPartyData = { + buffs = {}, + buff_details = {}, +} unbridled_learning_set = {['Thunderbolt']=true,['Harden Shell']=true,['Absolute Terror']=true, ['Gates of Hades']=true,['Tourbillion']=true,['Pyric Bulwark']=true,['Bilgestorm']=true, @@ -334,7 +330,7 @@ universal_tool_map = { ['Yain: Ichi'] = res.items[2972], } -region_to_zone_map = { +region_to_zone_map = { [4] = S{100,101,139,140,141,142,167,190}, [5] = S{102,103,108,193,196,248}, [6] = S{1,2,104,105,149,150,195}, @@ -355,7 +351,7 @@ region_to_zone_map = { [22] = S{11,12,13}, [24] = S{24,25,26,27,28,29,30,31,32}, } - + function initialize_globals() local pl = windower.ffxi.get_player() @@ -375,14 +371,14 @@ function initialize_globals() if not player.jobs then player.jobs = {} end if not player.merits then player.merits = {} end end - + player.equipment = make_user_table() pet = make_user_table() pet.isvalid = false fellow = make_user_table() fellow.isvalid = false partybuffs = {} - + -- GearSwap effectively needs to maintain two inventory structures: -- one is the proposed current inventory based on equip packets sent to the server, -- the other is the currently reported inventory based on packets sent from the server. From 24206d1fc46b59d8451e0d2194bb889e43b06077 Mon Sep 17 00:00:00 2001 From: Byrth Date: Sat, 7 Jan 2023 13:29:58 -0500 Subject: [PATCH 0908/1002] Fix bug in move_spell_target() --- addons/GearSwap/user_functions.lua | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/addons/GearSwap/user_functions.lua b/addons/GearSwap/user_functions.lua index afdcf84816..2062955ddc 100644 --- a/addons/GearSwap/user_functions.lua +++ b/addons/GearSwap/user_functions.lua @@ -77,10 +77,10 @@ function move_spell_target(position_table) error('\nGearSwap: move_spell_target() is only valid in the precast function', 2) return end - + if type(position_table) == 'table' and type(position_table.x or position_table.X) == 'number' and type(position_table.y or position_table.Y) == 'number' and - type(position_table.z or positino_table.Z) == 'number' then + type(position_table.z or position_table.Z) == 'number' then _global.target_arrow.x = position_table.x or position_table.X _global.target_arrow.y = position_table.y or position_table.Y _global.target_arrow.z = position_table.z or position_table.Z @@ -160,13 +160,13 @@ function enable(...) error('\nGearSwap: enable error, passed an unrecognized slot name. ('..tostring(v)..')',2) end end - + return sending_table end function user_enable(...) local sending_table = enable(...) - + if table.length(sending_table) > 0 then equip(sending_table) end @@ -175,7 +175,7 @@ end function command_enable(...) local sending_table = enable(...) - + if table.length(sending_table) > 0 then refresh_globals() equip_sets('equip_command',nil,sending_table) @@ -223,7 +223,7 @@ function print_set(set,title) end end end - + if #set == table.length(set) then -- If it is a list (keyed by continuous whole number starting at 1), then print it out in order for key,value in ipairs(set) do print_element(key,value) @@ -235,7 +235,7 @@ function print_set(set,title) print_element(k,set[k]) end end - for key,value in pairs(set) do + for key,_ in pairs(set) do if not slot_map[key] then print_element(key,set[key]) end @@ -301,21 +301,21 @@ function include_user(str, load_include_in_this_table) if not (type(str) == 'string') then error('\nGearSwap: include() was passed an invalid value ('..tostring(str)..'). (must be a string)', 2) end - + str = str:lower() if type(package.loaded[str]) == 'table' then return package.loaded[str] elseif T{'pack'}:contains(str) then return end - + if str:sub(-4)~='.lua' then str = str..'.lua' end local path, loaded_values = pathsearch({str}) - + if not path then error('\nGearSwap: Cannot find the include file ('..tostring(str)..').', 2) end - + local f, err = loadfile(path) if f and not err then if load_include_in_this_table and type(load_include_in_this_table) == 'table' then @@ -358,7 +358,7 @@ function user_midaction(bool) return true, v.spell end end - + return false end @@ -390,7 +390,7 @@ function add_to_chat_user(num,str) -- It only needs the number. num=8 end - + if language == 'japanese' then msg.add_to_chat(num,windower.to_shift_jis(str)) else @@ -420,4 +420,4 @@ user_windower = {register_event = register_event_user, raw_register_event = raw_ user_coroutine = coroutine user_coroutine.sleep = user_sleep user_coroutine.yield = user_yield -setmetatable(user_windower,{__index=windower}) \ No newline at end of file +setmetatable(user_windower,{__index=windower}) From ddd8f506c2faade6a5cfecbc3205dc390c106c0b Mon Sep 17 00:00:00 2001 From: Byrth Date: Sat, 7 Jan 2023 13:32:57 -0500 Subject: [PATCH 0909/1002] add disable check to check_spell() for gear spells --- addons/GearSwap/helper_functions.lua | 72 +++++++++++++++------------- 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/addons/GearSwap/helper_functions.lua b/addons/GearSwap/helper_functions.lua index 0034d6031a..9732048843 100644 --- a/addons/GearSwap/helper_functions.lua +++ b/addons/GearSwap/helper_functions.lua @@ -148,7 +148,7 @@ end function is_slot_key(k) return slot_map[k] end - + ----------------------------------------------------------------------------------- ----Name: make_empty_item_table(slot) @@ -273,7 +273,7 @@ function update_job_names() player.job = player.main_job..'/'..player.sub_job end - + ----------------------------------------------------------------------------------- ----Name: get_default_slot(k) -- Given a generally known slot key, return the default version of that key. @@ -325,7 +325,7 @@ function set_merge(respect_disable, baseSet, ...) end end end - + return baseSet end @@ -349,7 +349,7 @@ function parse_set_to_keys(str) if type(str) == 'table' then str = table.concat(str, ' ') end - + -- Parsing results get pushed into the result list. local result = L{} @@ -358,7 +358,7 @@ function parse_set_to_keys(str) local stop local sep = '.' local count = 0 - + -- Loop as long as remainder hasn't been nil'd or reduced to 0 characters, but only to a maximum of 30 tries. while remainder ~= "" and count < 30 do -- Try aaa.bbb set names first @@ -369,7 +369,7 @@ function parse_set_to_keys(str) -- "remainder" is everything after that result:append(key) end - + -- Then try aaa['bbb'] set names. -- Be sure to account for both single and double quote enclosures. -- Ignore periods contained within quote strings. @@ -397,7 +397,7 @@ function parse_set_to_keys(str) end result:append(key) end - + count = count +1 end @@ -444,11 +444,11 @@ end function initialize_arrow_offset(mob_table) local backtab = {} local arrow = windower.ffxi.get_info().target_arrow - + if arrow.x == 0 and arrow.y == 0 and arrow.z == 0 then return arrow end - + backtab.x = arrow.x-mob_table.x backtab.y = arrow.y-mob_table.y backtab.z = arrow.z-mob_table.z @@ -473,11 +473,11 @@ function assemble_action_packet(target_id,target_index,category,spell_id,arrow_o outstr = outstr..string.char( (target_id%256), math.floor(target_id/256)%256, math.floor( (target_id/65536)%256) , math.floor( (target_id/16777216)%256) ) outstr = outstr..string.char( (target_index%256), math.floor(target_index/256)%256) outstr = outstr..string.char( (category%256), math.floor(category/256)%256) - + if category == 16 then spell_id = 0 end - + outstr = outstr..string.char( (spell_id%256), math.floor(spell_id/256)%256)..string.char(0,0) .. 'fff':pack(arrow_offset.x,arrow_offset.z,arrow_offset.y) return outstr end @@ -524,7 +524,7 @@ end function assemble_menu_item_packet(target_id,target_index,...) local outstr = string.char(0x36,0x20,0,0) -- Message is coming out too short by 12 characters - + -- Target ID outstr = outstr.."I":pack(target_id) local item_ids,counts,count = {...},{},0 @@ -534,7 +534,7 @@ function assemble_menu_item_packet(target_id,target_index,...) count = count + 1 end end - + local unique_items = 0 for i,v in pairs(counts) do outstr = outstr.."I":pack(v) @@ -547,9 +547,9 @@ function assemble_menu_item_packet(target_id,target_index,...) while #outstr < 0x30 do outstr = outstr..string.char(0) end - + -- Inventory Index for the one unit - + for i,v in pairs(counts) do inventory_index = find_inventory_item(i) if inventory_index then @@ -685,7 +685,7 @@ function filter_pretarget(action) msg.debugging("Unable to execute command. You do not have access to that monsterskill ("..(res.monster_skills[action.id][language] or action.id)..")") return false end - + if err then msg.debugging(err) end @@ -705,9 +705,15 @@ end ---- false if the spell is not currently accessible ----------------------------------------------------------------------------------- function check_spell(available_spells,spell) - -- Filter for spells that you do not know. Exclude Impact / Dispelga. + -- Filter for spells that you do not know. + -- Exclude Impact / Dispelga / Honor March if the respective slots are enabled. + -- Need to add logic to check whether the equipment is already on local spell_jobs = copy_entry(res.spells[spell.id].levels) - if not available_spells[spell.id] and not (spell.id == 503 or spell.id == 417 or spell.id == 360) then + if not available_spells[spell.id] and not ( + (not disable_table[5] and not disable_table[4] and spell.id == 503) or -- Body + Head + Impact + (not disable_table[2] and spell.id == 417) or -- Range + Honor March + ((not disable_table[0] or not disable_table[1]) and spell.id == 360) -- Main or Sub + Dispelga + ) then return false,"Unable to execute command. You do not know that spell ("..(res.spells[spell.id][language] or spell.id)..")" -- Filter for spells that you know, but do not currently have access to elseif (not spell_jobs[player.main_job_id] or not (spell_jobs[player.main_job_id] <= player.main_job_level or @@ -883,7 +889,7 @@ end function cmd_reg:find_by_time(target_time) local time_stamp,ts target_time = target_time or os.time() - + -- Iterate over command_registry looking for the spell with the closest timestamp. -- Call aftercast with this spell's information (interrupted) if one is found. for i,v in pairs(self) do @@ -951,14 +957,14 @@ 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 == 12 or act.category == 2 then spell = copy_entry(resources_ranged_attack) else @@ -975,13 +981,13 @@ function get_spell(act) else spell = {name=tostring(msg_ID)} end - + return spell end - + local fields = fieldsearch(res.action_messages[msg_ID].english) -- ENGLISH - + if table.contains(fields,'spell') then spell = copy_entry(res.spells[abil_ID]) if act.category == 4 then spell.recast = act.recast end @@ -1011,7 +1017,7 @@ function get_spell(act) elseif msg_ID == 328 then spell = copy_entry(res.job_abilities[effect_val]) -- BPs that are out of range end - + if table.contains(fields,'item') then if spell then @@ -1023,12 +1029,12 @@ function get_spell(act) spell = spell_complete(spell) end end - + if spell then spell.name = spell[language] spell.interrupted = false end - + return spell end @@ -1054,7 +1060,7 @@ function spell_complete(rline) -- Entrust allows Indi- spells to be cast on party members rline.targets.Party = true end - + if rline == nil then return {tpaftercast = player.tp, mpaftercast = player.mp, mppaftercast = player.mpp} end @@ -1064,18 +1070,18 @@ function spell_complete(rline) elseif not rline.tp_cost or rline.tp_cost == -1 then rline.tp_cost = 0 end - + if rline.skill and tonumber(rline.skill) then rline.skill = res.skills[rline.skill][language] end - + if rline.element and tonumber(rline.element) then rline.element = res.elements[rline.element][language] end - + if rline.tp_cost == 0 then rline.tpaftercast = player.tp else rline.tpaftercast = player.tp - rline.tp_cost end - + if rline.mp_cost == 0 then rline.mpaftercast = player.mp rline.mppaftercast = player.mpp @@ -1083,7 +1089,7 @@ function spell_complete(rline) rline.mpaftercast = player.mp - rline.mp_cost rline.mppaftercast = (player.mp - rline.mp_cost)/player.max_mp end - + return rline end From 618e6f47ffbd6d42690e3d624f94b6d00c2f8644 Mon Sep 17 00:00:00 2001 From: Byrth Date: Sat, 7 Jan 2023 13:33:12 -0500 Subject: [PATCH 0910/1002] I just deleted dead code --- addons/GearSwap/flow.lua | 81 ++++++++++++---------------------------- 1 file changed, 24 insertions(+), 57 deletions(-) diff --git a/addons/GearSwap/flow.lua b/addons/GearSwap/flow.lua index ef5a1eecd1..dcc3459b33 100644 --- a/addons/GearSwap/flow.lua +++ b/addons/GearSwap/flow.lua @@ -47,16 +47,16 @@ function equip_sets(swap_type,ts,...) local val2 = var_inps[2] table.reassign(_global,command_registry[ts] or {pretarget_cast_delay = 0,precast_cast_delay=0,cancel_spell = false, new_target=false,target_arrow={x=0,y=0,z=0}}) _global.current_event = tostring(swap_type) - + if _global.current_event == 'precast' and val1 and val1.english and val1.english:find('Geo-') then _global.target_arrow = initialize_arrow_offset(val1.target) end - + windower.debug(tostring(swap_type)..' enter') if showphase or debugging.general then msg.debugging(8,windower.to_shift_jis(tostring(swap_type))..' enter') end - + local cur_equip = table.reassign({},update_equipment()) - + table.reassign(equip_list,{}) table.reassign(player.equipment,to_names_set(cur_equip)) for i,v in pairs(slot_map) do @@ -64,7 +64,7 @@ function equip_sets(swap_type,ts,...) player.equipment[i] = player.equipment[toslotname(v)] end end - + logit('\n\n'..tostring(os.clock)..'(15) equip_sets: '..tostring(swap_type)) if val1 then if type(val1) == 'table' and val1.english then @@ -83,20 +83,20 @@ function equip_sets(swap_type,ts,...) else logit(' : nil-or-false') end - + if type(swap_type) == 'string' then msg.debugging("Entering "..swap_type) else msg.debugging("Entering User Event "..tostring(swap_type)) end - + if not val1 then val1 = {} if debugging.general then msg.debugging(8,'val1 error') end end - + if type(swap_type) == 'function' then results = { pcall(swap_type,...) } if not table.remove(results,1) then error('\nUser Event Error: '..results[1]) end @@ -105,48 +105,15 @@ function equip_sets(swap_type,ts,...) else user_pcall(swap_type,...) end - ---[[ local c - if type(swap_type) == 'function' then - c = coroutine.create(swap_type) - elseif swap_type == 'equip_command' then - equip(val1) - elseif type(swap_type) == 'string' and user_env[swap_type] and type(user_env[swap_type]) == 'function' then - c = coroutine.create(user_env[swap_type]) - elseif type(swap_type) == 'string' and user_env[swap_type] then - msg.addon_msg(123,windower.to_shift_jis(tostring(str))..'() exists but is not a function') - end - - if c then - while coroutine.status(c) == 'suspended' do - local err, typ, val = coroutine.resume(c,unpack(var_inputs)) - if not err then - error('\nGearSwap has detected an error in the user function '..tostring(swap_type)..':\n'..typ) - elseif typ then - if typ == 'sleep' and type(val) == 'number' and val >= 0 then - -- coroutine slept - err, typ, val = coroutine.schedule(c,val) - else - -- Someone yielded or slept with a nonsensical argument. - err, typ, val = coroutine.resume(c) - end - else - -- coroutine finished - end - end - end]] - - + if type(swap_type) == 'string' and (swap_type == 'pretarget' or swap_type == 'filtered_action') then -- Target may just have been changed, so make the ind now. ts = command_registry:new_entry(val1) --- elseif type(swap_type) == 'string' and swap_type == 'precast' and not command_registry[ts] and debugging.command_registry then --- print_set(spell,'precast nil error') -- spell's scope changed to local end - + if player.race ~= 'Precomposed NPC' then -- Short circuits the routine and gets out before equip processing -- if there's no swapping to be done because the user is a monster. - + for v,i in pairs(default_slot_map) do if equip_list[i] and encumbrance_table[v] then not_sent_out_equip[i] = equip_list[i] @@ -154,19 +121,19 @@ function equip_sets(swap_type,ts,...) msg.debugging(i..' slot was not equipped because you are encumbered.') end end - + table.update(equip_list_history,equip_list) - + -- Attempts to identify the player-specified item in inventory -- Starts with (i=slot name, v=item name) -- Ends with (i=slot id and v={bag_id=bag_id, slot=inventory slot}). local equip_next,priorities = unpack_equip_list(equip_list,cur_equip) - + if (_settings.show_swaps and table.length(equip_next) > 0) or _settings.demo_mode then --and table.length(equip_next)>0 then local tempset = to_names_set(equip_next) print_set(tempset,tostring(swap_type)) end - + if (buffactive.charm or player.charmed) or (player.status == 2 or player.status == 3) then -- dead or engaged dead statuses local failure_reason if (buffactive.charm or player.charmed) then @@ -208,13 +175,13 @@ function equip_sets(swap_type,ts,...) windower.packets.inject_outgoing(command_registry[ts].proposed_packet:byte(1),command_registry[ts].proposed_packet) end end - + windower.debug(tostring(swap_type)..' exit') - + if type(swap_type) == 'function' then return unpack(results) end - + return equip_sets_exit(swap_type,ts,val1) end @@ -236,7 +203,7 @@ function equip_sets_exit(swap_type,ts,val1) end if type(swap_type) == 'string' then if swap_type == 'pretarget' then - + if command_registry[ts].cancel_spell then msg.debugging("Action canceled ("..storedcommand..' '..val1.target.raw..")") storedcommand = nil @@ -246,11 +213,11 @@ function equip_sets_exit(swap_type,ts,val1) msg.debugging('This case should not be hittable - 1') return true end - + if command_registry[ts].new_target then val1.target = command_registry[ts].new_target -- Switch target, if it is requested. end - + -- Compose a proposed packet for the given action (this should be possible after pretarget) command_registry[ts].spell = val1 if val1.target and val1.target.id and val1.target.index and val1.prefix and unify_prefix[val1.prefix] then @@ -275,7 +242,7 @@ function equip_sets_exit(swap_type,ts,val1) command_registry[ts].proposed_packet = assemble_action_packet(val1.target.id,val1.target.index,outgoing_action_category_table[unify_prefix[val1.prefix]],val1.id,command_registry[ts].target_arrow) if not command_registry[ts].proposed_packet then command_registry:delete_entry(ts) - + msg.debugging("Unable to create a packet for this command because the target is still invalid after pretarget ("..storedcommand..' '..val1.target.raw..")") storedcommand = nil return storedcommand..' '..val1.target.raw @@ -285,7 +252,7 @@ function equip_sets_exit(swap_type,ts,val1) msg.debugging(8,"Hark, what weird prefix through yonder window breaks? "..tostring(val1.prefix)) end end - + if ts and command_registry[ts] and val1.target then if st_targs[val1.target.raw] then -- st targets @@ -439,4 +406,4 @@ end function send_action(ts) command_registry[ts].midaction = true equip_sets('midcast',ts,command_registry[ts].spell) -end \ No newline at end of file +end From 9e1f29fb60171b33498df269358fd0a42ff94b91 Mon Sep 17 00:00:00 2001 From: Byrth Date: Sat, 7 Jan 2023 13:40:54 -0500 Subject: [PATCH 0911/1002] un-disable buff_refresh events --- addons/GearSwap/packet_parsing.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/GearSwap/packet_parsing.lua b/addons/GearSwap/packet_parsing.lua index 3b9541d889..7991a67195 100644 --- a/addons/GearSwap/packet_parsing.lua +++ b/addons/GearSwap/packet_parsing.lua @@ -518,7 +518,7 @@ parse.i[0x063] = function (data) end local buff_name = res.buffs[new.id][language] windower.debug('refresh buff '..buff_name..' ('..tostring(new.id)..')') - if false and not gearswap_disabled then + if not gearswap_disabled then refresh_globals() equip_sets('buff_refresh',nil,buff_name,new) end From 0cbfcd38d50dd36f2ff1cad15cbdd798ac964133 Mon Sep 17 00:00:00 2001 From: Byrth Date: Sat, 7 Jan 2023 13:54:33 -0500 Subject: [PATCH 0912/1002] add comment --- addons/GearSwap/packet_parsing.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/GearSwap/packet_parsing.lua b/addons/GearSwap/packet_parsing.lua index 7991a67195..3f042a07b1 100644 --- a/addons/GearSwap/packet_parsing.lua +++ b/addons/GearSwap/packet_parsing.lua @@ -531,6 +531,8 @@ parse.i[0x063] = function (data) windower.debug('gain buff '..buff_name..' ('..tostring(new.id)..')') -- Need to figure out what I'm going to do with this: if T{'terror','sleep','stun','petrification','charm','weakness','lullaby'}:contains(buff_name:lower()) then + --Weakness is technically incorrect, because monsters can afflict players with weakness without killing them. + --However, it is being used to detect when players die so for the moment it must stay. for ts,v in pairs(command_registry) do if v.midaction then command_registry:delete_entry(ts) From f9ab03329e53c8f65c3e8f6bbd43244fe93f79d1 Mon Sep 17 00:00:00 2001 From: Byrth Date: Thu, 12 Jan 2023 07:18:07 -0500 Subject: [PATCH 0913/1002] Make send no longer error when logged out --- addons/send/send.lua | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/addons/send/send.lua b/addons/send/send.lua index 8df543b72c..7289c78f71 100644 --- a/addons/send/send.lua +++ b/addons/send/send.lua @@ -15,7 +15,7 @@ windower.register_event('addon command',function (...) local qual = table.remove(broken_init,1) local player = windower.ffxi.get_player() - if qual:lower()==player['name']:lower() then + if player and qual:lower()==player['name']:lower() then if broken_init ~= nil then relevant_msg(table.concat(broken_init,' ')) end @@ -41,12 +41,12 @@ windower.register_event('ipc message',function (msg) local qual = table.remove(broken,1) local player = windower.ffxi.get_player() - if qual:lower()==player.name:lower() then + if player and qual:lower()==player.name:lower() then relevant_msg(table.concat(broken,' ')) end if string.char(qual:byte(1)) == '@' then local arg = string.char(qual:byte(2, qual:len())) - if arg:upper() == player.main_job:upper() then + if player and arg:upper() == player.main_job:upper() then if broken ~= nil then relevant_msg(table.concat(broken,' ')) end @@ -85,8 +85,6 @@ function split(msg, match) end function relevant_msg(msg) - local player = windower.ffxi.get_player() - if msg:sub(1,2)=='//' then windower.send_command(msg:sub(3)) elseif msg:sub(1,1)=='/' then From 9facaf073c9316595593efc2576d754ad5c2f8a4 Mon Sep 17 00:00:00 2001 From: Posimagi Date: Wed, 18 Jan 2023 23:29:10 -0800 Subject: [PATCH 0914/1002] [craft] Upgraded create_recipes.py to python3 and made it robust enough to not break on recipe(s) with unknown ingredients (though the output is not useful--not that it could be crafted anyway). --- addons/craft/create_recipes.py | 34 ++++++++++++++++++++-------------- addons/craft/slpp.py | 20 ++++++++++++++------ 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/addons/craft/create_recipes.py b/addons/craft/create_recipes.py index 9a424ff667..cc02c28158 100644 --- a/addons/craft/create_recipes.py +++ b/addons/craft/create_recipes.py @@ -1,4 +1,4 @@ -import urllib2 +import urllib.request from bs4 import BeautifulSoup from slpp import slpp as lua import os @@ -36,22 +36,27 @@ def get_recipe(row): 'Glimmer Crystal', 'Shadow Crystal', ] - y, r, c, i = [ + result, _, recipe = [ td for td in row.findAll('td') ] - name = str(y.findAll('a')[0]['title']) + name = str(result.findAll('a')[0]['title']) crystal = None ingredients = [] - for li in i.findAll('li'): + for li in recipe.findAll('li'): english = str(li.findAll('a')[0]['title']) if english in crystals: crystal = english continue - if li.text[-1].isdigit() and not "Kit" in english: - for n in range(int(li.text[-1])): + try: + if li.text is None: + ingredients.append("unknown") # ingredient is "Question Mark", e.g. for Pagodite + elif li.text[-1].isdigit() and not "Kit" in english: + for n in range(int(li.text[-1])): + ingredients.append(english) + else: ingredients.append(english) - else: - ingredients.append(english) + except IndexError: + return None return [(name, crystal, ingredients)] def get_sphere_recipe(row): @@ -99,7 +104,7 @@ def get_recipes_from_rows(rows, spheres=False): def get_recipes_from_soup(soup, spheres=False): string = "Sphere Obtained" if spheres else "Synthesis Information" - lengths = [4, 5, 6, 7] if spheres else [4] + lengths = [4, 5, 6, 7] if spheres else [3] subtables = [ descendant.parent.parent.parent for descendant in soup.descendants @@ -188,6 +193,7 @@ def fix_recipes(recipes): sorted.append(inverted[ingredient]) else: sorted.append(get_item(ingredient, inverted)) + sorted = list(filter(lambda item: item is not None, sorted)) sorted.sort() ingredients = [ items[ingredient]['en'] @@ -205,7 +211,7 @@ def build_recipe_string(name, crystal, ingredients): def save_recipes(recipes): with open('recipes.lua', 'w') as fd: fd.write("return {\n") - for key in sorted(recipes.iterkeys()): + for key in sorted(recipes.keys()): fd.write(build_recipe_string(key, *recipes[key])) fd.write("}\n") @@ -213,12 +219,12 @@ def get_recipes(craft, spheres=False): base = "https://www.bg-wiki.com/bg/" name = "%s.html" % craft if not os.path.exists(name): - req = urllib2.Request(base + craft, headers=hdr) + req = urllib.request.Request(base + craft, headers=hdr) try: - page = urllib2.urlopen(req).read() - except urllib2.HTTPError, e: + page = urllib.request.urlopen(req).read() + except urllib.request.HTTPError: return - with open(name, 'w') as fd: + with open(name, 'wb') as fd: fd.write(page) with open(name, 'r') as fd: page = fd.read() diff --git a/addons/craft/slpp.py b/addons/craft/slpp.py index 3da97b8199..ea9c4279b9 100644 --- a/addons/craft/slpp.py +++ b/addons/craft/slpp.py @@ -48,6 +48,10 @@ def __init__(self): self.tab = '\t' def decode(self, text): + try: + basestring + except NameError: + basestring = str if not text or not isinstance(text, basestring): return #FIXME: only short comments removed @@ -71,18 +75,22 @@ def __encode(self, obj): tp = type(obj) if isinstance(obj, str): s += '"%s"' % obj.replace(r'"', r'\"') - if isinstance(obj, unicode): + if isinstance(obj, str): s += '"%s"' % obj.encode('utf-8').replace(r'"', r'\"') - elif tp in [int, float, long, complex]: + elif tp in [int, float, complex]: s += str(obj) elif tp is bool: s += str(obj).lower() elif obj is None: s += 'nil' elif tp in [list, tuple, dict]: + try: + basestring + except NameError: + basestring = str self.depth += 1 if len(obj) == 0 or ( tp is not dict and len(filter( - lambda x: type(x) in (int, float, long) \ + lambda x: type(x) in (int, float) \ or (isinstance(x, basestring) and len(x) < 10), obj )) == len(obj) ): newline = tab = '' @@ -148,7 +156,7 @@ def string(self, end=None): if self.ch != end: s += '\\' s += self.ch - print ERRORS['unexp_end_string'] + print(ERRORS['unexp_end_string']) def object(self): o = {} @@ -174,7 +182,7 @@ def object(self): self.next_chr() if k is not None: o[idx] = k - if not numeric_keys and len([ key for key in o if isinstance(key, (str, unicode, float, bool, tuple))]) == 0: + if not numeric_keys and len([ key for key in o if isinstance(key, (str, float, bool, tuple))]) == 0: ar = [] for key in o: ar.insert(key, o[key]) @@ -200,7 +208,7 @@ def object(self): o[idx] = k idx += 1 k = None - print ERRORS['unexp_end_table'] #Bad exit here + print(ERRORS['unexp_end_table']) #Bad exit here words = {'true': True, 'false': False, 'nil': None} def word(self): From 532339b65ce2c53d91c4cc1f448988231503c422 Mon Sep 17 00:00:00 2001 From: Posimagi Date: Sun, 18 Dec 2022 17:11:28 -0800 Subject: [PATCH 0915/1002] [craft] Move multi-recipes (those that use Bundling Twine, Spindle, etc.) to higher recipe numbers than the standard recipe that makes the basic quantity. Fix issues with several recipes that erroneously show multiple copies of the bundling guild item. --- addons/craft/recipes.lua | 82 +++++++++++++--------------------------- 1 file changed, 26 insertions(+), 56 deletions(-) diff --git a/addons/craft/recipes.lua b/addons/craft/recipes.lua index 04b3f19dd9..9499442071 100644 --- a/addons/craft/recipes.lua +++ b/addons/craft/recipes.lua @@ -1219,15 +1219,15 @@ return { ["crystal"] = "Wind Crystal", ["ingredients"] = { "Petrified Log", - "Petrified Log", - "Petrified Log", - "Bundling Twine", }, }, ["Ancient Lumber 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { "Petrified Log", + "Petrified Log", + "Petrified Log", + "Bundling Twine", }, }, ["Anelace"] = { @@ -3330,15 +3330,15 @@ return { ["crystal"] = "Wind Crystal", ["ingredients"] = { "Beech Log", - "Beech Log", - "Beech Log", - "Bundling Twine", }, }, ["Beech Lumber 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { "Beech Log", + "Beech Log", + "Beech Log", + "Bundling Twine", }, }, ["Beef Paella"] = { @@ -7527,11 +7527,6 @@ return { ["Chapuli Fltchg. 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", "Zephyr Thread", "Chapuli Wing", "Chapuli Wing", @@ -8436,11 +8431,6 @@ return { ["Colibri Fletchings 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", "Zephyr Thread", "Colibri Feather", "Colibri Feather", @@ -11134,15 +11124,15 @@ return { ["crystal"] = "Wind Crystal", ["ingredients"] = { "Divine Log", - "Divine Log", - "Divine Log", - "Bundling Twine", }, }, ["Divine Lumber 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { "Divine Log", + "Divine Log", + "Divine Log", + "Bundling Twine", }, }, ["Divine Sap"] = { @@ -14317,11 +14307,6 @@ return { "G. Bird Plume", "G. Bird Plume", "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", }, }, ["Gilded Chest"] = { @@ -15135,11 +15120,6 @@ return { ["ingredients"] = { "Moko Grass", "Moko Grass", - "Moko Grass", - "Moko Grass", - "Moko Grass", - "Moko Grass", - "Spindle", }, }, ["Grass Thread 2"] = { @@ -15147,6 +15127,11 @@ return { ["ingredients"] = { "Moko Grass", "Moko Grass", + "Moko Grass", + "Moko Grass", + "Moko Grass", + "Moko Grass", + "Spindle", }, }, ["Grasshopper Broth"] = { @@ -19268,15 +19253,15 @@ return { ["crystal"] = "Wind Crystal", ["ingredients"] = { "Lacquer Tree Log", - "Lacquer Tree Log", - "Lacquer Tree Log", - "Bundling Twine", }, }, ["Lacquer Tree Lumber 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { "Lacquer Tree Log", + "Lacquer Tree Log", + "Lacquer Tree Log", + "Bundling Twine", }, }, ["Lacquer Tree Sap"] = { @@ -19382,15 +19367,15 @@ return { ["crystal"] = "Wind Crystal", ["ingredients"] = { "Lancewood Log", - "Lancewood Log", - "Lancewood Log", - "Bundling Twine", }, }, ["Lancewood Lumber 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { "Lancewood Log", + "Lancewood Log", + "Lancewood Log", + "Bundling Twine", }, }, ["Lanner Bow"] = { @@ -24442,11 +24427,6 @@ return { ["Peapuk Fletchings 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", "Zephyr Thread", "Peapuk Wing", "Peapuk Wing", @@ -25853,11 +25833,6 @@ return { ["Puk Fletchings 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", "Zephyr Thread", "Puk Wing", "Puk Wing", @@ -32704,15 +32679,15 @@ return { ["Teak Lumber"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Bundling Twine", - "Teak Log", - "Teak Log", "Teak Log", }, }, ["Teak Lumber 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { + "Bundling Twine", + "Teak Log", + "Teak Log", "Teak Log", }, }, @@ -33734,11 +33709,6 @@ return { ["Tulfaire Fletchings 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", - "Zephyr Thread", "Zephyr Thread", "Tulfaire Feather", "Tulfaire Feather", @@ -34186,15 +34156,15 @@ return { ["Urunday Lumber"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Bundling Twine", - "Urunday Log", - "Urunday Log", "Urunday Log", }, }, ["Urunday Lumber 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { + "Bundling Twine", + "Urunday Log", + "Urunday Log", "Urunday Log", }, }, From 7fd02cf041f0651d1a18a6c24722c93b6ff9f93e Mon Sep 17 00:00:00 2001 From: Posimagi Date: Wed, 18 Jan 2023 23:46:14 -0800 Subject: [PATCH 0916/1002] [craft] generate new recipes.lua --- addons/craft/recipes.lua | 357 +++++++++++++++++++++++++++++++-------- 1 file changed, 288 insertions(+), 69 deletions(-) diff --git a/addons/craft/recipes.lua b/addons/craft/recipes.lua index 9499442071..10ee9fb487 100644 --- a/addons/craft/recipes.lua +++ b/addons/craft/recipes.lua @@ -674,7 +674,6 @@ return { ["crystal"] = "Earth Crystal", ["ingredients"] = { "Platinum Ingot", - "Wool Thread", "Gold Thread", "Gold Thread", "Silk Cloth", @@ -1818,7 +1817,6 @@ return { "Silver Chain", "Velvet Cloth", "Velvet Cloth", - "Velvet Cloth", "Sheep Leather", "Sheep Leather", "Eltoro Leather", @@ -4740,7 +4738,7 @@ return { "Hallowed Water", }, }, - ["Blessed Briault"] = { + ["Blessed Bliaut"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { "Silver Thread", @@ -4953,6 +4951,7 @@ return { "Gold Thread", "Gold Thread", "Silk Cloth", + "Rainbow Cloth", "Saruta Cotton", "Saruta Cotton", "Dragon Blood", @@ -5674,6 +5673,14 @@ return { "Teak Lumber", }, }, + ["Bongo Drum"] = { + ["crystal"] = "Earth Crystal", + ["ingredients"] = { + "Bamboo Stick", + "Dhalmel Hide", + "Buffalo Leather", + }, + }, ["Book Holder"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -6671,6 +6678,7 @@ return { ["Bug Broth"] = { ["crystal"] = "Water Crystal", ["ingredients"] = { + "Lugworm", "Lugworm", "Shell Bug", "Shell Bug", @@ -7129,6 +7137,7 @@ return { ["ingredients"] = { "Gelatin", "Hare Meat", + "Hare Meat", "Rotten Meat", }, }, @@ -7723,6 +7732,14 @@ return { "Rosewood Lbr.", }, }, + ["Chikuwa"] = { + ["crystal"] = "Earth Crystal", + ["ingredients"] = { + "Rock Salt", + "Bastore Bream", + "Tiger Cod", + }, + }, ["Chimera Blood"] = { ["crystal"] = "Lightng. Crystal", ["ingredients"] = { @@ -7889,6 +7906,9 @@ return { ["ingredients"] = { "Maple Sugar", "Kukuru Bean", + "Kukuru Bean", + "Kukuru Bean", + "Kukuru Bean", "Honey", "Selbina Milk", "Distilled Water", @@ -8473,18 +8493,6 @@ return { "Gigant Axe", }, }, - ["Comaa Belt"] = { - ["crystal"] = "Earth Crystal", - ["ingredients"] = { - "Thought Crystal", - "Hope Crystal", - "Fulfillment Crystal", - "Khoma Thread", - "Khoma Thread", - "Khoma Thread", - "Khoma Thread", - }, - }, ["Combat Caster's Axe +1"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -8640,7 +8648,7 @@ return { ["Compression Sphere 5"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Dark Card", + "Dark Crest Card", }, }, ["Console"] = { @@ -9989,13 +9997,13 @@ return { "Dk. Ixion Ferrule", }, }, - ["Dagger"] = { + ["Dagger (Weapon)"] = { ["crystal"] = "Light Crystal", ["ingredients"] = { "Rusty Dagger", }, }, - ["Dagger 2"] = { + ["Dagger (Weapon) 2"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { "Bronze Ingot", @@ -10950,7 +10958,7 @@ return { ["Detonation Sphere 5"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Wind Card", + "Wind Crest Card", }, }, ["Devotee's Mitts"] = { @@ -12096,6 +12104,15 @@ return { "Yilanbaligi", }, }, + ["Egg Sandwich"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "Selbina Butter", + "White Bread", + "Hard-boiled Egg", + "Graubg. Lettuce", + }, + }, ["Egg Soup"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -12397,6 +12414,57 @@ return { "Enhancing Mantle", }, }, + ["Enchanted Ink"] = { + ["crystal"] = "Dark Crystal", + ["ingredients"] = { + "Black Ink", + "Magicked Blood", + }, + }, + ["Enfeeblement Kit of Blindness"] = { + ["crystal"] = "Earth Crystal", + ["ingredients"] = { + "Fine Parchment", + "Fine Parchment", + "Enchanted Ink", + "Enchanted Ink", + "Padded Box", + "Blinding Potion", + }, + }, + ["Enfeeblement Kit of Poison"] = { + ["crystal"] = "Earth Crystal", + ["ingredients"] = { + "Fine Parchment", + "Fine Parchment", + "Enchanted Ink", + "Enchanted Ink", + "Padded Box", + "Poison Potion", + }, + }, + ["Enfeeblement Kit of Silence"] = { + ["crystal"] = "Earth Crystal", + ["ingredients"] = { + "Fine Parchment", + "Fine Parchment", + "Enchanted Ink", + "Enchanted Ink", + "Padded Box", + "Silencing Potion", + }, + }, + ["Enfeeblement Kit of Sleep"] = { + ["crystal"] = "Earth Crystal", + ["ingredients"] = { + "Fine Parchment", + "Fine Parchment", + "Enchanted Ink", + "Enchanted Ink", + "Padded Box", + "Sleeping Potion", + }, + }, ["Engetsuto"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -12814,6 +12882,8 @@ return { "Apple Vinegar", "Beastman Blood", "Hecteyes Eye", + "Hecteyes Eye", + "Hecteyes Eye", "Gelatin", "Frost Turnip", "Distilled Water", @@ -13410,6 +13480,7 @@ return { "Apple Vinegar", "Olive Oil", "Tiger Cod", + "Tiger Cod", "Bird Egg", "Moval. Water", }, @@ -14998,7 +15069,7 @@ return { ["Goldsmithing Set 90"] = { ["crystal"] = "Geo Crystal", ["ingredients"] = { - "Gold Ingot", + "Gold Sheet", "Emerald", "Ruby", "Diamond", @@ -15402,19 +15473,6 @@ return { "Distilled Water", }, }, - ["Griffon Leather 3"] = { - ["crystal"] = "Dark Crystal", - ["ingredients"] = { - "Win. Tea Leaves", - "Win. Tea Leaves", - "Win. Tea Leaves", - "Griffon Hide", - "Griffon Hide", - "Griffon Hide", - "Tanning Vat", - "Distilled Water", - }, - }, ["Grilled Hare"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -15500,6 +15558,19 @@ return { "Gysahl Greens", }, }, + ["Gyudon"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "Ginger", + "Tarutaru Rice", + "Soy Stock", + "Wild Onion", + "Buffalo Meat", + "Cotton Tofu", + "Shungiku", + "Shirataki", + }, + }, ["Hachimaki"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { @@ -15746,13 +15817,13 @@ return { ["Hard Leather Ring"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Tiger Leather", + "Leath. Kit 60", }, }, ["Hard Leather Ring 2"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Leath. Kit 60", + "Tiger Leather", }, }, ["Hard-boiled Egg"] = { @@ -16185,6 +16256,7 @@ return { ["Herb Paste"] = { ["crystal"] = "Water Crystal", ["ingredients"] = { + "Toko. Wildgrass", "Toko. Wildgrass", "La Theine Millet", "Lizard Egg", @@ -17544,7 +17616,7 @@ return { ["Impaction Sphere 5"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Lightning Card", + "Lightning Crest Card", }, }, ["Imperial Cermet"] = { @@ -17650,7 +17722,7 @@ return { ["Induration Sphere 4"] = { ["crystal"] = "Lightng. Crystal", ["ingredients"] = { - "Ice Card", + "Ice Crest Card", }, }, ["Induration Sphere 5"] = { @@ -18344,7 +18416,7 @@ return { }, }, ["Jolt Counter"] = { - ["crystal"] = "Earth Crystal", + ["crystal"] = "Fire Crystal", ["ingredients"] = { "Moonbow Steel", "Moonbow Stone", @@ -18794,6 +18866,18 @@ return { "Khimaira Mane", }, }, + ["Khoma Belt"] = { + ["crystal"] = "Earth Crystal", + ["ingredients"] = { + "Thought Crystal", + "Hope Crystal", + "Fulfillment Crystal", + "Khoma Thread", + "Khoma Thread", + "Khoma Thread", + "Khoma Thread", + }, + }, ["Khoma Cloth"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -19081,6 +19165,14 @@ return { "Bird Egg", }, }, + ["Konjak"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "Seashell", + "Distilled Water", + "Konjak Tuber", + }, + }, ["Konron Hassen"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -19501,7 +19593,7 @@ return { }, }, ["Leather Pot"] = { - ["crystal"] = "Earth Crystal", + ["crystal"] = "Fire Crystal", ["ingredients"] = { "Hickory Lumber", "Karakul Leather", @@ -20013,7 +20105,7 @@ return { ["Liquefaction Sphere 5"] = { ["crystal"] = "Lightng. Crystal", ["ingredients"] = { - "Fire Card", + "Fire Crest Card", }, }, ["Lithic Wyvern Scale"] = { @@ -20287,6 +20379,12 @@ return { "Bkn. Lu Rod", }, }, + ["Lu Shang's Fishing Rod +1"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "B. Lu. Rod +1", + }, + }, ["Lucent Axe"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -20422,6 +20520,15 @@ return { "Lynx Hide", }, }, + ["M. Counteragent"] = { + ["crystal"] = "Water Crystal", + ["ingredients"] = { + "Seashell", + "Salinator", + "Distilled Water", + "Distilled Water", + }, + }, ["Mace"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -21036,14 +21143,6 @@ return { }, }, ["Marbled Drawers"] = { - ["crystal"] = "Earth Crystal", - ["ingredients"] = { - "Bamboo Stick", - "Dhalmel Hide", - "Buffalo Leather", - }, - }, - ["Marbled Drawers 2"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { "Walnut Lumber", @@ -21799,6 +21898,13 @@ return { "Glass Fiber", }, }, + ["Miracle Mulch"] = { + ["crystal"] = "Dark Crystal", + ["ingredients"] = { + "Chocobo Bedding", + "Dung", + }, + }, ["Mirage Stole"] = { ["crystal"] = "Light Crystal", ["ingredients"] = { @@ -22017,6 +22123,14 @@ return { "Raptor Skin", }, }, + ["Mohbwa Cloth"] = { + ["crystal"] = "Earth Crystal", + ["ingredients"] = { + "Mohbwa Thread", + "Mohbwa Thread", + "Mohbwa Thread", + }, + }, ["Mohbwa Sash"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -22232,7 +22346,7 @@ return { "Moonbow Steel", "Moonbow Cloth", "Moonbow Leather", - "Comaa Belt", + "Khoma Belt", }, }, ["Moonbow Whistle"] = { @@ -23523,6 +23637,15 @@ return { "Contortacle", }, }, + ["Oden"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "Fish Stock", + "Konjak", + "Daikon", + "Chikuwa", + }, + }, ["Odorous Knife"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -23607,6 +23730,16 @@ return { "Wamoura Silk", }, }, + ["Omelette Sandwich"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "Selbina Butter", + "White Bread", + "Apkallu Egg", + "Puk Egg", + "Graubg. Lettuce", + }, + }, ["Onyx"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { @@ -23756,6 +23889,7 @@ return { "Selbina Butter", "Maple Sugar", "Saruta Orange", + "Saruta Orange", "Bird Egg", }, }, @@ -24389,6 +24523,8 @@ return { ["Pea Soup"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { + "Blue Peas", + "Blue Peas", "Blue Peas", "Dried Marjoram", "Wild Onion", @@ -24462,6 +24598,7 @@ return { ["Pear au Lait"] = { ["crystal"] = "Water Crystal", ["ingredients"] = { + "Derfland Pear", "Derfland Pear", "Honey", "Selbina Milk", @@ -24991,6 +25128,7 @@ return { "Rock Salt", "Sea Foliage", "Kitron", + "Rarab Tail", }, }, ["Pie Dough"] = { @@ -25585,6 +25723,19 @@ return { "Orichalcum Lance", }, }, + ["Popo. con Queso"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "San d'Or. Flour", + "Selbina Butter", + "Popoto", + "Rock Salt", + "Danceshroom", + "Selbina Milk", + "Wild Onion", + "Chalaimbille", + }, + }, ["Popstar"] = { ["crystal"] = "Light Crystal", ["ingredients"] = { @@ -25896,6 +26047,44 @@ return { "Distilled Water", }, }, + ["Pungent Powder"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Ahriman Lens", + "Silk Cloth", + "Saruta Cotton", + "Glass Fiber", + "Glass Fiber", + "Gelatin", + "Cornstarch", + "Pagodite", + }, + }, + ["Pungent Powder II"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Ahriman Lens", + "Silk Cloth", + "Saruta Cotton", + "Glass Fiber", + "Glass Fiber", + "Revival Root", + "Cornstarch", + "Pagodite", + }, + }, + ["Pungent Powder III"] = { + ["crystal"] = "Light Crystal", + ["ingredients"] = { + "Ahriman Lens", + "Silk Cloth", + "Saruta Cotton", + "Glass Fiber", + "Glass Fiber", + "Cornstarch", + "Pagodite", + }, + }, ["Pup. Collar"] = { ["crystal"] = "Light Crystal", ["ingredients"] = { @@ -26014,6 +26203,19 @@ return { "Walnut Lumber", }, }, + ["R. Pickled R. Tail"] = { + ["crystal"] = "Dark Crystal", + ["ingredients"] = { + "Apple Vinegar", + "Black Pepper", + "Maple Sugar", + "Rock Salt", + "Ro'Maeve Water", + "Rolanberry", + "Rarab Tail", + "Rarab Tail", + }, + }, ["Ra'Kaznar Arrowheads"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { @@ -27102,7 +27304,7 @@ return { ["Reverberation Sphere 4"] = { ["crystal"] = "Lightng. Crystal", ["ingredients"] = { - "Water Card", + "Water Crest Card", }, }, ["Reverberation Sphere 5"] = { @@ -27300,6 +27502,7 @@ return { ["ingredients"] = { "Rock Salt", "Danceshroom", + "Danceshroom", }, }, ["Roast Mushroom 2"] = { @@ -27307,6 +27510,7 @@ return { ["ingredients"] = { "Rock Salt", "Woozyshroom", + "Woozyshroom", }, }, ["Roast Mushroom 3"] = { @@ -27314,6 +27518,7 @@ return { ["ingredients"] = { "Rock Salt", "Sleepshroom", + "Sleepshroom", }, }, ["Roast Mutton"] = { @@ -28682,7 +28887,7 @@ return { ["Scission Sphere 5"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Earth Card", + "Earth Crest Card", }, }, ["Scope"] = { @@ -28920,6 +29125,19 @@ return { "Coral Fragment", }, }, + ["Seafood Gratin"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "San d'Or. Flour", + "Selbina Butter", + "Rock Salt", + "Danceshroom", + "Selbina Milk", + "Gigant Squid", + "Bastore Sweeper", + "Chalaimbille", + }, + }, ["Seafood Paella"] = { ["crystal"] = "Fire Crystal", ["ingredients"] = { @@ -29396,6 +29614,7 @@ return { "Rock Salt", "Kazham Pineapl.", "Shall Shell", + "Shall Shell", "Distilled Water", }, }, @@ -30722,7 +30941,7 @@ return { "Cockatrice Skin", }, }, - ["Smithing Set 71"] = { + ["Smithing Set 70"] = { ["crystal"] = "Pyre Crystal", ["ingredients"] = { "Darksteel Ingot", @@ -33536,7 +33755,7 @@ return { ["Transfixion Sphere 5"] = { ["crystal"] = "Wind Crystal", ["ingredients"] = { - "Light Card", + "Light Crest Card", }, }, ["Translucent Rock"] = { @@ -34911,22 +35130,6 @@ return { "Hexed Kecks", }, }, - ["Vexed Kote"] = { - ["crystal"] = "Fire Crystal", - ["ingredients"] = { - "Eschite Ore", - "Hexed Tekko -1", - }, - }, - ["Vexed Kote 2"] = { - ["crystal"] = "Fire Crystal", - ["ingredients"] = { - "Cehuetzi Pelt", - "Muut's Vestment", - "Eschite Ore", - "Hexed Tekko", - }, - }, ["Vexed Mitra"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { @@ -35007,6 +35210,22 @@ return { "Hexed Sune-Ate", }, }, + ["Vexed Tekko"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "Eschite Ore", + "Hexed Tekko -1", + }, + }, + ["Vexed Tekko 2"] = { + ["crystal"] = "Fire Crystal", + ["ingredients"] = { + "Cehuetzi Pelt", + "Muut's Vestment", + "Eschite Ore", + "Hexed Tekko", + }, + }, ["Vexed Tights"] = { ["crystal"] = "Earth Crystal", ["ingredients"] = { From 40101f257f4b4339b9d2196746bc72c43c650399 Mon Sep 17 00:00:00 2001 From: Posimagi Date: Sun, 18 Dec 2022 17:02:35 -0800 Subject: [PATCH 0917/1002] [craft] report quantity of items crafted --- addons/craft/craft.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/addons/craft/craft.lua b/addons/craft/craft.lua index f8b89b74d5..020893d35e 100644 --- a/addons/craft/craft.lua +++ b/addons/craft/craft.lua @@ -792,7 +792,12 @@ windower.register_event('incoming chunk', function(id, original, modified, injec local p = packets.parse('incoming',original) if p['Result'] == 0 or p['Result'] == 2 then local item = res.items[p['Item']].english - windower.add_to_chat(121, 'You synthesized: \30\02%s\30\01.':format(item)) + local count = p['Count'] + if count > 1 then + windower.add_to_chat(121, 'You synthesized: \30\02%s\30\01 x%d.':format(item, count)) + else + windower.add_to_chat(121, 'You synthesized: \30\02%s\30\01.':format(item)) + end injected_synth = false end if p['Result'] == 1 or p['Result'] == 5 then From 78ab4ad037841651e3be2ddb99c6a5fd1ecac7a3 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Tue, 24 Jan 2023 15:40:32 +0100 Subject: [PATCH 0918/1002] [Slips lib] Update for new items Adding the new items Cornelia's belt, Kni cap and Knit cap +1 --- addons/libs/slips.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 55ee0f3578..7aacfc96bc 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -15,7 +15,7 @@ slips.storages = L{29312, 29313, 29314, 29315, 29316, 29317, 29318, 2931 slips.items = { [slips.storages[1]] = L{16084, 14546, 14961, 15625, 15711, 16085, 14547, 14962, 15626, 15712, 16086, 14548, 14963, 15627, 15713, 16087, 14549, 14964, 15628, 15714, 16088, 14550, 14965, 15629, 15715, 16089, 14551, 14966, 15630, 15716, 16090, 14552, 14967, 15631, 15717, 16091, 14553, 14968, 15632, 15718, 16092, 14554, 14969, 15633, 15719, 16093, 14555, 14970, 15634, 15720, 16094, 14556, 14971, 15635, 15721, 16095, 14557, 14972, 15636, 15722, 16096, 14558, 14973, 15637, 15723, 16097, 14559, 14974, 15638, 15724, 16098, 14560, 14975, 15639, 15725, 16099, 14561, 14976, 15640, 15726, 16100, 14562, 14977, 15641, 15727, 16101, 14563, 14978, 15642, 15728, 16102, 14564, 14979, 15643, 15729, 16103, 14565, 14980, 15644, 15730, 16106, 14568, 14983, 15647, 15733, 16107, 14569, 14984, 15648, 15734, 16108, 14570, 14985, 15649, 15735, 16602, 17741, 18425, 18491, 18588, 18717, 18718, 18850, 18943, 16069, 14530, 14940, 15609, 15695, 16062, 14525, 14933, 15604, 15688, 16064, 14527, 14935, 15606, 15690, 18685, 18065, 17851, 18686, 18025, 18435, 18113, 17951, 17715, 18485, 18408, 18365, 18583, 18417, 18388, 16267, 16268, 16269, 16228, 16229, 15911, 15799, 15800, 15990, 17745, 18121, 16117, 14577, 17857}, -- 168 [slips.storages[2]] = L{12421, 12549, 12677, 12805, 12933, 13911, 14370, 14061, 14283, 14163, 12429, 12557, 12685, 12813, 12941, 13924, 14371, 14816, 14296, 14175, 13934, 14387, 14821, 14303, 14184, 13935, 14388, 14822, 14304, 14185, 13876, 13787, 14006, 14247, 14123, 13877, 13788, 14007, 14248, 14124, 13908, 14367, 14058, 14280, 14160, 13909, 14368, 14059, 14281, 14161, 16113, 14573, 14995, 15655, 15740, 16115, 14575, 14997, 15657, 15742, 16114, 14574, 14996, 15656, 15741, 16116, 14576, 14998, 15658, 15743, 12818, 18198, 12946, 18043, 12690, 17659, 12296, 12434, 15471, 15472, 15473, 15508, 15509, 15510, 15511, 15512, 15513, 15514, 17710, 17595, 18397, 18360, 18222, 17948, 18100, 15475, 15476, 15477, 15488, 15961, 14815, 14812, 14813, 15244, 15240, 14488, 14905, 15576, 15661, 15241, 14489, 14906, 15577, 15662, 13927, 14378, 14076, 14308, 14180, 13928, 14379, 14077, 14309, 14181, 10438, 10276, 10320, 10326, 10367, 10439, 10277, 10321, 10327, 10368, 10440, 10278, 10322, 10328, 10369, 10441, 10279, 10323, 10329, 10370, 25734, 25735, 25736, 25737, 25738, 25739, 25740, 25741, 25742, 25743, 25744}, -- 155 - [slips.storages[3]] = L{16155, 11282, 15021, 16341, 11376, 16156, 11283, 15022, 16342, 11377, 16157, 11284, 15023, 16343, 11378, 16148, 14590, 15011, 16317, 15757, 16143, 14591, 15012, 16318, 15758, 16146, 14588, 15009, 16315, 15755, 16147, 14589, 15010, 16316, 15756, 15966, 15967, 19041, 17684, 17685, 11636, 15844, 15934, 16258, 18735, 18734, 16291, 16292, 19042, 15935, 16293, 16294, 15936, 18618, 11588, 11545, 16158, 16159, 16160, 16149, 14583, 15007, 16314, 15751, 16141, 14581, 15005, 16312, 15749, 16142, 14582, 15006, 16313, 15750, 10876, 10450, 10500, 11969, 10600, 10877, 10451, 10501, 11970, 10601, 10878, 10452, 10502, 11971, 10602, 19132, 18551, 11798, 11362, 11363, 11625, 15959, 16259, 22299, 26414, 21623, 26219, 21886, 23792, 23793, 23794, 23795, 23796, 22032, 22043, 21530, 22044, 26273, 25415, 25416, 25414, 22050, 22302}, -- 117 + [slips.storages[3]] = L{16155, 11282, 15021, 16341, 11376, 16156, 11283, 15022, 16342, 11377, 16157, 11284, 15023, 16343, 11378, 16148, 14590, 15011, 16317, 15757, 16143, 14591, 15012, 16318, 15758, 16146, 14588, 15009, 16315, 15755, 16147, 14589, 15010, 16316, 15756, 15966, 15967, 19041, 17684, 17685, 11636, 15844, 15934, 16258, 18735, 18734, 16291, 16292, 19042, 15935, 16293, 16294, 15936, 18618, 11588, 11545, 16158, 16159, 16160, 16149, 14583, 15007, 16314, 15751, 16141, 14581, 15005, 16312, 15749, 16142, 14582, 15006, 16313, 15750, 10876, 10450, 10500, 11969, 10600, 10877, 10451, 10501, 11970, 10601, 10878, 10452, 10502, 11971, 10602, 19132, 18551, 11798, 11362, 11363, 11625, 15959, 16259, 22299, 26414, 21623, 26219, 21886, 23792, 23793, 23794, 23795, 23796, 22032, 22043, 21530, 22044, 26273, 25415, 25416, 25414, 22050, 22302, 26365}, -- 118 [slips.storages[4]] = L{12511, 12638, 13961, 14214, 14089, 12512, 12639, 13962, 14215, 14090, 13855, 12640, 13963, 14216, 14091, 13856, 12641, 13964, 14217, 14092, 12513, 12642, 13965, 14218, 14093, 12514, 12643, 13966, 14219, 14094, 12515, 12644, 13967, 14220, 14095, 12516, 12645, 13968, 14221, 14096, 12517, 12646, 13969, 14222, 14097, 13857, 12647, 13970, 14223, 14098, 12518, 12648, 13971, 14099, 14224, 13868, 13781, 13972, 14225, 14100, 13869, 13782, 13973, 14226, 14101, 12519, 12649, 13974, 14227, 14102, 12520, 12650, 13975, 14228, 14103, 15265, 14521, 14928, 15600, 15684, 15266, 14522, 14929, 15601, 15685, 15267, 14523, 14930, 15602, 15686, 16138, 14578, 15002, 15659, 15746, 16139, 14579, 15003, 15660, 15747, 16140, 14580, 15004, 16311, 15748, 16678, 17478, 17422, 17423, 16829, 16764, 17643, 16798, 16680, 16766, 17188, 17812, 17771, 17772, 16887, 17532, 17717, 18702, 17858, 19203, 21461, 21124, 20776, 27786, 27926, 28066, 28206, 28346, 27787, 27927, 28067, 28207, 28347}, -- 138 [slips.storages[5]] = L{15225, 14473, 14890, 15561, 15352, 15226, 14474, 14891, 15562, 15353, 15227, 14475, 14892, 15563, 15354, 15228, 14476, 14893, 15564, 15355, 15229, 14477, 14894, 15565, 15356, 15230, 14478, 14895, 15566, 15357, 15231, 14479, 14896, 15567, 15358, 15232, 14480, 14897, 15568, 15359, 15233, 14481, 14898, 15569, 15360, 15234, 14482, 14899, 15570, 15361, 15235, 14483, 14900, 15362, 15571, 15236, 14484, 14901, 15572, 15363, 15237, 14485, 14902, 15573, 15364, 15238, 14486, 14903, 15574, 15365, 15239, 14487, 14904, 15575, 15366, 11464, 11291, 15024, 16345, 11381, 11467, 11294, 15027, 16348, 11384, 11470, 11297, 15030, 16351, 11387, 11475, 11302, 15035, 16357, 11393, 11476, 11303, 15036, 16358, 11394, 11477, 11304, 15037, 16359, 11395}, -- 105 [slips.storages[6]] = L{15072, 15087, 15102, 15117, 15132, 15871, 15073, 15088, 15103, 15118, 15133, 15478, 15074, 15089, 15104, 15119, 15134, 15872, 15075, 15090, 15105, 15120, 15135, 15874, 15076, 15091, 15106, 15121, 15136, 15873, 15077, 15092, 15107, 15122, 15137, 15480, 15078, 15093, 15108, 15123, 15138, 15481, 15079, 15094, 15109, 15124, 15139, 15479, 15080, 15095, 15110, 15125, 15140, 15875, 15081, 15096, 15111, 15126, 15141, 15482, 15082, 15097, 15112, 15127, 15142, 15876, 15083, 15098, 15113, 15128, 15143, 15879, 15084, 15099, 15114, 15129, 15144, 15877, 15085, 15100, 15115, 15130, 15145, 15878, 15086, 15101, 15116, 15131, 15146, 15484, 11465, 11292, 15025, 16346, 11382, 16244, 11468, 11295, 15028, 16349, 11385, 15920, 11471, 11298, 15031, 16352, 11388, 16245, 11478, 11305, 15038, 16360, 11396, 16248, 11480, 11307, 15040, 16362, 11398, 15925}, -- 120 @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757, 25909}, -- 192 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912, 3753, 23806, 3754}, -- 162 SE Skipped an index hence the 0 as one of the items + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912, 3753, 23806, 3754, 23810, 23811}, -- 164 SE Skipped an index hence the 0 as one of the items [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067, 21680, 22071}, -- 177 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, -- 115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, -- 115 From bf77ef7ff0c8f7bf50f068de52a6f9e390834e18 Mon Sep 17 00:00:00 2001 From: Imisnew Date: Sat, 4 Feb 2023 20:42:17 +0900 Subject: [PATCH 0919/1002] Update 0x03C to have starting index field. --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index ac65ce1666..4813bed35b 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -2243,7 +2243,7 @@ types.shop_item = L{ -- Shop fields.incoming[0x03C] = L{ - {ctype='unsigned short', label='_zero1', const=0x0000}, -- 04 + {ctype='unsigned short', label='Starting Index'}, -- 04 {ctype='unsigned short', label='_padding1'}, -- 06 {ref=types.shop_item, label='Item', count='*'}, -- 08 - * } From e3660a94bd8137de960383b1fbe8b342a4b7ffa4 Mon Sep 17 00:00:00 2001 From: Byrth Date: Fri, 10 Feb 2023 04:58:37 -0500 Subject: [PATCH 0920/1002] Update slips for the 2023-02 update --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 7aacfc96bc..81963981ae 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757, 25909}, -- 192 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912, 3753, 23806, 3754, 23810, 23811}, -- 164 SE Skipped an index hence the 0 as one of the items + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912, 3753, 23806, 3754, 23810, 23811, 3755}, -- 164 SE Skipped an index hence the 0 as one of the items [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067, 21680, 22071}, -- 177 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, -- 115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, -- 115 From 546c4dbeebdeffa16ae93a7c33039ffa89e6ee9f Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 19 Feb 2023 20:25:07 +0000 Subject: [PATCH 0921/1002] Fix Lightningday spelling --- addons/gametime/gametime.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/gametime/gametime.lua b/addons/gametime/gametime.lua index 6b9d4c2a03..7c439cb01d 100644 --- a/addons/gametime/gametime.lua +++ b/addons/gametime/gametime.lua @@ -320,7 +320,7 @@ function day_change(day) dlist = {'4','5','6','7','8','1','2','3'} elseif (day == 'Iceday') then dlist = {'5','6','7','8','1','2','3','4'} - elseif (day == 'Lightningsday') then + elseif (day == 'Lightningday') then dlist = {'6','7','8','1','2','3','4','5'} elseif (day == 'Lightsday') then dlist = {'7','8','1','2','3','4','5','6'} From 2b46b3268370c75a7946f467cb8f0709f8cb398e Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Tue, 7 Mar 2023 19:37:36 +0000 Subject: [PATCH 0922/1002] Update fields.lua The new field in 0x0119 contains the difference between the base recast of a job ability, and the actual recast as affected by merits/gear/job points. --- addons/libs/packets/fields.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 4813bed35b..65f8f7e8c5 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -4019,7 +4019,8 @@ types.ability_recast = L{ {ctype='unsigned short', label='Duration', fn=div+{1}}, -- 00 {ctype='unsigned char', label='_unknown1', const=0x00}, -- 02 {ctype='unsigned char', label='Recast', fn=arecast}, -- 03 - {ctype='unsigned int', label='_unknown2'} -- 04 + {ctype='signed short', label='Recast Modifier',} -- 04 + {ctype='unsigned short', label='_unknown2'} -- 06 } -- Ability timers From d97a154f5de7d77f0271b895bab8d31b50896d00 Mon Sep 17 00:00:00 2001 From: Byrth Date: Wed, 8 Mar 2023 07:06:15 -0500 Subject: [PATCH 0923/1002] an unfathomably wondrous contribution --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 65f8f7e8c5..2b6a53bb6b 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -4019,7 +4019,7 @@ types.ability_recast = L{ {ctype='unsigned short', label='Duration', fn=div+{1}}, -- 00 {ctype='unsigned char', label='_unknown1', const=0x00}, -- 02 {ctype='unsigned char', label='Recast', fn=arecast}, -- 03 - {ctype='signed short', label='Recast Modifier',} -- 04 + {ctype='signed short', label='Recast Modifier'}, -- 04 {ctype='unsigned short', label='_unknown2'} -- 06 } From b4de0110beedacc8d37e2da99c0e0bb3899953ab Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Tue, 14 Mar 2023 02:48:53 +0100 Subject: [PATCH 0924/1002] [Slips lib] Adding new item Adding Platinum Moogle Belt to the slips lib. --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 81963981ae..ca614cb818 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -15,7 +15,7 @@ slips.storages = L{29312, 29313, 29314, 29315, 29316, 29317, 29318, 2931 slips.items = { [slips.storages[1]] = L{16084, 14546, 14961, 15625, 15711, 16085, 14547, 14962, 15626, 15712, 16086, 14548, 14963, 15627, 15713, 16087, 14549, 14964, 15628, 15714, 16088, 14550, 14965, 15629, 15715, 16089, 14551, 14966, 15630, 15716, 16090, 14552, 14967, 15631, 15717, 16091, 14553, 14968, 15632, 15718, 16092, 14554, 14969, 15633, 15719, 16093, 14555, 14970, 15634, 15720, 16094, 14556, 14971, 15635, 15721, 16095, 14557, 14972, 15636, 15722, 16096, 14558, 14973, 15637, 15723, 16097, 14559, 14974, 15638, 15724, 16098, 14560, 14975, 15639, 15725, 16099, 14561, 14976, 15640, 15726, 16100, 14562, 14977, 15641, 15727, 16101, 14563, 14978, 15642, 15728, 16102, 14564, 14979, 15643, 15729, 16103, 14565, 14980, 15644, 15730, 16106, 14568, 14983, 15647, 15733, 16107, 14569, 14984, 15648, 15734, 16108, 14570, 14985, 15649, 15735, 16602, 17741, 18425, 18491, 18588, 18717, 18718, 18850, 18943, 16069, 14530, 14940, 15609, 15695, 16062, 14525, 14933, 15604, 15688, 16064, 14527, 14935, 15606, 15690, 18685, 18065, 17851, 18686, 18025, 18435, 18113, 17951, 17715, 18485, 18408, 18365, 18583, 18417, 18388, 16267, 16268, 16269, 16228, 16229, 15911, 15799, 15800, 15990, 17745, 18121, 16117, 14577, 17857}, -- 168 [slips.storages[2]] = L{12421, 12549, 12677, 12805, 12933, 13911, 14370, 14061, 14283, 14163, 12429, 12557, 12685, 12813, 12941, 13924, 14371, 14816, 14296, 14175, 13934, 14387, 14821, 14303, 14184, 13935, 14388, 14822, 14304, 14185, 13876, 13787, 14006, 14247, 14123, 13877, 13788, 14007, 14248, 14124, 13908, 14367, 14058, 14280, 14160, 13909, 14368, 14059, 14281, 14161, 16113, 14573, 14995, 15655, 15740, 16115, 14575, 14997, 15657, 15742, 16114, 14574, 14996, 15656, 15741, 16116, 14576, 14998, 15658, 15743, 12818, 18198, 12946, 18043, 12690, 17659, 12296, 12434, 15471, 15472, 15473, 15508, 15509, 15510, 15511, 15512, 15513, 15514, 17710, 17595, 18397, 18360, 18222, 17948, 18100, 15475, 15476, 15477, 15488, 15961, 14815, 14812, 14813, 15244, 15240, 14488, 14905, 15576, 15661, 15241, 14489, 14906, 15577, 15662, 13927, 14378, 14076, 14308, 14180, 13928, 14379, 14077, 14309, 14181, 10438, 10276, 10320, 10326, 10367, 10439, 10277, 10321, 10327, 10368, 10440, 10278, 10322, 10328, 10369, 10441, 10279, 10323, 10329, 10370, 25734, 25735, 25736, 25737, 25738, 25739, 25740, 25741, 25742, 25743, 25744}, -- 155 - [slips.storages[3]] = L{16155, 11282, 15021, 16341, 11376, 16156, 11283, 15022, 16342, 11377, 16157, 11284, 15023, 16343, 11378, 16148, 14590, 15011, 16317, 15757, 16143, 14591, 15012, 16318, 15758, 16146, 14588, 15009, 16315, 15755, 16147, 14589, 15010, 16316, 15756, 15966, 15967, 19041, 17684, 17685, 11636, 15844, 15934, 16258, 18735, 18734, 16291, 16292, 19042, 15935, 16293, 16294, 15936, 18618, 11588, 11545, 16158, 16159, 16160, 16149, 14583, 15007, 16314, 15751, 16141, 14581, 15005, 16312, 15749, 16142, 14582, 15006, 16313, 15750, 10876, 10450, 10500, 11969, 10600, 10877, 10451, 10501, 11970, 10601, 10878, 10452, 10502, 11971, 10602, 19132, 18551, 11798, 11362, 11363, 11625, 15959, 16259, 22299, 26414, 21623, 26219, 21886, 23792, 23793, 23794, 23795, 23796, 22032, 22043, 21530, 22044, 26273, 25415, 25416, 25414, 22050, 22302, 26365}, -- 118 + [slips.storages[3]] = L{16155, 11282, 15021, 16341, 11376, 16156, 11283, 15022, 16342, 11377, 16157, 11284, 15023, 16343, 11378, 16148, 14590, 15011, 16317, 15757, 16143, 14591, 15012, 16318, 15758, 16146, 14588, 15009, 16315, 15755, 16147, 14589, 15010, 16316, 15756, 15966, 15967, 19041, 17684, 17685, 11636, 15844, 15934, 16258, 18735, 18734, 16291, 16292, 19042, 15935, 16293, 16294, 15936, 18618, 11588, 11545, 16158, 16159, 16160, 16149, 14583, 15007, 16314, 15751, 16141, 14581, 15005, 16312, 15749, 16142, 14582, 15006, 16313, 15750, 10876, 10450, 10500, 11969, 10600, 10877, 10451, 10501, 11970, 10601, 10878, 10452, 10502, 11971, 10602, 19132, 18551, 11798, 11362, 11363, 11625, 15959, 16259, 22299, 26414, 21623, 26219, 21886, 23792, 23793, 23794, 23795, 23796, 22032, 22043, 21530, 22044, 26273, 25415, 25416, 25414, 22050, 22302, 26365, 26366}, -- 119 [slips.storages[4]] = L{12511, 12638, 13961, 14214, 14089, 12512, 12639, 13962, 14215, 14090, 13855, 12640, 13963, 14216, 14091, 13856, 12641, 13964, 14217, 14092, 12513, 12642, 13965, 14218, 14093, 12514, 12643, 13966, 14219, 14094, 12515, 12644, 13967, 14220, 14095, 12516, 12645, 13968, 14221, 14096, 12517, 12646, 13969, 14222, 14097, 13857, 12647, 13970, 14223, 14098, 12518, 12648, 13971, 14099, 14224, 13868, 13781, 13972, 14225, 14100, 13869, 13782, 13973, 14226, 14101, 12519, 12649, 13974, 14227, 14102, 12520, 12650, 13975, 14228, 14103, 15265, 14521, 14928, 15600, 15684, 15266, 14522, 14929, 15601, 15685, 15267, 14523, 14930, 15602, 15686, 16138, 14578, 15002, 15659, 15746, 16139, 14579, 15003, 15660, 15747, 16140, 14580, 15004, 16311, 15748, 16678, 17478, 17422, 17423, 16829, 16764, 17643, 16798, 16680, 16766, 17188, 17812, 17771, 17772, 16887, 17532, 17717, 18702, 17858, 19203, 21461, 21124, 20776, 27786, 27926, 28066, 28206, 28346, 27787, 27927, 28067, 28207, 28347}, -- 138 [slips.storages[5]] = L{15225, 14473, 14890, 15561, 15352, 15226, 14474, 14891, 15562, 15353, 15227, 14475, 14892, 15563, 15354, 15228, 14476, 14893, 15564, 15355, 15229, 14477, 14894, 15565, 15356, 15230, 14478, 14895, 15566, 15357, 15231, 14479, 14896, 15567, 15358, 15232, 14480, 14897, 15568, 15359, 15233, 14481, 14898, 15569, 15360, 15234, 14482, 14899, 15570, 15361, 15235, 14483, 14900, 15362, 15571, 15236, 14484, 14901, 15572, 15363, 15237, 14485, 14902, 15573, 15364, 15238, 14486, 14903, 15574, 15365, 15239, 14487, 14904, 15575, 15366, 11464, 11291, 15024, 16345, 11381, 11467, 11294, 15027, 16348, 11384, 11470, 11297, 15030, 16351, 11387, 11475, 11302, 15035, 16357, 11393, 11476, 11303, 15036, 16358, 11394, 11477, 11304, 15037, 16359, 11395}, -- 105 [slips.storages[6]] = L{15072, 15087, 15102, 15117, 15132, 15871, 15073, 15088, 15103, 15118, 15133, 15478, 15074, 15089, 15104, 15119, 15134, 15872, 15075, 15090, 15105, 15120, 15135, 15874, 15076, 15091, 15106, 15121, 15136, 15873, 15077, 15092, 15107, 15122, 15137, 15480, 15078, 15093, 15108, 15123, 15138, 15481, 15079, 15094, 15109, 15124, 15139, 15479, 15080, 15095, 15110, 15125, 15140, 15875, 15081, 15096, 15111, 15126, 15141, 15482, 15082, 15097, 15112, 15127, 15142, 15876, 15083, 15098, 15113, 15128, 15143, 15879, 15084, 15099, 15114, 15129, 15144, 15877, 15085, 15100, 15115, 15130, 15145, 15878, 15086, 15101, 15116, 15131, 15146, 15484, 11465, 11292, 15025, 16346, 11382, 16244, 11468, 11295, 15028, 16349, 11385, 15920, 11471, 11298, 15031, 16352, 11388, 16245, 11478, 11305, 15038, 16360, 11396, 16248, 11480, 11307, 15040, 16362, 11398, 15925}, -- 120 From 86c06635a2561b203a54f1a4300add43df81b221 Mon Sep 17 00:00:00 2001 From: Byrth Date: Mon, 10 Apr 2023 08:57:41 -0400 Subject: [PATCH 0925/1002] Update user_functions.lua --- addons/GearSwap/user_functions.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/GearSwap/user_functions.lua b/addons/GearSwap/user_functions.lua index 2062955ddc..1bb3110917 100644 --- a/addons/GearSwap/user_functions.lua +++ b/addons/GearSwap/user_functions.lua @@ -81,10 +81,10 @@ function move_spell_target(position_table) if type(position_table) == 'table' and type(position_table.x or position_table.X) == 'number' and type(position_table.y or position_table.Y) == 'number' and type(position_table.z or position_table.Z) == 'number' then + _global.target_arrow.x = position_table.x or position_table.X _global.target_arrow.y = position_table.y or position_table.Y _global.target_arrow.z = position_table.z or position_table.Z - print_set(_global.target_arrow) else error('\nGearSwap: move_spell_target() was passed an invalid value ('..tostring(position_table)..'). Should be a table with x, y, and z keys (offset from target)', 2) end From bcb27e9d5e481835973d542a3904db898f7c6b38 Mon Sep 17 00:00:00 2001 From: Trey Bennett <92297195+LordTreyBennett@users.noreply.github.com> Date: Tue, 11 Apr 2023 07:03:22 -0500 Subject: [PATCH 0926/1002] Update README.md corrected the English spelling and grammar from "if you won't" to the correct "if you do not want" so that the meaning of the sentence matches the command mentioned and corrected the spelling of want from won't, meaning will not instead of want's meaning of an expectation of action. --- addons/Tab/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/Tab/README.md b/addons/Tab/README.md index a98513269c..b05cf8eafe 100644 --- a/addons/Tab/README.md +++ b/addons/Tab/README.md @@ -2,7 +2,7 @@ ### English - Simple addon Replace Tab key input to `` or ``. (X+Tab) -- **Tips:** if you won't to include pet or trust in `` by other players, use `/ignorepet on` and `/ignoretrust on` (in-game commands) +- **Tips:** if you do not want to include pet or trust in `` by other players, use `/ignorepet on` and `/ignoretrust on` (in-game commands) ### 日本語 - Tabキーの動作を``または``(X+Tab)に置き換えます。 From c76922fcb175756b484f63139cbeaa83565ef56b Mon Sep 17 00:00:00 2001 From: Byrth Date: Sat, 15 Apr 2023 13:51:35 -0400 Subject: [PATCH 0927/1002] Remove XML option for //gs export --- addons/GearSwap/export.lua | 95 +++++++++----------------- addons/GearSwap/libs/closetCleaner.lua | 8 ++- 2 files changed, 37 insertions(+), 66 deletions(-) diff --git a/addons/GearSwap/export.lua b/addons/GearSwap/export.lua index 454bab4c77..deac064b82 100644 --- a/addons/GearSwap/export.lua +++ b/addons/GearSwap/export.lua @@ -26,7 +26,7 @@ function export_set(options) local item_list = T{} - local targinv,all_items,xml,all_sets,use_job_in_filename,use_subjob_in_filename,overwrite_existing,named_file + local targinv,all_items,all_sets,use_job_in_filename,use_subjob_in_filename,overwrite_existing,named_file if #options > 0 then for _,v in ipairs(options) do if S{'inventory','inv','i'}:contains(v:lower()) then @@ -35,8 +35,6 @@ function export_set(options) all_items = true elseif v:lower() == 'wearable' then wearable = true - elseif S{'xml'}:contains(v:lower()) then - xml = true elseif S{'sets','set','s'}:contains(v:lower()) then all_sets = true if not user_env or not user_env.sets then @@ -72,11 +70,7 @@ function export_set(options) buildmsg = buildmsg..'your currently equipped gear' end - if xml then - buildmsg = buildmsg..' as an xml file.' - else - buildmsg = buildmsg..' as a lua file.' - end + buildmsg = buildmsg..' as a lua file.' if use_job_in_filename then buildmsg = buildmsg..' (Naming format: Character_JOB)' @@ -130,15 +124,13 @@ function export_set(options) name = res.items[item_tab.id][language], slot = slot_name } - if not xml then - local augments = extdata.decode(item_tab).augments or {} - local aug_str = '' - for aug_ind,augment in pairs(augments) do - if augment ~= 'none' then aug_str = aug_str.."'"..augment:gsub("'","\\'").."'," end - end - if string.len(aug_str) > 0 then - item_list[slot_map[slot_name]+1].augments = aug_str - end + local augments = extdata.decode(item_tab).augments or {} + local aug_str = '' + for aug_ind,augment in pairs(augments) do + if augment ~= 'none' then aug_str = aug_str.."'"..augment:gsub("'","\\'").."'," end + end + if string.len(aug_str) > 0 then + item_list[slot_map[slot_name]+1].augments = aug_str end else msg.addon_msg(123,'You are wearing an item that is not in the resources yet.') @@ -180,42 +172,24 @@ function export_set(options) else path = path..os.date(' %Y-%m-%d %H-%M-%S') end - if xml then - -- Export in .xml - if (not overwrite_existing) and windower.file_exists(path..'.xml') then - path = path..' '..os.clock() - end - local f = io.open(path..'.xml','w+') - f:write('\n \n \n \n') - for i,v in ipairs(item_list) do - if v.name ~= empty then - local slot = xmlify(tostring(v.slot)) - local name = xmlify(tostring(v.name)) - f:write(' <'..slot..'>'..name..'\n') - end - end - f:write(' \n \n \n') - f:close() - else - -- Default to exporting in .lua - if (not overwrite_existing) and windower.file_exists(path..'.lua') then - path = path..' '..os.clock() - end - local f = io.open(path..'.lua','w+') - f:write('sets.exported={\n') - for i,v in ipairs(item_list) do - if v.name ~= empty then - if v.augments then - --Advanced set table - f:write(' '..v.slot..'={ name="'..v.name..'", augments={'..v.augments..'}},\n') - else - f:write(' '..v.slot..'="'..v.name..'",\n') - end + -- Default to exporting in .lua + if (not overwrite_existing) and windower.file_exists(path..'.lua') then + path = path..' '..os.clock() + end + local f = io.open(path..'.lua','w+') + f:write('sets.exported={\n') + for i,v in ipairs(item_list) do + if v.name ~= empty then + if v.augments then + --Advanced set table + f:write(' '..v.slot..'={ name="'..v.name..'", augments={'..v.augments..'}},\n') + else + f:write(' '..v.slot..'="'..v.name..'",\n') end end - f:write('}') - f:close() end + f:write('}') + f:close() end function unpack_names(ret_tab,up,tab_level,unpacked_table,exported) @@ -280,11 +254,6 @@ function unlogify_unpacked_name(name) return name,slot end -function xmlify(phrase) - if tonumber(phrase:sub(1,1)) then phrase = 'NUM'..phrase end - return phrase --:gsub('"','"'):gsub("'","'"):gsub('<','<'):gsub('>','>'):gsub('&&','&') -end - function get_item_list(bag) local items_in_bag = {} -- Load the entire inventory @@ -298,15 +267,13 @@ function get_item_list(bag) slot = res.slots[potslots:it()()].english:gsub(' ','_'):lower() -- Multi-lingual support requires that we add more languages to slots.lua end items_in_bag[#items_in_bag].slot = slot or 'item' - if not xml then - local augments = extdata.decode(v).augments or {} - local aug_str = '' - for aug_ind,augment in pairs(augments) do - if augment ~= 'none' then aug_str = aug_str.."'"..augment:gsub("'","\\'").."'," end - end - if string.len(aug_str) > 0 then - items_in_bag[#items_in_bag].augments = aug_str - end + local augments = extdata.decode(v).augments or {} + local aug_str = '' + for aug_ind,augment in pairs(augments) do + if augment ~= 'none' then aug_str = aug_str.."'"..augment:gsub("'","\\'").."'," end + end + if string.len(aug_str) > 0 then + items_in_bag[#items_in_bag].augments = aug_str end else msg.addon_msg(123,'You possess an item that is not in the resources yet.') diff --git a/addons/GearSwap/libs/closetCleaner.lua b/addons/GearSwap/libs/closetCleaner.lua index 50a35efc2d..d21f3fad16 100644 --- a/addons/GearSwap/libs/closetCleaner.lua +++ b/addons/GearSwap/libs/closetCleaner.lua @@ -146,6 +146,10 @@ function cc.run_report(path) print("File created: "..mainReportName) end +function cc.xmlify(phrase) + if tonumber(phrase:sub(1,1)) then phrase = 'NUM'..phrase end + return phrase --:gsub('"','"'):gsub("'","'"):gsub('<','<'):gsub('>','>'):gsub('&&','&') +end -- This function tallies all the gear in your inventory function cc.export_inv(path) if ccDebug then @@ -161,8 +165,8 @@ function cc.export_inv(path) if not settings.ccskipBags:contains(gearswap.res.bags[n].english) then for i,v in ipairs(gearswap.get_item_list(gearswap.items[gearswap.res.bags[n].english:gsub(' ', ''):lower()])) do if v.name ~= empty then - local slot = gearswap.xmlify(tostring(v.slot)) - local name = gearswap.xmlify(tostring(v.name)):gsub('NUM1','1') + local slot = cc.xmlify(tostring(v.slot)) + local name = cc.xmlify(tostring(v.name)):gsub('NUM1','1') if cc.sandbox.itemsByName[name:lower()] ~= nil then itemid = cc.sandbox.itemsByName[name:lower()] From 4c84b4ac8b11343f04e2aed19fe361c002140e3b Mon Sep 17 00:00:00 2001 From: funkworkz Date: Tue, 9 May 2023 09:10:33 -0500 Subject: [PATCH 0928/1002] Update setbgm.lua Anticipated new songs for May 2023 update. Placeholders are already in the DATs. --- addons/setbgm/setbgm.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/setbgm/setbgm.lua b/addons/setbgm/setbgm.lua index da8f4648d4..450b746b10 100644 --- a/addons/setbgm/setbgm.lua +++ b/addons/setbgm/setbgm.lua @@ -51,7 +51,7 @@ music_types = { songs = { [25]='Voracious Resurgence Unknown 1', [26]='Voracious Resurgence Unknown 2', [27]='Voracious Resurgence Unknown 3', [28]='The Destiny Destroyers', [29]="Devils' Delight", [30]="Odyssey - Bumba", [31]='Voracious Resurgence Unknown 4', [32]='Voracious Resurgence Unknown 5', - [33]='Voracious Resurgence Unknown 6', [34]="We Are Vana'diel", [35]='Goddessspeed', [36]='Sortie - +3 Area', + [33]='Voracious Resurgence Unknown 6', [34]="We Are Vana'diel", [35]='Goddessspeed', [36]='Sortie - +3 Area', [37]='Voracious Resurgence Unknown 7', [38]='Voracious Resurgence Unknown 8', [40]='Cloister of Time and Souls', [41]='Royal Wanderlust', [42]='Snowdrift Waltz', [43]='Troubled Shadows', [44]='Where Lords Rule Not', [45]='Summers Lost', [46]='Goddess Divine', [47]='Echoes of Creation', [48]='Main Theme', [49]='Luck of the Mog', [50]='Feast of the Ladies', [51]='Abyssea - Scarlet Skies, Shadowed Plains', [52]='Melodies Errant', [53]='Shinryu', [54]='Everlasting Bonds', [55]='Provenance Watcher', [56]='Where it All Begins', [57]='Steel Sings, Blades Dance', [58]='A New Direction', [59]='The Pioneers', [60]='Into Lands Primeval - Ulbuka', [61]="Water's Umbral Knell", [62]='Keepers of the Wild', [63]='The Sacred City of Adoulin', [64]='Breaking Ground', [65]='Hades', [66]='Arciela', [67]='Mog Resort', [68]='Worlds Away', [69]="Distant Worlds (Nanaa Mihgo's version)", From be48b039dbc42ce0f36981d35a2b0db165cdb9ea Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Fri, 12 May 2023 01:35:47 +0200 Subject: [PATCH 0929/1002] [Slips lib] Adding new items Added Ageist and Regis to storage slip 22 --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index ca614cb818..f8307fdffc 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757, 25909}, -- 192 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912, 3753, 23806, 3754, 23810, 23811, 3755}, -- 164 SE Skipped an index hence the 0 as one of the items + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912, 3753, 23806, 3754, 23810, 23811, 3755, 26496, 26497}, -- 166 SE Skipped an index hence the 0 as one of the items [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067, 21680, 22071}, -- 177 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, -- 115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, -- 115 From 5a8fa7197baeb8f618d9b64e851f6ebb7a61a502 Mon Sep 17 00:00:00 2001 From: DrakeFS Date: Sun, 14 May 2023 17:07:33 -0400 Subject: [PATCH 0930/1002] Update Mote-Utility.lua Changed book error text, in set_macro_page(), to reflect that there are 40 macro books. --- addons/GearSwap/libs/Mote-Utility.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/GearSwap/libs/Mote-Utility.lua b/addons/GearSwap/libs/Mote-Utility.lua index 0f734f37ef..44df8d164e 100644 --- a/addons/GearSwap/libs/Mote-Utility.lua +++ b/addons/GearSwap/libs/Mote-Utility.lua @@ -524,7 +524,7 @@ function set_macro_page(set,book) return end if book < 1 or book > 40 then - add_to_chat(123,'Error setting macro page: Macro book ('..tostring(book)..') must be between 1 and 20.') + add_to_chat(123,'Error setting macro page: Macro book ('..tostring(book)..') must be between 1 and 40.') return end send_command('@input /macro book '..tostring(book)..';wait 1.1;input /macro set '..tostring(set)) From 621aaf0a5430733ae8b5d311ffdeca6ad207679d Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Thu, 18 May 2023 16:05:16 +0200 Subject: [PATCH 0931/1002] GearSwap: Added minify feature to export options --- addons/GearSwap/export.lua | 66 ++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/addons/GearSwap/export.lua b/addons/GearSwap/export.lua index deac064b82..2757da93db 100644 --- a/addons/GearSwap/export.lua +++ b/addons/GearSwap/export.lua @@ -26,7 +26,7 @@ function export_set(options) local item_list = T{} - local targinv,all_items,all_sets,use_job_in_filename,use_subjob_in_filename,overwrite_existing,named_file + local targinv,all_items,minify,all_sets,use_job_in_filename,use_subjob_in_filename,overwrite_existing,named_file if #options > 0 then for _,v in ipairs(options) do if S{'inventory','inv','i'}:contains(v:lower()) then @@ -35,6 +35,8 @@ function export_set(options) all_items = true elseif v:lower() == 'wearable' then wearable = true + elseif S{'mini'}:contains(v:lower()) then + minify = true elseif S{'sets','set','s'}:contains(v:lower()) then all_sets = true if not user_env or not user_env.sets then @@ -56,7 +58,7 @@ function export_set(options) end end end - + local buildmsg = 'Exporting ' if all_items then buildmsg = buildmsg..'all your items' @@ -71,7 +73,7 @@ function export_set(options) end buildmsg = buildmsg..' as a lua file.' - + if use_job_in_filename then buildmsg = buildmsg..' (Naming format: Character_JOB)' elseif use_subjob_in_filename then @@ -79,17 +81,17 @@ function export_set(options) elseif named_file then buildmsg = buildmsg..' (Named: Character_'..filename..')' end - + if overwrite_existing then buildmsg = buildmsg..' Will overwrite existing files with same name.' end - + msg.addon_msg(123,buildmsg) - + if not windower.dir_exists(windower.addon_path..'data/export') then windower.create_dir(windower.addon_path..'data/export') end - + if all_items then for i = 0, #res.bags do item_list:extend(get_item_list(items[res.bags[i].english:gsub(' ', ''):lower()])) @@ -105,7 +107,7 @@ function export_set(options) item_list,exported = unpack_names({},'L1',user_env.sets,{},{empty=true}) else -- Default to loading the currently worn gear. - + for i = 1,16 do -- ipairs will be used on item_list if not item_list[i] then item_list[i] = {} @@ -113,7 +115,7 @@ function export_set(options) item_list[i].slot = toslotname(i-1) end end - + for slot_name,gs_item_tab in pairs(items.equipment) do if gs_item_tab.slot ~= empty then local item_tab @@ -138,7 +140,7 @@ function export_set(options) end end end - + if #item_list == 0 then msg.addon_msg(123,'There is nothing to export.') return @@ -155,14 +157,14 @@ function export_set(options) return end end - - + + if not windower.dir_exists(windower.addon_path..'data/export') then windower.create_dir(windower.addon_path..'data/export') end - + local path = windower.addon_path..'data/export/'..player.name - + if use_job_in_filename then path = path..'_'..windower.ffxi.get_player().main_job elseif use_subjob_in_filename then @@ -172,23 +174,39 @@ function export_set(options) else path = path..os.date(' %Y-%m-%d %H-%M-%S') end - -- Default to exporting in .lua + if (not overwrite_existing) and windower.file_exists(path..'.lua') then path = path..' '..os.clock() end + local f = io.open(path..'.lua','w+') - f:write('sets.exported={\n') - for i,v in ipairs(item_list) do - if v.name ~= empty then - if v.augments then - --Advanced set table - f:write(' '..v.slot..'={ name="'..v.name..'", augments={'..v.augments..'}},\n') - else - f:write(' '..v.slot..'="'..v.name..'",\n') + if minify then + f:write('sets.exported={\n') + for i,v in ipairs(item_list) do + if v.name ~= empty then + if v.augments then + --Advanced set table + f:write(v.slot..'={ name="'..v.name..'", augments={'..v.augments..'}},') + else + f:write(v.slot..'="'..v.name..'",') + end + end + end + f:write('\n}') + else + f:write('sets.exported={\n') + for i,v in ipairs(item_list) do + if v.name ~= empty then + if v.augments then + --Advanced set table + f:write(' '..v.slot..'={ name="'..v.name..'", augments={'..v.augments..'}},\n') + else + f:write(' '..v.slot..'="'..v.name..'",\n') + end end end + f:write('}') end - f:write('}') f:close() end From 2b47c1893ee38bb8d9523c5b29fbcdf5cef4d381 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Thu, 8 Jun 2023 03:00:04 +0200 Subject: [PATCH 0932/1002] Fixing some statuses Fixing some statuses to use the long form. --- addons/battlemod/battlemod.lua | 13 +++++-------- addons/battlemod/statics.lua | 2 +- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index 9a0b17a7e4..4283ca60d0 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -13,7 +13,7 @@ require 'generic_helpers' require 'parse_action_packet' require 'statics' -_addon.version = '3.32' +_addon.version = '3.33' _addon.name = 'BattleMod' _addon.author = 'Byrth, maintainer: SnickySnacks' _addon.commands = {'bm','battlemod'} @@ -364,6 +364,7 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec elseif (am.message_id == 206 or am.message_id == 204) and condensetargets then -- Wears off and is no longer messages -- Condenses across multiple packets local status + local lang = log_form_messages:contains(am.message_id) and 'english_log' or language if not is_injected and am.message_id == 206 then local outstr = res.action_messages[am.message_id][language] @@ -379,15 +380,11 @@ windower.register_event('incoming chunk',function (id,original,modified,is_injec end if enfeebling:contains(am.param_1) and res.buffs[am.param_1] then - if log_form_messages:contains(am.message_id) then - status = color_it(res.buffs[am.param_1].english_log,color_arr.enfeebcol) - else - status = color_it(res.buffs[am.param_1][language],color_arr.enfeebcol) - end + status = color_it(res.buffs[am.param_1][lang],color_arr.enfeebcol) elseif color_arr.statuscol == rcol then - status = color_it(res.buffs[am.param_1][language],string.char(0x1F,191)) + status = color_it(res.buffs[am.param_1][lang],string.char(0x1F,191)) else - status = color_it(res.buffs[am.param_1][language],color_arr.statuscol) + status = color_it(res.buffs[am.param_1][lang],color_arr.statuscol) end if not multi_actor[status] then multi_actor[status] = player_info(am.actor_id) end diff --git a/addons/battlemod/statics.lua b/addons/battlemod/statics.lua index 03262651df..d4c14c2426 100644 --- a/addons/battlemod/statics.lua +++ b/addons/battlemod/statics.lua @@ -154,7 +154,7 @@ domain_buffs = S{ 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} +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,572,576,597,630,631} reaction_offsets = { [1] = 8, From 3788ad42fc774711086e78032d15400203a2d01a Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Mon, 12 Jun 2023 08:46:24 -0600 Subject: [PATCH 0933/1002] Update slips.lua Poison Axe (+1) -- guess --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index f8307fdffc..ae70d59292 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757, 25909}, -- 192 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912, 3753, 23806, 3754, 23810, 23811, 3755, 26496, 26497}, -- 166 SE Skipped an index hence the 0 as one of the items + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912, 3753, 23806, 3754, 23810, 23811, 3755, 26496, 26497, 21786, 21787}, -- 166 SE Skipped an index hence the 0 as one of the items [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067, 21680, 22071}, -- 177 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, -- 115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, -- 115 From 18ed35d9a05d3e2b8ff01784807c5247b3152d05 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Wed, 14 Jun 2023 09:28:52 -0600 Subject: [PATCH 0934/1002] [packets] fields.lua Zone Line Packet discoveries --- addons/libs/packets/fields.lua | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 2b6a53bb6b..3fc1231b1e 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -712,8 +712,9 @@ fields.outgoing[0x05E] = L{ -- Zone line identifier ('4' for Port Jeuno > Qufim Island, '2' for Port Jeuno > Lower Jeuno, etc.) {ctype='data[12]', label='_unknown1', const=''}, -- 08 {ctype='unsigned short', label='_unknown2', const=0}, -- 14 - {ctype='unsigned char', label='_unknown3', const=0x04}, -- 16 Seemed to never vary for me - {ctype='unsigned char', label='Type'}, -- 17 03 for leaving the MH, 00 otherwise + {ctype='unsigned char', label='MH Door Menu', fn=e+{'mh door menus'}}, -- 16 should always contain the "MH Door Menu" byte of the last `incoming 0x00A` + {ctype='unsigned char', label='Type'}, -- 17 should be 0 except for when using mog house door, when it is a menu value: + -- 0="Whence I came", 1=first_option, 2=second_option, 3and-so-on, 125=mh_first_floor, 126=mh_second_floor, 127=mog_garden } -- Equipment Screen, also observed when zoning @@ -1217,6 +1218,19 @@ types.job_level = L{ {ctype='unsigned char', label='Level'}, -- 00 } +enums['mh door menus'] = { -- only known use is Mog House exit menu type + [0x00] = 'None', -- results in simple yes/no dialog to leave to where you came from + [0x01] = 'San d\'Oria', -- only when flower girl quest completed + [0x02] = 'Bastok', -- only when flower girl quest completed + [0x03] = 'Windurst', -- only when flower girl quest completed + [0x04] = 'Jeuno', -- only when flower girl quest completed + [0x05] = 'Aht Urgan', -- only when flower girl quest completed + [0x06] = "San d\'Oria [S]", -- only one exit so value should never be seen on retail (but value tested) + [0x07] = "Bastok [S]", -- only one exit so value should never be seen on retail (but value tested) + [0x08] = "Windurst [S]", -- only one exit so value should never be seen on retail (but value tested) + [0x09] = 'Adoulin', -- no flower girl quest, should always be this value for adoulin mh +} + -- Zone update fields.incoming[0x00A] = L{ {ctype='unsigned int', label='Player', fn=id}, -- 04 @@ -1267,7 +1281,11 @@ fields.incoming[0x00A] = L{ {ctype='unsigned int', label='_unknown9', const=0x0003A020}, -- A4 {ctype='data[2]', label='_unknown10'}, -- A8 {ctype='unsigned short', label='Zone model'}, -- AA - {ctype='data[8]', label='_unknown11'}, -- AC 0xAC is 2 for some zones, 0 for others + {ctype='data[2]', label='_unknown11'}, -- AC 0xAC is 2 for some zones, 0 for others + {ctype='unsigned char', label='MH Door Menu',fn=e+{'mh door menus'}}, -- AE Updated when Mog House entered. Determines which MH exits are available in door/exit menu. + -- Persists through zoning and logout. see enum for more info + {ctype='unsigned char', label='Nomad Moogle'}, -- AF set to 1 iff nomad moogle menu is accessible in zone (Odyssey:Gaol, Mhaura, Norg, etc -- but not mog house or mog garden) + {ctype='data[4]', label='_unknown12'}, -- B0 {ctype='unsigned char', label='Main Job', fn=job}, -- B4 {ctype='unsigned char', label='_unknown12'}, -- B5 {ctype='unsigned char', label='_unknown13'}, -- B6 @@ -4042,4 +4060,3 @@ Redistribution and use in source and binary forms, with or without modification, 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 Windower 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. ]] - From 748cde40910f82ea15fd5468beae2101b9de3ae6 Mon Sep 17 00:00:00 2001 From: maxom1310 <82432645+maxom1310@users.noreply.github.com> Date: Wed, 14 Jun 2023 14:12:46 -0400 Subject: [PATCH 0935/1002] Update helper_functions.lua --- addons/GearSwap/helper_functions.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/GearSwap/helper_functions.lua b/addons/GearSwap/helper_functions.lua index 9732048843..4d78846fbd 100644 --- a/addons/GearSwap/helper_functions.lua +++ b/addons/GearSwap/helper_functions.lua @@ -711,7 +711,7 @@ function check_spell(available_spells,spell) local spell_jobs = copy_entry(res.spells[spell.id].levels) if not available_spells[spell.id] and not ( (not disable_table[5] and not disable_table[4] and spell.id == 503) or -- Body + Head + Impact - (not disable_table[2] and spell.id == 417) or -- Range + Honor March + (not disable_table[2] and (spell.id == 417 or spell.id == 418) or -- Range + Honor March + Aria of Passion ((not disable_table[0] or not disable_table[1]) and spell.id == 360) -- Main or Sub + Dispelga ) then return false,"Unable to execute command. You do not know that spell ("..(res.spells[spell.id][language] or spell.id)..")" From 798358d67ed8e51054d1a8e3e8f0fe0d5aace5f6 Mon Sep 17 00:00:00 2001 From: maxom1310 <82432645+maxom1310@users.noreply.github.com> Date: Wed, 14 Jun 2023 14:14:33 -0400 Subject: [PATCH 0936/1002] Update helper_functions.lua --- addons/GearSwap/helper_functions.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/GearSwap/helper_functions.lua b/addons/GearSwap/helper_functions.lua index 4d78846fbd..1afaa222c0 100644 --- a/addons/GearSwap/helper_functions.lua +++ b/addons/GearSwap/helper_functions.lua @@ -711,7 +711,7 @@ function check_spell(available_spells,spell) local spell_jobs = copy_entry(res.spells[spell.id].levels) if not available_spells[spell.id] and not ( (not disable_table[5] and not disable_table[4] and spell.id == 503) or -- Body + Head + Impact - (not disable_table[2] and (spell.id == 417 or spell.id == 418) or -- Range + Honor March + Aria of Passion + (not disable_table[2] and (spell.id == 417 or spell.id == 418)) or -- Range + Honor March + Aria of Passion ((not disable_table[0] or not disable_table[1]) and spell.id == 360) -- Main or Sub + Dispelga ) then return false,"Unable to execute command. You do not know that spell ("..(res.spells[spell.id][language] or spell.id)..")" From f54479e943968630c5a0e3b633b4f67f92e244a1 Mon Sep 17 00:00:00 2001 From: Matt Newnham-Wheatley Date: Thu, 22 Jun 2023 20:26:52 +0100 Subject: [PATCH 0937/1002] Update gametime.lua to resolve issue with loading on Lightningday The gametime addon will not load correctly on Lightningday due to a check only looking for the pluralised form. --- addons/gametime/gametime.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/gametime/gametime.lua b/addons/gametime/gametime.lua index 6b9d4c2a03..7c439cb01d 100644 --- a/addons/gametime/gametime.lua +++ b/addons/gametime/gametime.lua @@ -320,7 +320,7 @@ function day_change(day) dlist = {'4','5','6','7','8','1','2','3'} elseif (day == 'Iceday') then dlist = {'5','6','7','8','1','2','3','4'} - elseif (day == 'Lightningsday') then + elseif (day == 'Lightningday') then dlist = {'6','7','8','1','2','3','4','5'} elseif (day == 'Lightsday') then dlist = {'7','8','1','2','3','4','5','6'} From 30030a61d3fe98ecc76b395d47bba92714cb986c Mon Sep 17 00:00:00 2001 From: Byrth Date: Wed, 5 Jul 2023 22:40:31 -0400 Subject: [PATCH 0938/1002] make it possible to access text settings again --- addons/libs/texts.lua | 4 ++++ addons/pointwatch/pointwatch.lua | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/addons/libs/texts.lua b/addons/libs/texts.lua index d040b63804..32cf2e9d70 100644 --- a/addons/libs/texts.lua +++ b/addons/libs/texts.lua @@ -607,6 +607,10 @@ function texts.destroy(t) meta[t] = nil end +function texts.settings(t) + return meta[t].settings +end + -- Handle drag and drop windower.register_event('mouse', function(type, x, y, delta, blocked) if blocked then diff --git a/addons/pointwatch/pointwatch.lua b/addons/pointwatch/pointwatch.lua index 4fc0ac0dda..aa67a7a4a5 100644 --- a/addons/pointwatch/pointwatch.lua +++ b/addons/pointwatch/pointwatch.lua @@ -203,7 +203,7 @@ windower.register_event('addon command',function(...) end end texts[first_cmd](box,unpack(tab)) - settings.text_box_settings = box._settings + settings.text_box_settings = box.settings() config.save(settings) elseif first_cmd == 'reload' then windower.send_command('lua r pointwatch') From 174d6f4a2b644473f560c8be39896d69158debbd Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Mon, 10 Jul 2023 14:56:58 +0200 Subject: [PATCH 0939/1002] [Slips] Update for July 10, 2023 items Adding items from the July 10, 2023 update. --- addons/libs/slips.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index ae70d59292..b73a377b28 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -15,7 +15,7 @@ slips.storages = L{29312, 29313, 29314, 29315, 29316, 29317, 29318, 2931 slips.items = { [slips.storages[1]] = L{16084, 14546, 14961, 15625, 15711, 16085, 14547, 14962, 15626, 15712, 16086, 14548, 14963, 15627, 15713, 16087, 14549, 14964, 15628, 15714, 16088, 14550, 14965, 15629, 15715, 16089, 14551, 14966, 15630, 15716, 16090, 14552, 14967, 15631, 15717, 16091, 14553, 14968, 15632, 15718, 16092, 14554, 14969, 15633, 15719, 16093, 14555, 14970, 15634, 15720, 16094, 14556, 14971, 15635, 15721, 16095, 14557, 14972, 15636, 15722, 16096, 14558, 14973, 15637, 15723, 16097, 14559, 14974, 15638, 15724, 16098, 14560, 14975, 15639, 15725, 16099, 14561, 14976, 15640, 15726, 16100, 14562, 14977, 15641, 15727, 16101, 14563, 14978, 15642, 15728, 16102, 14564, 14979, 15643, 15729, 16103, 14565, 14980, 15644, 15730, 16106, 14568, 14983, 15647, 15733, 16107, 14569, 14984, 15648, 15734, 16108, 14570, 14985, 15649, 15735, 16602, 17741, 18425, 18491, 18588, 18717, 18718, 18850, 18943, 16069, 14530, 14940, 15609, 15695, 16062, 14525, 14933, 15604, 15688, 16064, 14527, 14935, 15606, 15690, 18685, 18065, 17851, 18686, 18025, 18435, 18113, 17951, 17715, 18485, 18408, 18365, 18583, 18417, 18388, 16267, 16268, 16269, 16228, 16229, 15911, 15799, 15800, 15990, 17745, 18121, 16117, 14577, 17857}, -- 168 [slips.storages[2]] = L{12421, 12549, 12677, 12805, 12933, 13911, 14370, 14061, 14283, 14163, 12429, 12557, 12685, 12813, 12941, 13924, 14371, 14816, 14296, 14175, 13934, 14387, 14821, 14303, 14184, 13935, 14388, 14822, 14304, 14185, 13876, 13787, 14006, 14247, 14123, 13877, 13788, 14007, 14248, 14124, 13908, 14367, 14058, 14280, 14160, 13909, 14368, 14059, 14281, 14161, 16113, 14573, 14995, 15655, 15740, 16115, 14575, 14997, 15657, 15742, 16114, 14574, 14996, 15656, 15741, 16116, 14576, 14998, 15658, 15743, 12818, 18198, 12946, 18043, 12690, 17659, 12296, 12434, 15471, 15472, 15473, 15508, 15509, 15510, 15511, 15512, 15513, 15514, 17710, 17595, 18397, 18360, 18222, 17948, 18100, 15475, 15476, 15477, 15488, 15961, 14815, 14812, 14813, 15244, 15240, 14488, 14905, 15576, 15661, 15241, 14489, 14906, 15577, 15662, 13927, 14378, 14076, 14308, 14180, 13928, 14379, 14077, 14309, 14181, 10438, 10276, 10320, 10326, 10367, 10439, 10277, 10321, 10327, 10368, 10440, 10278, 10322, 10328, 10369, 10441, 10279, 10323, 10329, 10370, 25734, 25735, 25736, 25737, 25738, 25739, 25740, 25741, 25742, 25743, 25744}, -- 155 - [slips.storages[3]] = L{16155, 11282, 15021, 16341, 11376, 16156, 11283, 15022, 16342, 11377, 16157, 11284, 15023, 16343, 11378, 16148, 14590, 15011, 16317, 15757, 16143, 14591, 15012, 16318, 15758, 16146, 14588, 15009, 16315, 15755, 16147, 14589, 15010, 16316, 15756, 15966, 15967, 19041, 17684, 17685, 11636, 15844, 15934, 16258, 18735, 18734, 16291, 16292, 19042, 15935, 16293, 16294, 15936, 18618, 11588, 11545, 16158, 16159, 16160, 16149, 14583, 15007, 16314, 15751, 16141, 14581, 15005, 16312, 15749, 16142, 14582, 15006, 16313, 15750, 10876, 10450, 10500, 11969, 10600, 10877, 10451, 10501, 11970, 10601, 10878, 10452, 10502, 11971, 10602, 19132, 18551, 11798, 11362, 11363, 11625, 15959, 16259, 22299, 26414, 21623, 26219, 21886, 23792, 23793, 23794, 23795, 23796, 22032, 22043, 21530, 22044, 26273, 25415, 25416, 25414, 22050, 22302, 26365, 26366}, -- 119 + [slips.storages[3]] = L{16155, 11282, 15021, 16341, 11376, 16156, 11283, 15022, 16342, 11377, 16157, 11284, 15023, 16343, 11378, 16148, 14590, 15011, 16317, 15757, 16143, 14591, 15012, 16318, 15758, 16146, 14588, 15009, 16315, 15755, 16147, 14589, 15010, 16316, 15756, 15966, 15967, 19041, 17684, 17685, 11636, 15844, 15934, 16258, 18735, 18734, 16291, 16292, 19042, 15935, 16293, 16294, 15936, 18618, 11588, 11545, 16158, 16159, 16160, 16149, 14583, 15007, 16314, 15751, 16141, 14581, 15005, 16312, 15749, 16142, 14582, 15006, 16313, 15750, 10876, 10450, 10500, 11969, 10600, 10877, 10451, 10501, 11970, 10601, 10878, 10452, 10502, 11971, 10602, 19132, 18551, 11798, 11362, 11363, 11625, 15959, 16259, 22299, 26414, 21623, 26219, 21886, 23792, 23793, 23794, 23795, 23796, 22032, 22043, 21530, 22044, 26273, 25415, 25416, 25414, 22050, 22302, 26365, 26366, 23862, 23863, 23864, 23865, 21536}, -- 124 [slips.storages[4]] = L{12511, 12638, 13961, 14214, 14089, 12512, 12639, 13962, 14215, 14090, 13855, 12640, 13963, 14216, 14091, 13856, 12641, 13964, 14217, 14092, 12513, 12642, 13965, 14218, 14093, 12514, 12643, 13966, 14219, 14094, 12515, 12644, 13967, 14220, 14095, 12516, 12645, 13968, 14221, 14096, 12517, 12646, 13969, 14222, 14097, 13857, 12647, 13970, 14223, 14098, 12518, 12648, 13971, 14099, 14224, 13868, 13781, 13972, 14225, 14100, 13869, 13782, 13973, 14226, 14101, 12519, 12649, 13974, 14227, 14102, 12520, 12650, 13975, 14228, 14103, 15265, 14521, 14928, 15600, 15684, 15266, 14522, 14929, 15601, 15685, 15267, 14523, 14930, 15602, 15686, 16138, 14578, 15002, 15659, 15746, 16139, 14579, 15003, 15660, 15747, 16140, 14580, 15004, 16311, 15748, 16678, 17478, 17422, 17423, 16829, 16764, 17643, 16798, 16680, 16766, 17188, 17812, 17771, 17772, 16887, 17532, 17717, 18702, 17858, 19203, 21461, 21124, 20776, 27786, 27926, 28066, 28206, 28346, 27787, 27927, 28067, 28207, 28347}, -- 138 [slips.storages[5]] = L{15225, 14473, 14890, 15561, 15352, 15226, 14474, 14891, 15562, 15353, 15227, 14475, 14892, 15563, 15354, 15228, 14476, 14893, 15564, 15355, 15229, 14477, 14894, 15565, 15356, 15230, 14478, 14895, 15566, 15357, 15231, 14479, 14896, 15567, 15358, 15232, 14480, 14897, 15568, 15359, 15233, 14481, 14898, 15569, 15360, 15234, 14482, 14899, 15570, 15361, 15235, 14483, 14900, 15362, 15571, 15236, 14484, 14901, 15572, 15363, 15237, 14485, 14902, 15573, 15364, 15238, 14486, 14903, 15574, 15365, 15239, 14487, 14904, 15575, 15366, 11464, 11291, 15024, 16345, 11381, 11467, 11294, 15027, 16348, 11384, 11470, 11297, 15030, 16351, 11387, 11475, 11302, 15035, 16357, 11393, 11476, 11303, 15036, 16358, 11394, 11477, 11304, 15037, 16359, 11395}, -- 105 [slips.storages[6]] = L{15072, 15087, 15102, 15117, 15132, 15871, 15073, 15088, 15103, 15118, 15133, 15478, 15074, 15089, 15104, 15119, 15134, 15872, 15075, 15090, 15105, 15120, 15135, 15874, 15076, 15091, 15106, 15121, 15136, 15873, 15077, 15092, 15107, 15122, 15137, 15480, 15078, 15093, 15108, 15123, 15138, 15481, 15079, 15094, 15109, 15124, 15139, 15479, 15080, 15095, 15110, 15125, 15140, 15875, 15081, 15096, 15111, 15126, 15141, 15482, 15082, 15097, 15112, 15127, 15142, 15876, 15083, 15098, 15113, 15128, 15143, 15879, 15084, 15099, 15114, 15129, 15144, 15877, 15085, 15100, 15115, 15130, 15145, 15878, 15086, 15101, 15116, 15131, 15146, 15484, 11465, 11292, 15025, 16346, 11382, 16244, 11468, 11295, 15028, 16349, 11385, 15920, 11471, 11298, 15031, 16352, 11388, 16245, 11478, 11305, 15038, 16360, 11396, 16248, 11480, 11307, 15040, 16362, 11398, 15925}, -- 120 @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757, 25909}, -- 192 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912, 3753, 23806, 3754, 23810, 23811, 3755, 26496, 26497, 21786, 21787}, -- 166 SE Skipped an index hence the 0 as one of the items + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912, 3753, 23806, 3754, 23810, 23811, 3755, 26496, 26497, 21786, 21787, 21996, 21997}, -- 170 SE Skipped an index hence the 0 as one of the items [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067, 21680, 22071}, -- 177 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, -- 115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, -- 115 From e3600b8d71d6626078bea5f7209533eea1d8f1dc Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Fri, 21 Jul 2023 09:49:52 +0100 Subject: [PATCH 0940/1002] Update itemizer.lua This change fixes an issue where itemizer would fail to locate HQ items, whose name ended with "+1", "+2" etc, because was treating the the +x at the end of the string as the amount argument instead. --- addons/itemizer/itemizer.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/itemizer/itemizer.lua b/addons/itemizer/itemizer.lua index 31015e34ea..f0006c2eea 100644 --- a/addons/itemizer/itemizer.lua +++ b/addons/itemizer/itemizer.lua @@ -1,6 +1,6 @@ _addon.name = 'Itemizer' _addon.author = 'Ihina' -_addon.version = '3.0.1.3' +_addon.version = '3.0.1.4' _addon.command = 'itemizer' require('luau') @@ -127,7 +127,7 @@ windower.register_event('unhandled command', function(command, ...) local last = args[#args] if last == 'all' then args:remove() - elseif tonumber(last) then + elseif tonumber(last) and not last:find('+') then count = tonumber(last) args:remove() else From e68b930fac4906301aaf112136d14ac36ca6ceab Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Tue, 25 Jul 2023 15:39:59 +0100 Subject: [PATCH 0941/1002] Update setbgm.lua Added `find` argument and corresponding functionality to search song names for a provided string. --- addons/setbgm/setbgm.lua | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/addons/setbgm/setbgm.lua b/addons/setbgm/setbgm.lua index 450b746b10..390b2dda60 100644 --- a/addons/setbgm/setbgm.lua +++ b/addons/setbgm/setbgm.lua @@ -31,7 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --]] _addon.name = 'setbgm' -_addon.version = '1.2.3' +_addon.version = '1.3.0' _addon.command = 'setbgm' _addon.author = 'Seth VanHeulen (Acacia@Odin)' @@ -118,6 +118,15 @@ function display_songs() end end +function find_songs(str) + windower.add_to_chat(207, 'Songs matching %s:':format(str:color(204))) + for id=25,900 do + if songs[id] and songs[id]:lower():find(str) then + windower.add_to_chat(207, ' %s: %s':format(tostring(id):color(204), songs[id])) + end + end +end + function display_music_types() windower.add_to_chat(207, 'Available music types:') local output = ' ' @@ -130,6 +139,7 @@ end function display_help() windower.add_to_chat(167, 'Command usage:') windower.add_to_chat(167, ' setbgm list [music|type]') + windower.add_to_chat(167, ' setbgm find ') windower.add_to_chat(167, ' setbgm []') windower.add_to_chat(167, ' setbgm ') end @@ -145,6 +155,10 @@ function setbgm_command(...) elseif #arg == 2 and arg[1]:lower() == 'list' and arg[2]:lower() == 'type' then display_music_types() return + elseif #arg == 2 and arg[1]:lower() == 'find' then + local str = arg[2]:lower() + find_songs(str) + return elseif #arg == 1 then set_music(nil, arg[1]) return From e0e3fae58edf3d2ee8adb47849988b06fd263122 Mon Sep 17 00:00:00 2001 From: Nifim Date: Sun, 6 Aug 2023 20:05:32 -0700 Subject: [PATCH 0942/1002] Remove unnecessary print --- addons/GearSwap/user_functions.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/GearSwap/user_functions.lua b/addons/GearSwap/user_functions.lua index 2062955ddc..1bb3110917 100644 --- a/addons/GearSwap/user_functions.lua +++ b/addons/GearSwap/user_functions.lua @@ -81,10 +81,10 @@ function move_spell_target(position_table) if type(position_table) == 'table' and type(position_table.x or position_table.X) == 'number' and type(position_table.y or position_table.Y) == 'number' and type(position_table.z or position_table.Z) == 'number' then + _global.target_arrow.x = position_table.x or position_table.X _global.target_arrow.y = position_table.y or position_table.Y _global.target_arrow.z = position_table.z or position_table.Z - print_set(_global.target_arrow) else error('\nGearSwap: move_spell_target() was passed an invalid value ('..tostring(position_table)..'). Should be a table with x, y, and z keys (offset from target)', 2) end From 9183495e6201eab786741e89779372ec008e8db8 Mon Sep 17 00:00:00 2001 From: Byrth Date: Wed, 9 Aug 2023 09:04:49 -0400 Subject: [PATCH 0943/1002] 2023-08 boxdestroyer update --- addons/boxdestroyer/messages.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/boxdestroyer/messages.lua b/addons/boxdestroyer/messages.lua index b955bc6173..4a2708d859 100644 --- a/addons/boxdestroyer/messages.lua +++ b/addons/boxdestroyer/messages.lua @@ -1,12 +1,12 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination" for the associated zone IDs - [100] = 8066, + [100] = 8067, [101] = 7516, [102] = 7917, [103] = 8092, [104] = 8657, [105] = 7708, [106] = 8082, - [107] = 7543, + [107] = 7544, [108] = 7612, [109] = 8475, [110] = 7599, @@ -15,7 +15,7 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination [113] = 7939, [114] = 7777, [115] = 7873, - [116] = 7569, + [116] = 7570, [117] = 7576, [118] = 8118, [119] = 8355, From 9c96475a44edf4b854b7e04e3187af5888689f6f Mon Sep 17 00:00:00 2001 From: Byrth Date: Wed, 9 Aug 2023 09:04:49 -0400 Subject: [PATCH 0944/1002] 2023-08 boxdestroyer update --- addons/boxdestroyer/messages.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/boxdestroyer/messages.lua b/addons/boxdestroyer/messages.lua index b955bc6173..4a2708d859 100644 --- a/addons/boxdestroyer/messages.lua +++ b/addons/boxdestroyer/messages.lua @@ -1,12 +1,12 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination" for the associated zone IDs - [100] = 8066, + [100] = 8067, [101] = 7516, [102] = 7917, [103] = 8092, [104] = 8657, [105] = 7708, [106] = 8082, - [107] = 7543, + [107] = 7544, [108] = 7612, [109] = 8475, [110] = 7599, @@ -15,7 +15,7 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination [113] = 7939, [114] = 7777, [115] = 7873, - [116] = 7569, + [116] = 7570, [117] = 7576, [118] = 8118, [119] = 8355, From a16eabfc3cade5f078cc1051e49cf35470c20d1a Mon Sep 17 00:00:00 2001 From: AkadenTK Date: Fri, 11 Aug 2023 20:33:14 -0500 Subject: [PATCH 0945/1002] Fix for allowing blocked messages through --- addons/translate/translate.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/translate/translate.lua b/addons/translate/translate.lua index 78306bc87f..bb61d07b4c 100644 --- a/addons/translate/translate.lua +++ b/addons/translate/translate.lua @@ -221,6 +221,7 @@ windower.register_event('incoming chunk',function(id,orgi,modi,is_injected,is_bl end return true end + return is_blocked end) function translate_phrase(out_text) From 21df0324635171b7f5d0e437b2a2c04352ebec73 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Mon, 14 Aug 2023 21:49:38 +0100 Subject: [PATCH 0946/1002] Update setbgm.lua The `find` argument will print a notice if no matching songs are found. --- addons/setbgm/setbgm.lua | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/addons/setbgm/setbgm.lua b/addons/setbgm/setbgm.lua index 390b2dda60..42d831405c 100644 --- a/addons/setbgm/setbgm.lua +++ b/addons/setbgm/setbgm.lua @@ -120,11 +120,17 @@ end function find_songs(str) windower.add_to_chat(207, 'Songs matching %s:':format(str:color(204))) + local output = '' for id=25,900 do if songs[id] and songs[id]:lower():find(str) then - windower.add_to_chat(207, ' %s: %s':format(tostring(id):color(204), songs[id])) + output = output .. '\n %s: %s':format(tostring(id):color(204), songs[id]) end end + if output ~= '' then + windower.add_to_chat(207,output) + else + windower.add_to_chat(207,' No songs matching %s found.':format(str:color(204))) + end end function display_music_types() @@ -155,8 +161,9 @@ function setbgm_command(...) elseif #arg == 2 and arg[1]:lower() == 'list' and arg[2]:lower() == 'type' then display_music_types() return - elseif #arg == 2 and arg[1]:lower() == 'find' then - local str = arg[2]:lower() + elseif #arg > 1 and arg[1]:lower() == 'find' then + table.remove(arg,1) + local str = table.concat(arg,' ') find_songs(str) return elseif #arg == 1 then From 01b36c3020783aeed03d68a57c2690e5cf7d3d25 Mon Sep 17 00:00:00 2001 From: funkworkz Date: Fri, 18 Aug 2023 09:18:08 -0500 Subject: [PATCH 0947/1002] Update setbgm.lua --- addons/setbgm/setbgm.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/setbgm/setbgm.lua b/addons/setbgm/setbgm.lua index 42d831405c..4a78255f83 100644 --- a/addons/setbgm/setbgm.lua +++ b/addons/setbgm/setbgm.lua @@ -50,8 +50,8 @@ music_types = { } songs = { - [25]='Voracious Resurgence Unknown 1', [26]='Voracious Resurgence Unknown 2', [27]='Voracious Resurgence Unknown 3', [28]='The Destiny Destroyers', [29]="Devils' Delight", [30]="Odyssey - Bumba", [31]='Voracious Resurgence Unknown 4', [32]='Voracious Resurgence Unknown 5', - [33]='Voracious Resurgence Unknown 6', [34]="We Are Vana'diel", [35]='Goddessspeed', [36]='Sortie - +3 Area', [37]='Voracious Resurgence Unknown 7', [38]='Voracious Resurgence Unknown 8', + [25]='The Voracious Resurgence', [26]='The Devoured', [27]='Enroaching Perils', [28]='The Destiny Destroyers', [29]="Devils' Delight", [30]="Sojourner", [31]='Black Stars Rise', [32]='All Smiles', + [33]='Valhalla', [34]="We Are Vana'diel", [35]='Goddessspeed', [36]='Good Fortune', [37]='All-Consuming Chaos', [38]='Your Choice', [40]='Cloister of Time and Souls', [41]='Royal Wanderlust', [42]='Snowdrift Waltz', [43]='Troubled Shadows', [44]='Where Lords Rule Not', [45]='Summers Lost', [46]='Goddess Divine', [47]='Echoes of Creation', [48]='Main Theme', [49]='Luck of the Mog', [50]='Feast of the Ladies', [51]='Abyssea - Scarlet Skies, Shadowed Plains', [52]='Melodies Errant', [53]='Shinryu', [54]='Everlasting Bonds', [55]='Provenance Watcher', [56]='Where it All Begins', [57]='Steel Sings, Blades Dance', [58]='A New Direction', [59]='The Pioneers', [60]='Into Lands Primeval - Ulbuka', [61]="Water's Umbral Knell", [62]='Keepers of the Wild', [63]='The Sacred City of Adoulin', [64]='Breaking Ground', [65]='Hades', [66]='Arciela', [67]='Mog Resort', [68]='Worlds Away', [69]="Distant Worlds (Nanaa Mihgo's version)", From f15f789ff7e50b7ecb613bb9fe57f35adc976a52 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sat, 19 Aug 2023 01:06:02 +0100 Subject: [PATCH 0948/1002] Update setbgm.lua A value of `0` effectively disables the music reproduction for the given type. Debated calling it "silence" or "disabled" but settled for "No Music" in the end. Also bumped version after this change and last PR by Funk. --- addons/setbgm/setbgm.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/setbgm/setbgm.lua b/addons/setbgm/setbgm.lua index 4a78255f83..f9ca9622a8 100644 --- a/addons/setbgm/setbgm.lua +++ b/addons/setbgm/setbgm.lua @@ -31,7 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --]] _addon.name = 'setbgm' -_addon.version = '1.3.0' +_addon.version = '1.3.2' _addon.command = 'setbgm' _addon.author = 'Seth VanHeulen (Acacia@Odin)' @@ -50,6 +50,7 @@ music_types = { } songs = { + [0] = 'No Music', [25]='The Voracious Resurgence', [26]='The Devoured', [27]='Enroaching Perils', [28]='The Destiny Destroyers', [29]="Devils' Delight", [30]="Sojourner", [31]='Black Stars Rise', [32]='All Smiles', [33]='Valhalla', [34]="We Are Vana'diel", [35]='Goddessspeed', [36]='Good Fortune', [37]='All-Consuming Chaos', [38]='Your Choice', [40]='Cloister of Time and Souls', [41]='Royal Wanderlust', [42]='Snowdrift Waltz', [43]='Troubled Shadows', [44]='Where Lords Rule Not', [45]='Summers Lost', [46]='Goddess Divine', [47]='Echoes of Creation', [48]='Main Theme', [49]='Luck of the Mog', From b618d7e85e44df902e298495a8485ace817362be Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Thu, 17 Aug 2023 19:48:21 +0200 Subject: [PATCH 0949/1002] [Slips lib] August 2023 Update August 2023 Update for the Slips library. --- addons/libs/slips.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index b73a377b28..4ac34e8133 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757, 25909}, -- 192 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912, 3753, 23806, 3754, 23810, 23811, 3755, 26496, 26497, 21786, 21787, 21996, 21997}, -- 170 SE Skipped an index hence the 0 as one of the items + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912, 3753, 23806, 3754, 23810, 23811, 3755, 26496, 26497, 21786, 21787, 21996, 21997, 23802, 25777, 25778}, -- 173 SE Skipped an index hence the 0 as one of the items [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067, 21680, 22071}, -- 177 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, -- 115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, -- 115 @@ -43,6 +43,7 @@ slips.items = { [slips.storages[28]] = L{21515, 21561, 21617, 21670, 21718, 21775, 21826, 21879, 21918, 21971, 22027, 22082, 22108, 22214, 21516, 21562, 21618, 21671, 21719, 21776, 21827, 21880, 21919, 21972, 22028, 22083, 22109, 22215, 21517, 21563, 21619, 21672, 21720, 21777, 21828, 21881, 21920, 21973, 22029, 22084, 22110, 22216, 21518, 21564, 21620, 21673, 21721, 21778, 21829, 21882, 21921, 21974, 22030, 22085, 22111, 22217, 21519, 21565, 21621, 21674, 21722, 21779, 21830, 21883, 21922, 21975, 22031, 22086, 22107, 22218, 22089}, --71 [slips.storages[29]] = L{23085, 23152, 23219, 23286, 23353, 23086, 23153, 23220, 23287, 23354, 23087, 23154, 23221, 23288, 23355, 23088, 23155, 23222, 23289, 23356, 23089, 23156, 23223, 23290, 23357, 23090, 23157, 23224, 23291, 23358, 23091, 23158, 23225, 23292, 23359, 23092, 23159, 23226, 23293, 23360, 23093, 23160, 23227, 23294, 23361, 23094, 23161, 23228, 23295, 23362, 23095, 23162, 23229, 23296, 23363, 23096, 23163, 23230, 23297, 23364, 23097, 23164, 23231, 23298, 23365, 23098, 23165, 23232, 23299, 23366, 23099, 23166, 23233, 23300, 23367, 23100, 23167, 23234, 23301, 23368, 23101, 23168, 23235, 23302, 23369, 23102, 23169, 23236, 23303, 23370, 23103, 23170, 23237, 23304, 23371, 23104, 23171, 23238, 23305, 23372, 23105, 23172, 23239, 23306, 23373, 23106, 23173, 23240, 23307, 23374}, -- 110 [slips.storages[30]] = L{23420, 23487, 23554, 23621, 23688, 23421, 23488, 23555, 23622, 23689, 23422, 23489, 23556, 23623, 23690, 23423, 23490, 23557, 23624, 23691, 23424, 23491, 23558, 23625, 23692, 23425, 23492, 23559, 23626, 23693, 23426, 23493, 23560, 23627, 23694, 23427, 23494, 23561, 23628, 23695, 23428, 23495, 23562, 23629, 23696, 23429, 23496, 23563, 23630, 23697, 23430, 23497, 23564, 23631, 23698, 23431, 23498, 23565, 23632, 23699, 23432, 23499, 23566, 23633, 23700, 23433, 23500, 23567, 23634, 23701, 23434, 23501, 23568, 23635, 23702, 23435, 23502, 23569, 23636, 23703, 23436, 23503, 23570, 23637, 23704, 23437, 23504, 23571, 23638, 23705, 23438, 23505, 23572, 23639, 23706, 23439, 23506, 23573, 23640, 23707, 23440, 23507, 23574, 23641, 23708, 23441, 23508, 23575, 23642, 23709}, -- 110 + [slips.storages[31]] = L{23812, 23813, 23814, 23815, 23816, 23817, 23818, 23819, 23820, 23821, 23832, 23833, 23834, 23835, 23836}, -- 15 } function slips.get_slip_id(n) From ed0eb980b12a1af819b35585f4a8d0a4b42790aa Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Thu, 24 Aug 2023 23:45:07 +0200 Subject: [PATCH 0950/1002] [Slips lib] Forget to add slip 31 id Adding Slip 31 id --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 4ac34e8133..b428b3dab8 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -11,7 +11,7 @@ _libs.slips = slips slips.default_storages = {'inventory', 'safe', 'storage', 'locker', 'satchel', 'sack', 'case', 'wardrobe', 'safe2', 'wardrobe2', 'wardrobe3', 'wardrobe4', 'wardrobe5', 'wardrobe6', 'wardrobe7', 'wardrobe8'} -slips.storages = L{29312, 29313, 29314, 29315, 29316, 29317, 29318, 29319, 29320, 29321, 29322, 29323, 29324, 29325, 29326, 29327, 29328, 29329, 29330, 29331, 29332, 29333, 29334, 29335, 29336, 29337, 29338, 29339, 29340, 29341} +slips.storages = L{29312, 29313, 29314, 29315, 29316, 29317, 29318, 29319, 29320, 29321, 29322, 29323, 29324, 29325, 29326, 29327, 29328, 29329, 29330, 29331, 29332, 29333, 29334, 29335, 29336, 29337, 29338, 29339, 29340, 29341, 29342} slips.items = { [slips.storages[1]] = L{16084, 14546, 14961, 15625, 15711, 16085, 14547, 14962, 15626, 15712, 16086, 14548, 14963, 15627, 15713, 16087, 14549, 14964, 15628, 15714, 16088, 14550, 14965, 15629, 15715, 16089, 14551, 14966, 15630, 15716, 16090, 14552, 14967, 15631, 15717, 16091, 14553, 14968, 15632, 15718, 16092, 14554, 14969, 15633, 15719, 16093, 14555, 14970, 15634, 15720, 16094, 14556, 14971, 15635, 15721, 16095, 14557, 14972, 15636, 15722, 16096, 14558, 14973, 15637, 15723, 16097, 14559, 14974, 15638, 15724, 16098, 14560, 14975, 15639, 15725, 16099, 14561, 14976, 15640, 15726, 16100, 14562, 14977, 15641, 15727, 16101, 14563, 14978, 15642, 15728, 16102, 14564, 14979, 15643, 15729, 16103, 14565, 14980, 15644, 15730, 16106, 14568, 14983, 15647, 15733, 16107, 14569, 14984, 15648, 15734, 16108, 14570, 14985, 15649, 15735, 16602, 17741, 18425, 18491, 18588, 18717, 18718, 18850, 18943, 16069, 14530, 14940, 15609, 15695, 16062, 14525, 14933, 15604, 15688, 16064, 14527, 14935, 15606, 15690, 18685, 18065, 17851, 18686, 18025, 18435, 18113, 17951, 17715, 18485, 18408, 18365, 18583, 18417, 18388, 16267, 16268, 16269, 16228, 16229, 15911, 15799, 15800, 15990, 17745, 18121, 16117, 14577, 17857}, -- 168 [slips.storages[2]] = L{12421, 12549, 12677, 12805, 12933, 13911, 14370, 14061, 14283, 14163, 12429, 12557, 12685, 12813, 12941, 13924, 14371, 14816, 14296, 14175, 13934, 14387, 14821, 14303, 14184, 13935, 14388, 14822, 14304, 14185, 13876, 13787, 14006, 14247, 14123, 13877, 13788, 14007, 14248, 14124, 13908, 14367, 14058, 14280, 14160, 13909, 14368, 14059, 14281, 14161, 16113, 14573, 14995, 15655, 15740, 16115, 14575, 14997, 15657, 15742, 16114, 14574, 14996, 15656, 15741, 16116, 14576, 14998, 15658, 15743, 12818, 18198, 12946, 18043, 12690, 17659, 12296, 12434, 15471, 15472, 15473, 15508, 15509, 15510, 15511, 15512, 15513, 15514, 17710, 17595, 18397, 18360, 18222, 17948, 18100, 15475, 15476, 15477, 15488, 15961, 14815, 14812, 14813, 15244, 15240, 14488, 14905, 15576, 15661, 15241, 14489, 14906, 15577, 15662, 13927, 14378, 14076, 14308, 14180, 13928, 14379, 14077, 14309, 14181, 10438, 10276, 10320, 10326, 10367, 10439, 10277, 10321, 10327, 10368, 10440, 10278, 10322, 10328, 10369, 10441, 10279, 10323, 10329, 10370, 25734, 25735, 25736, 25737, 25738, 25739, 25740, 25741, 25742, 25743, 25744}, -- 155 From 00e34b84d14558e67f97605594c40b0d62de4741 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Fri, 8 Sep 2023 14:46:58 +0100 Subject: [PATCH 0951/1002] Added functionality to Itemizer (#2312) * Added functionality to Itemizer Significant changes to Itemizer: - added auto-stacking of the destination bag when moving partial stacks of stackable items, along with a setting for the functionality, and a manual argument to invoke it. - changed the previous fix to the recognition of high quality item names (ending in `+1`, `+2`, etc) to include any other non-digit character (i.e `#`) - changed help text to reflect the new functionality (and fixed capitalization) - changed all instances of `windower.add_to_chat()` to use `log()` instead, since it's using the `luau` library anyway - changed version-recognizing logic so that it recognizes changes in major and minor versions automatically without the need for hardcoded values - Adjusted version check so that it only fires when the user is logged in all the way and thus the chatlog is available to print the notice. - bumped version number I am, tentatively, not using the packets library for the stacking functionality, since it adds a good bit of overhead and there can be situations where the addon might be spamming stacking commands, especially when the //put commands are invoked via scripts - as it's common. On the other hand, the addon is already using item resources which is a lot of overhead on its own, so I am not sure if it would be better to use the packets lib as well at that point. I'm open to suggestions. --- addons/itemizer/itemizer.lua | 68 ++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 14 deletions(-) diff --git a/addons/itemizer/itemizer.lua b/addons/itemizer/itemizer.lua index f0006c2eea..4eb442ac2a 100644 --- a/addons/itemizer/itemizer.lua +++ b/addons/itemizer/itemizer.lua @@ -1,6 +1,6 @@ _addon.name = 'Itemizer' _addon.author = 'Ihina' -_addon.version = '3.0.1.4' +_addon.version = '3.1.0.0' _addon.command = 'itemizer' require('luau') @@ -8,8 +8,9 @@ require('luau') defaults = {} defaults.AutoNinjaTools = true defaults.AutoItems = true +defaults.AutoStack = true defaults.Delay = 0.5 -defaults.version = "3.0.1.1" +defaults.version = _addon.version defaults.UseUniversalTools = {} defaults.UseUniversalTools.Katon = false @@ -39,10 +40,16 @@ bag_ids = res.bags:key_map(string.gsub-{' ', ''} .. string.lower .. table.get-{' bag_ids.temporary = nil --Added this function for first load on new version. Because of the newly added features that weren't there before. -windower.register_event("load", function() - if settings.version == "3.0.1.1" then - windower.add_to_chat(207,"Itemizer v3.0.1.2: New features added. (use //itemizer help to find out about them)") - settings.version = "3.0.1.2" +windower.register_event("load", "login", function() + if not windower.ffxi.get_info().logged_in then + return + end + + local _, _, saved = settings.version:find("(%d+%.%d+%.)") + local _, _, current = _addon.version:find("(%d+%.%d+%.)") + if saved ~= current then + log("Itemizer v%s: New features added. (use //itemizer help to find out about them)":format(_addon.version)) + settings.version = _addon.version settings:save() end end) @@ -62,6 +69,7 @@ find_items = function(ids, bag, limit) bag = bag_index, slot = item.slot, count = count, + id = item.id, }) if limit then @@ -79,39 +87,60 @@ find_items = function(ids, bag, limit) return res, found end +stack = function(bag_id) + if not bag_id or type(bag_id) ~= 'number' or bag_id == 0 then + return + end + windower.packets.inject_outgoing(0x03A, string.char(0x3A, 0x1E, 0, 0, bag_id, 0, 0, 0)) +end + windower.register_event("addon command", function(command, arg2, ...) if command == 'help' then - local helptext = [[Itemizer - Command List:') + local helptext = [[Itemizer - Usage: + //get [bag] [count] -- //gets [bag] - Retrieves the specified item from the specified bag + //put [bag] [count] -- //puts [bag] - Places the specified item into the specified bag + //stack -- Stacks all stackable items in all currently available bags + Command List: 1. Delay - Sets the time delay. - 2. Autoninjatools - toggles Automatically getting ninja tools (Shortened ant) + 2. Autoninjatools - Toggles automatically getting ninja tools (Shortened ant) 3. Autoitems - Toggles automatically getting items from bags (shortened ai) - 4. Useuniversaltool - toggles using universal ninja tools for (shortened uut) + 4. Useuniversaltool - Toggles using universal ninja tools for (shortened uut) i.e. uut katon - will toggle katon either true or false depending on your setting all defaulted false. - 5. help --Shows this menu.]] + 5. Autostack - Toggles utomatically stacking items in the destination bag (shortened as, defaults true) + 6. help - Shows this menu.]] for _, line in ipairs(helptext:split('\n')) do - windower.add_to_chat(207, line) + log(line) end elseif command:lower() == "delay" and arg2 ~= nil then if type(arg2) == 'number' then settings.delay = arg2 settings:save() + log('Delay is now %s.':format(settings.delay)) else error('The delay must be a number') end elseif T{'autoninjatools','ant'}:contains(command:lower()) then settings.AutoNinjaTools = not settings.AutoNinjaTools settings:save() + log('AutoNinjaTools is now %s.':format(settings.AutoNinjaTools)) elseif T{'autoitems','ai'}:contains(command:lower()) then settings.AutoItems = not settings.AutoItems settings:save() + log('AutoItems is now %s.':format(settings.AutoItems)) elseif T{'useuniversaltool','uut'}:contains(command:lower()) then - if settings.UseUniversalTools[arg2:ucfirst()] ~= nil then - settings.UseUniversalTools[arg2:ucfirst()] = not settings.UseUniversalTools[arg2:ucfirst()] + local arg = arg2:ucfirst() + if settings.UseUniversalTools[arg] ~= nil then + settings.UseUniversalTools[arg] = not settings.UseUniversalTools[arg] settings:save() + log('UseUniversalTools for %s spells is now %s.':format(arg, settings.UseUniversalTools[arg])) else error('Argument 2 must be a ninjutsu spell (sans :ichi or :ni) i.e. uut katon') end + elseif T{'autostack','as'}:contains(command:lower()) then + settings.AutoStack = not settings.AutoStack + log('AutoStack is now %s.':format(settings.AutoStack)) + settings:save() end end) @@ -127,7 +156,7 @@ windower.register_event('unhandled command', function(command, ...) local last = args[#args] if last == 'all' then args:remove() - elseif tonumber(last) and not last:find('+') then + elseif not last:find('[^0-9]') then count = tonumber(last) args:remove() else @@ -185,6 +214,17 @@ windower.register_event('unhandled command', function(command, ...) for match in matches:it() do windower.ffxi[command .. '_item'](command == 'get' and match.bag or destination_bag, match.slot, match.count) + + if settings.AutoStack and command == 'put' and match.count < res.items[match.id].stack then + stack(destination_bag) + end + end + + elseif command == 'stack' then + log('Stacking items in all currently accessible bags.') + + for bag_index in bag_ids:filter(table.get-{'enabled'} .. windower.ffxi.get_bag_info):it() do + stack(bag_index) end end end) From 3198f1e995284461553bd91f7baa37128f32f4fd Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Fri, 8 Sep 2023 14:57:24 +0100 Subject: [PATCH 0952/1002] Bugfix after commit #2312 `log()` can translate booleans directly into strings whereas `string.format()` doesn't. --- addons/itemizer/itemizer.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/itemizer/itemizer.lua b/addons/itemizer/itemizer.lua index 4eb442ac2a..794267fb9b 100644 --- a/addons/itemizer/itemizer.lua +++ b/addons/itemizer/itemizer.lua @@ -123,23 +123,23 @@ windower.register_event("addon command", function(command, arg2, ...) elseif T{'autoninjatools','ant'}:contains(command:lower()) then settings.AutoNinjaTools = not settings.AutoNinjaTools settings:save() - log('AutoNinjaTools is now %s.':format(settings.AutoNinjaTools)) + log('AutoNinjaTools is now', settings.AutoNinjaTools) elseif T{'autoitems','ai'}:contains(command:lower()) then settings.AutoItems = not settings.AutoItems settings:save() - log('AutoItems is now %s.':format(settings.AutoItems)) + log('AutoItems is now', settings.AutoItems) elseif T{'useuniversaltool','uut'}:contains(command:lower()) then local arg = arg2:ucfirst() if settings.UseUniversalTools[arg] ~= nil then settings.UseUniversalTools[arg] = not settings.UseUniversalTools[arg] settings:save() - log('UseUniversalTools for %s spells is now %s.':format(arg, settings.UseUniversalTools[arg])) + log('UseUniversalTools for %s spells is now':format(arg), settings.UseUniversalTools[arg]) else error('Argument 2 must be a ninjutsu spell (sans :ichi or :ni) i.e. uut katon') end elseif T{'autostack','as'}:contains(command:lower()) then settings.AutoStack = not settings.AutoStack - log('AutoStack is now %s.':format(settings.AutoStack)) + log('AutoStack is now', settings.AutoStack) settings:save() end end) From 0f67dd051281153b59d10e7d82795e7bc8927470 Mon Sep 17 00:00:00 2001 From: Byrth Date: Mon, 11 Sep 2023 11:00:54 -0400 Subject: [PATCH 0953/1002] add user_pcall variant that doesn't throw --- addons/GearSwap/flow.lua | 23 ++++++++++++++++++++++- addons/GearSwap/refresh.lua | 2 +- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/addons/GearSwap/flow.lua b/addons/GearSwap/flow.lua index dcc3459b33..0542479fea 100644 --- a/addons/GearSwap/flow.lua +++ b/addons/GearSwap/flow.lua @@ -306,7 +306,7 @@ end ----------------------------------------------------------------------------------- ---Name: user_pcall(str,val1,val2,exit_funct) +--Name: user_pcall(str,...) --Desc: Calls a user function, if it exists. If not, throws an error. --Args: ---- str - Function's key in user_env. @@ -326,6 +326,27 @@ function user_pcall(str,...) end +----------------------------------------------------------------------------------- +--Name: user_pcall2(str,...) +--Desc: Calls a user function, if it exists. If not, prints an error and continues. +--Args: +---- str - Function's key in user_env. +----------------------------------------------------------------------------------- +--Returns: +---- none +----------------------------------------------------------------------------------- +function user_pcall2(str,...) + if user_env then + if type(user_env[str]) == 'function' then + bool,err = pcall(user_env[str],...) + if not bool then print('\nGearSwap has detected an error in the user function '..str..':\n'..err) end + elseif user_env[str] then + msg.addon_msg(123,windower.to_shift_jis(tostring(str))..'() exists but is not a function') + end + end +end + + ----------------------------------------------------------------------------------- --Name: pretarget_delayed_cast(ts) --Desc: Triggers an outgoing action packet (if the passed key is valid). diff --git a/addons/GearSwap/refresh.lua b/addons/GearSwap/refresh.lua index 18040d1824..0242cf6622 100644 --- a/addons/GearSwap/refresh.lua +++ b/addons/GearSwap/refresh.lua @@ -63,7 +63,7 @@ function load_user_files(job_id,user_file) job_id = tonumber(job_id) if current_file then - user_pcall('file_unload',current_file) + user_pcall2('file_unload',current_file) end for i in pairs(registered_user_events) do From 88f33c755326ded0e96544d0babe7f27e64b93e5 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Mon, 11 Sep 2023 22:43:31 +0200 Subject: [PATCH 0954/1002] [Slips] September 11th, 2023 FFXI Update Added items from the September 11th. 2023 FFXI Update. --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index b428b3dab8..455a59eb99 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757, 25909}, -- 192 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912, 3753, 23806, 3754, 23810, 23811, 3755, 26496, 26497, 21786, 21787, 21996, 21997, 23802, 25777, 25778}, -- 173 SE Skipped an index hence the 0 as one of the items + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912, 3753, 23806, 3754, 23810, 23811, 3755, 26496, 26497, 21786, 21787, 21996, 21997, 23802, 25777, 25778, 21933, 21934}, -- 175 SE Skipped an index hence the 0 as one of the items [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067, 21680, 22071}, -- 177 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, -- 115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, -- 115 From 404db46b8b2d850b2216b8d089707e81bdb319bf Mon Sep 17 00:00:00 2001 From: eLii Date: Thu, 14 Sep 2023 07:11:00 -0500 Subject: [PATCH 0955/1002] Addon: Shortcuts If a user attempts to use the default in-game item command, shortcuts attempts to cast a spell if the spell and item name are the same. Block shortcuts from finishing command logic if it detects default item command method. --- addons/shortcuts/shortcuts.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/addons/shortcuts/shortcuts.lua b/addons/shortcuts/shortcuts.lua index a2f5da526e..ba71c73ef5 100644 --- a/addons/shortcuts/shortcuts.lua +++ b/addons/shortcuts/shortcuts.lua @@ -218,6 +218,11 @@ function command_logic(original,modified) potential_targ = splitline[splitline.n] end local a,b,spell = string.find(original,'"(.-)"') + + -- If user is attempting to use the default item command stop. + if original:match("item [\"\'][%a\':-.]+[\"\'] [<][%a]+[>]") then + return false + end if unhandled_list[command] then return modified,true @@ -406,4 +411,4 @@ function interp_text(splitline,offset,modified) end lastsent = '' return modified,false -end \ No newline at end of file +end From 86a3feee695705ce1866562c60bce2697cae0af0 Mon Sep 17 00:00:00 2001 From: eLii Date: Thu, 14 Sep 2023 07:37:31 -0500 Subject: [PATCH 0956/1002] Addon: Shortcuts. Adjusted the pattern, and forgot to add a space pattern check for item names with spaces. --- addons/shortcuts/shortcuts.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/shortcuts/shortcuts.lua b/addons/shortcuts/shortcuts.lua index ba71c73ef5..47b2d374ce 100644 --- a/addons/shortcuts/shortcuts.lua +++ b/addons/shortcuts/shortcuts.lua @@ -220,7 +220,7 @@ function command_logic(original,modified) local a,b,spell = string.find(original,'"(.-)"') -- If user is attempting to use the default item command stop. - if original:match("item [\"\'][%a\':-.]+[\"\'] [<][%a]+[>]") then + if original:match("item [\"\'][%a%s\':-.]+[\"\'] .+") then return false end From 772fc292603368168a24ce13e02734f19ada0845 Mon Sep 17 00:00:00 2001 From: eLii Date: Thu, 14 Sep 2023 17:19:43 -0500 Subject: [PATCH 0957/1002] Addon: Shortcuts Revert earlier commits. --- addons/shortcuts/shortcuts.lua | 5 ----- 1 file changed, 5 deletions(-) diff --git a/addons/shortcuts/shortcuts.lua b/addons/shortcuts/shortcuts.lua index 47b2d374ce..0b13b1ef7d 100644 --- a/addons/shortcuts/shortcuts.lua +++ b/addons/shortcuts/shortcuts.lua @@ -218,11 +218,6 @@ function command_logic(original,modified) potential_targ = splitline[splitline.n] end local a,b,spell = string.find(original,'"(.-)"') - - -- If user is attempting to use the default item command stop. - if original:match("item [\"\'][%a%s\':-.]+[\"\'] .+") then - return false - end if unhandled_list[command] then return modified,true From 41e90b8c52502afcf74b2db2a113af193fe7c95f Mon Sep 17 00:00:00 2001 From: eLii Date: Thu, 14 Sep 2023 17:20:49 -0500 Subject: [PATCH 0958/1002] Addons: Shortcuts [ statics.lua ] Add /item to unhandled command list. --- addons/shortcuts/statics.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/shortcuts/statics.lua b/addons/shortcuts/statics.lua index 50f06af57d..9c8e961613 100644 --- a/addons/shortcuts/statics.lua +++ b/addons/shortcuts/statics.lua @@ -160,7 +160,7 @@ command2_list = { ['bstpet']=new_cmd_entry(No_targets,{['1']=BST_targets,['2']=BST_targets,['3']=BST_targets,['4']=BST_targets,['5']=BST_targets,['6']=BST_targets,['7']=BST_targets}), } -unhandled_list = {['p']=true,['s']=true,['sh']=true,['yell']=true,['echo']=true,['t']=true,['l']=true,['breaklinkshell']=true} +unhandled_list = {['p']=true,['s']=true,['sh']=true,['yell']=true,['echo']=true,['t']=true,['l']=true,['breaklinkshell']=true,['item']=true} -- List of commands to be ignored ignore_list = {['equip']=true,['raw']=true,['fish']=true,['dig']=true,['range']=true,['map']=true,['hide']=true,['jump']=true,['attackoff']=true,['quest']=true,['recruitlist']=true,['rlist']=true,['statustimer']=true,['recycle']=true} @@ -207,4 +207,4 @@ validabils_it('spells') validabils_it('job_abilities') validabils_it('weapon_skills') validabils_it('monster_skills') -validabils_it('mounts') \ No newline at end of file +validabils_it('mounts') From eba4a8867f907f6ed5a7a3f2aa17c24fa329dad3 Mon Sep 17 00:00:00 2001 From: nmarigoni Date: Sat, 7 Oct 2023 04:04:57 -0600 Subject: [PATCH 0959/1002] [barfiller] Fix EXP rate calculation (#2319) * Update statics.lua Updated to use current time (os.time() ) rather than seconds of CPU time (os.clock() ) to calculate elapsed time. Added msg 253 to parsing to capture EXP awarded from EXP chains. * Update barfiller.lua Update to use current time rather than CPU seconds --- addons/barfiller/barfiller.lua | 2 +- addons/barfiller/statics.lua | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/addons/barfiller/barfiller.lua b/addons/barfiller/barfiller.lua index 2a67a06f31..b941a1f9eb 100644 --- a/addons/barfiller/barfiller.lua +++ b/addons/barfiller/barfiller.lua @@ -120,7 +120,7 @@ windower.register_event('prerender',function() foreground_image:size(x, settings.Images.Foreground.Size.Height) if debug then print(old_width, x, new_width) end - local now = os.clock() + local now = os.time() if now - last_update > 0.5 then update_strings() last_update = now diff --git a/addons/barfiller/statics.lua b/addons/barfiller/statics.lua index f15aa8b331..624609c85a 100644 --- a/addons/barfiller/statics.lua +++ b/addons/barfiller/statics.lua @@ -234,8 +234,8 @@ function display_help() end function exp_msg(val,msg) - local t = os.clock() - if msg == 8 or msg == 105 then + local t = os.time() + if msg == 8 or msg == 105 or msg == 253 then xp.registry[t] = (xp.registry[t] or 0) + val xp.current = math.min(xp.current + val,55999) if xp.current > xp.tnl then @@ -246,12 +246,12 @@ function exp_msg(val,msg) end function analyze_points_table(tab) - local t = os.clock() + local t = os.time() local running_total = 0 - local maximum_timestamp = 29 + local maximum_timestamp = 0 for ts,points in pairs(tab) do local time_diff = t - ts - if t - ts > 600 then + if time_diff > 600 then tab[ts] = nil else running_total = running_total + points @@ -262,7 +262,7 @@ function analyze_points_table(tab) end local rate - if maximum_timestamp == 29 then + if maximum_timestamp < 30 then rate = 0 else rate = math.floor((running_total/maximum_timestamp)*3600) From bdef1b4445037138348fc4dd6a5e6ad5bb1a52cb Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Tue, 10 Oct 2023 16:45:54 +0200 Subject: [PATCH 0960/1002] [Slips] October 10th, 2023 FFXI Update Added items from the September 11th. 2023 FFXI Update. --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 455a59eb99..fa05217b97 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757, 25909}, -- 192 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912, 3753, 23806, 3754, 23810, 23811, 3755, 26496, 26497, 21786, 21787, 21996, 21997, 23802, 25777, 25778, 21933, 21934}, -- 175 SE Skipped an index hence the 0 as one of the items + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912, 3753, 23806, 3754, 23810, 23811, 3755, 26496, 26497, 21786, 21787, 21996, 21997, 23802, 25777, 25778, 21933, 21934, 21993, 21994}, -- 177 SE Skipped an index hence the 0 as one of the items [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067, 21680, 22071}, -- 177 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, -- 115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, -- 115 From 147e79be98fe01564f4fe2613ed48f1e68e363f9 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Mon, 23 Oct 2023 22:33:56 -0600 Subject: [PATCH 0961/1002] Update chat.icons Add Mentor Flags and Information icon --- addons/libs/chat/icons.lua | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/addons/libs/chat/icons.lua b/addons/libs/chat/icons.lua index 6e7c57150b..32428992c8 100644 --- a/addons/libs/chat/icons.lua +++ b/addons/libs/chat/icons.lua @@ -16,4 +16,35 @@ return { non = string.char(0xEF, 0x2C), -- OFF sign (French) ein = string.char(0xEF, 0x2D), -- ON sign (German) aus = string.char(0xEF, 0x2E), -- OFF sign (German) + bronze1 = string.char(0xEF, 0x2F), -- Mentor Rank Flag Bronze 1 + bronze2 = string.char(0xEF, 0x30), -- Mentor Rank Flag Bronze 2 + bronze3 = string.char(0xEF, 0x31), -- Mentor Rank Flag Bronze 3 + bronze4 = string.char(0xEF, 0x32), -- Mentor Rank Flag Bronze 4 + bronze5 = string.char(0xEF, 0x33), -- Mentor Rank Flag Bronze 5 + bronze6 = string.char(0xEF, 0x34), -- Mentor Rank Flag Bronze 6 + bronze7 = string.char(0xEF, 0x35), -- Mentor Rank Flag Bronze 7 + bronze8 = string.char(0xEF, 0x36), -- Mentor Rank Flag Bronze 8 + bronze9 = string.char(0xEF, 0x37), -- Mentor Rank Flag Bronze 9 + bronze10 = string.char(0xEF, 0x38), -- Mentor Rank Flag Bronze 10 + silver1 = string.char(0xEF, 0x39), -- Mentor Rank Flag Silver 1 + silver2 = string.char(0xEF, 0x3A), -- Mentor Rank Flag Silver 2 + silver3 = string.char(0xEF, 0x3B), -- Mentor Rank Flag Silver 3 + silver4 = string.char(0xEF, 0x3C), -- Mentor Rank Flag Silver 4 + silver5 = string.char(0xEF, 0x3D), -- Mentor Rank Flag Silver 5 + silver6 = string.char(0xEF, 0x3E), -- Mentor Rank Flag Silver 6 + silver7 = string.char(0xEF, 0x3F), -- Mentor Rank Flag Silver 7 + silver8 = string.char(0xEF, 0x40), -- Mentor Rank Flag Silver 8 + silver9 = string.char(0xEF, 0x41), -- Mentor Rank Flag Silver 9 + silver10 = string.char(0xEF, 0x42), -- Mentor Rank Flag Silver 10 + gold1 = string.char(0xEF, 0x43), -- Mentor Rank Flag Gold 1 + gold2 = string.char(0xEF, 0x44), -- Mentor Rank Flag Gold 2 + gold3 = string.char(0xEF, 0x45), -- Mentor Rank Flag Gold 3 + gold4 = string.char(0xEF, 0x46), -- Mentor Rank Flag Gold 4 + gold5 = string.char(0xEF, 0x47), -- Mentor Rank Flag Gold 5 + gold6 = string.char(0xEF, 0x48), -- Mentor Rank Flag Gold 6 + gold7 = string.char(0xEF, 0x49), -- Mentor Rank Flag Gold 7 + gold8 = string.char(0xEF, 0x4A), -- Mentor Rank Flag Gold 8 + gold9 = string.char(0xEF, 0x4B), -- Mentor Rank Flag Gold 9 + gold10 = string.char(0xEF, 0x4C), -- Mentor Rank Flag Gold 10 + info = string.char(0xEF, 0x4D), -- Information Icon (Blue) } From 5cb8aae7e6ead88c280309e24cc9429f49b1848e Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Tue, 14 Nov 2023 09:45:13 -0700 Subject: [PATCH 0962/1002] [boxdestroyer] Update messages.lua --- addons/boxdestroyer/messages.lua | 120 +++++++++++++++---------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/addons/boxdestroyer/messages.lua b/addons/boxdestroyer/messages.lua index 4a2708d859..ce99d127bd 100644 --- a/addons/boxdestroyer/messages.lua +++ b/addons/boxdestroyer/messages.lua @@ -1,63 +1,63 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination" for the associated zone IDs - [100] = 8067, - [101] = 7516, - [102] = 7917, - [103] = 8092, - [104] = 8657, - [105] = 7708, - [106] = 8082, - [107] = 7544, - [108] = 7612, - [109] = 8475, - [110] = 7599, - [111] = 8576, - [112] = 8178, - [113] = 7939, - [114] = 7777, - [115] = 7873, - [116] = 7570, - [117] = 7576, - [118] = 8118, - [119] = 8355, - [120] = 7515, - [121] = 8095, - [122] = 7445, - [123] = 7878, - [124] = 7829, - [125] = 7646, - [126] = 8062, - [127] = 7362, - [128] = 7517, - [130] = 7581, - [153] = 11407, - [157] = 7387, - [158] = 7393, - [159] = 8456, - [160] = 7420, - [166] = 10589, - [167] = 10603, - [169] = 7550, - [172] = 7423, - [173] = 10528, - [174] = 11406, - [176] = 7615, - [177] = 11230, - [178] = 11410, - [184] = 8640, - [190] = 8264, - [191] = 8384, - [192] = 7420, - [193] = 8396, - [194] = 8276, - [195] = 7607, - [196] = 8316, - [197] = 7361, - [198] = 8282, - [200] = 7538, - [204] = 7526, - [205] = 11493, - [208] = 8295, - [212] = 10649, - [213] = 10459, + [100] = 8068, + [101] = 7517, + [102] = 7918, + [103] = 8093, + [104] = 8658, + [105] = 7709, + [106] = 8083, + [107] = 7545, + [108] = 7613, + [109] = 8476, + [110] = 7600, + [111] = 8577, + [112] = 8179, + [113] = 7940, + [114] = 7778, + [115] = 7874, + [116] = 7571, + [117] = 7577, + [118] = 8119, + [119] = 8356, + [120] = 7516, + [121] = 8096, + [122] = 7446, + [123] = 7879, + [124] = 7830, + [125] = 7647, + [126] = 8063, + [127] = 7363, + [128] = 7518, + [130] = 7582, + [153] = 11408, + [157] = 7388, + [158] = 7394, + [159] = 8457, + [160] = 7421, + [166] = 10590, + [167] = 10604, + [169] = 7551, + [172] = 7424, + [173] = 10529, + [174] = 11407, + [176] = 7616, + [177] = 11231, + [178] = 11411, + [184] = 8641, + [190] = 8265, + [191] = 8385, + [192] = 7421, + [193] = 8397, + [194] = 8277, + [195] = 7608, + [196] = 8317, + [197] = 7362, + [198] = 8283, + [200] = 7539, + [204] = 7527, + [205] = 11494, + [208] = 8296, + [212] = 10650, + [213] = 10460, } offsets = {greater_less=1, failure=2, success=4, second_even_odd=5, first_even_odd=6, range=7, less=8, greater=9, equal=10, second_multiple=11, first_multiple=12, tool_failure=13} From c8f6714e4b7f709d1ad480f0c3aef26171aa904d Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Mon, 11 Dec 2023 11:57:50 -0700 Subject: [PATCH 0963/1002] [JobChange] allow for uppercase in commands --- addons/JobChange/jobchange.lua | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/addons/JobChange/jobchange.lua b/addons/JobChange/jobchange.lua index 81e6ff52d8..2825e75645 100644 --- a/addons/JobChange/jobchange.lua +++ b/addons/JobChange/jobchange.lua @@ -118,11 +118,14 @@ local find_job_change_npc = function() end windower.register_event('addon command', function(command, ...) + command = command:lower() local p = windower.ffxi.get_player() local args = L{...} - local job = '' + local job = nil if args[1] then job = args[1]:lower() + else + job = command end local main = nil local sub = nil @@ -136,8 +139,8 @@ windower.register_event('addon command', function(command, ...) log('Resetting Job') sub = p.sub_job:lower() elseif command:contains('/') or command:contains('\\') then - command = command:gsub('\\','/') - local js = command:split('/') + job = job:gsub('\\','/') + local js = job:split('/') main = (js[1] ~= '' and js[1] or nil) sub = (js[2] ~= '' and js[2] or nil) -- remove identicals. From 6d4b8d1a591630ddf1ae219c510a2b11bf765e3a Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Mon, 11 Dec 2023 22:14:06 -0700 Subject: [PATCH 0964/1002] [boxdestroyer] Update messages.lua --- addons/boxdestroyer/messages.lua | 48 ++++++++++++++++---------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/addons/boxdestroyer/messages.lua b/addons/boxdestroyer/messages.lua index ce99d127bd..a77a132db1 100644 --- a/addons/boxdestroyer/messages.lua +++ b/addons/boxdestroyer/messages.lua @@ -1,31 +1,31 @@ messages = { -- These dialogue IDs match "You were unable to enter a combination" for the associated zone IDs - [100] = 8068, + [100] = 8069, [101] = 7517, - [102] = 7918, - [103] = 8093, - [104] = 8658, - [105] = 7709, - [106] = 8083, - [107] = 7545, - [108] = 7613, - [109] = 8476, - [110] = 7600, - [111] = 8577, - [112] = 8179, + [102] = 7919, + [103] = 8094, + [104] = 8659, + [105] = 7710, + [106] = 8084, + [107] = 7546, + [108] = 7614, + [109] = 8477, + [110] = 7601, + [111] = 8578, + [112] = 8180, [113] = 7940, - [114] = 7778, - [115] = 7874, - [116] = 7571, - [117] = 7577, - [118] = 8119, - [119] = 8356, - [120] = 7516, - [121] = 8096, + [114] = 7779, + [115] = 7875, + [116] = 7572, + [117] = 7578, + [118] = 8120, + [119] = 8357, + [120] = 7517, + [121] = 8097, [122] = 7446, - [123] = 7879, - [124] = 7830, - [125] = 7647, - [126] = 8063, + [123] = 7880, + [124] = 7831, + [125] = 7648, + [126] = 8064, [127] = 7363, [128] = 7518, [130] = 7582, From 99a6c0568081229e81921f644be2dd4505070463 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Mon, 11 Dec 2023 22:15:56 -0700 Subject: [PATCH 0965/1002] [JobChange] remove unnecessary repeated lower() calls --- addons/JobChange/jobchange.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/JobChange/jobchange.lua b/addons/JobChange/jobchange.lua index 2825e75645..3bdb31ca40 100644 --- a/addons/JobChange/jobchange.lua +++ b/addons/JobChange/jobchange.lua @@ -132,10 +132,10 @@ windower.register_event('addon command', function(command, ...) if command:lower() == 'main' then main = job if main and main:upper() == p.main_job then main = nil end - elseif command:lower() == 'sub' then + elseif command == 'sub' then sub = job if sub and sub:upper() == p.sub_job then main = nil end - elseif command:lower() == 'reset' then + elseif command == 'reset' then log('Resetting Job') sub = p.sub_job:lower() elseif command:contains('/') or command:contains('\\') then @@ -147,7 +147,7 @@ windower.register_event('addon command', function(command, ...) if main and main:upper() == p.main_job then main = nil end if sub and sub:upper() == p.sub_job then sub = nil end elseif command ~= nil and command ~= '' then - main = command:lower() + main = command if main and main:upper() == p.main_job then main = nil end else log('Syntax: //jc main|sub JOB -- Chnages main or sub to target JOB') From 96112df38b144e9611c9aa4eb29a3086e540a575 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Mon, 11 Dec 2023 22:16:54 -0700 Subject: [PATCH 0966/1002] [JobChange] remove unnecessary repeated lower() calls --- addons/JobChange/jobchange.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/JobChange/jobchange.lua b/addons/JobChange/jobchange.lua index 3bdb31ca40..d74c728b50 100644 --- a/addons/JobChange/jobchange.lua +++ b/addons/JobChange/jobchange.lua @@ -129,7 +129,7 @@ windower.register_event('addon command', function(command, ...) end local main = nil local sub = nil - if command:lower() == 'main' then + if command == 'main' then main = job if main and main:upper() == p.main_job then main = nil end elseif command == 'sub' then From 2d9c8b9081faddabbba01d6b1923d7f717cdc092 Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Fri, 22 Dec 2023 17:06:20 +0100 Subject: [PATCH 0967/1002] [Slips] Swapping wrong item order Swapping order for hunter's braccae and socks. --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index fa05217b97..49c6fcebe4 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -16,7 +16,7 @@ slips.items = { [slips.storages[1]] = L{16084, 14546, 14961, 15625, 15711, 16085, 14547, 14962, 15626, 15712, 16086, 14548, 14963, 15627, 15713, 16087, 14549, 14964, 15628, 15714, 16088, 14550, 14965, 15629, 15715, 16089, 14551, 14966, 15630, 15716, 16090, 14552, 14967, 15631, 15717, 16091, 14553, 14968, 15632, 15718, 16092, 14554, 14969, 15633, 15719, 16093, 14555, 14970, 15634, 15720, 16094, 14556, 14971, 15635, 15721, 16095, 14557, 14972, 15636, 15722, 16096, 14558, 14973, 15637, 15723, 16097, 14559, 14974, 15638, 15724, 16098, 14560, 14975, 15639, 15725, 16099, 14561, 14976, 15640, 15726, 16100, 14562, 14977, 15641, 15727, 16101, 14563, 14978, 15642, 15728, 16102, 14564, 14979, 15643, 15729, 16103, 14565, 14980, 15644, 15730, 16106, 14568, 14983, 15647, 15733, 16107, 14569, 14984, 15648, 15734, 16108, 14570, 14985, 15649, 15735, 16602, 17741, 18425, 18491, 18588, 18717, 18718, 18850, 18943, 16069, 14530, 14940, 15609, 15695, 16062, 14525, 14933, 15604, 15688, 16064, 14527, 14935, 15606, 15690, 18685, 18065, 17851, 18686, 18025, 18435, 18113, 17951, 17715, 18485, 18408, 18365, 18583, 18417, 18388, 16267, 16268, 16269, 16228, 16229, 15911, 15799, 15800, 15990, 17745, 18121, 16117, 14577, 17857}, -- 168 [slips.storages[2]] = L{12421, 12549, 12677, 12805, 12933, 13911, 14370, 14061, 14283, 14163, 12429, 12557, 12685, 12813, 12941, 13924, 14371, 14816, 14296, 14175, 13934, 14387, 14821, 14303, 14184, 13935, 14388, 14822, 14304, 14185, 13876, 13787, 14006, 14247, 14123, 13877, 13788, 14007, 14248, 14124, 13908, 14367, 14058, 14280, 14160, 13909, 14368, 14059, 14281, 14161, 16113, 14573, 14995, 15655, 15740, 16115, 14575, 14997, 15657, 15742, 16114, 14574, 14996, 15656, 15741, 16116, 14576, 14998, 15658, 15743, 12818, 18198, 12946, 18043, 12690, 17659, 12296, 12434, 15471, 15472, 15473, 15508, 15509, 15510, 15511, 15512, 15513, 15514, 17710, 17595, 18397, 18360, 18222, 17948, 18100, 15475, 15476, 15477, 15488, 15961, 14815, 14812, 14813, 15244, 15240, 14488, 14905, 15576, 15661, 15241, 14489, 14906, 15577, 15662, 13927, 14378, 14076, 14308, 14180, 13928, 14379, 14077, 14309, 14181, 10438, 10276, 10320, 10326, 10367, 10439, 10277, 10321, 10327, 10368, 10440, 10278, 10322, 10328, 10369, 10441, 10279, 10323, 10329, 10370, 25734, 25735, 25736, 25737, 25738, 25739, 25740, 25741, 25742, 25743, 25744}, -- 155 [slips.storages[3]] = L{16155, 11282, 15021, 16341, 11376, 16156, 11283, 15022, 16342, 11377, 16157, 11284, 15023, 16343, 11378, 16148, 14590, 15011, 16317, 15757, 16143, 14591, 15012, 16318, 15758, 16146, 14588, 15009, 16315, 15755, 16147, 14589, 15010, 16316, 15756, 15966, 15967, 19041, 17684, 17685, 11636, 15844, 15934, 16258, 18735, 18734, 16291, 16292, 19042, 15935, 16293, 16294, 15936, 18618, 11588, 11545, 16158, 16159, 16160, 16149, 14583, 15007, 16314, 15751, 16141, 14581, 15005, 16312, 15749, 16142, 14582, 15006, 16313, 15750, 10876, 10450, 10500, 11969, 10600, 10877, 10451, 10501, 11970, 10601, 10878, 10452, 10502, 11971, 10602, 19132, 18551, 11798, 11362, 11363, 11625, 15959, 16259, 22299, 26414, 21623, 26219, 21886, 23792, 23793, 23794, 23795, 23796, 22032, 22043, 21530, 22044, 26273, 25415, 25416, 25414, 22050, 22302, 26365, 26366, 23862, 23863, 23864, 23865, 21536}, -- 124 - [slips.storages[4]] = L{12511, 12638, 13961, 14214, 14089, 12512, 12639, 13962, 14215, 14090, 13855, 12640, 13963, 14216, 14091, 13856, 12641, 13964, 14217, 14092, 12513, 12642, 13965, 14218, 14093, 12514, 12643, 13966, 14219, 14094, 12515, 12644, 13967, 14220, 14095, 12516, 12645, 13968, 14221, 14096, 12517, 12646, 13969, 14222, 14097, 13857, 12647, 13970, 14223, 14098, 12518, 12648, 13971, 14099, 14224, 13868, 13781, 13972, 14225, 14100, 13869, 13782, 13973, 14226, 14101, 12519, 12649, 13974, 14227, 14102, 12520, 12650, 13975, 14228, 14103, 15265, 14521, 14928, 15600, 15684, 15266, 14522, 14929, 15601, 15685, 15267, 14523, 14930, 15602, 15686, 16138, 14578, 15002, 15659, 15746, 16139, 14579, 15003, 15660, 15747, 16140, 14580, 15004, 16311, 15748, 16678, 17478, 17422, 17423, 16829, 16764, 17643, 16798, 16680, 16766, 17188, 17812, 17771, 17772, 16887, 17532, 17717, 18702, 17858, 19203, 21461, 21124, 20776, 27786, 27926, 28066, 28206, 28346, 27787, 27927, 28067, 28207, 28347}, -- 138 + [slips.storages[4]] = L{12511, 12638, 13961, 14214, 14089, 12512, 12639, 13962, 14215, 14090, 13855, 12640, 13963, 14216, 14091, 13856, 12641, 13964, 14217, 14092, 12513, 12642, 13965, 14218, 14093, 12514, 12643, 13966, 14219, 14094, 12515, 12644, 13967, 14220, 14095, 12516, 12645, 13968, 14221, 14096, 12517, 12646, 13969, 14222, 14097, 13857, 12647, 13970, 14223, 14098, 12518, 12648, 13971, 14224, 14099, 13868, 13781, 13972, 14225, 14100, 13869, 13782, 13973, 14226, 14101, 12519, 12649, 13974, 14227, 14102, 12520, 12650, 13975, 14228, 14103, 15265, 14521, 14928, 15600, 15684, 15266, 14522, 14929, 15601, 15685, 15267, 14523, 14930, 15602, 15686, 16138, 14578, 15002, 15659, 15746, 16139, 14579, 15003, 15660, 15747, 16140, 14580, 15004, 16311, 15748, 16678, 17478, 17422, 17423, 16829, 16764, 17643, 16798, 16680, 16766, 17188, 17812, 17771, 17772, 16887, 17532, 17717, 18702, 17858, 19203, 21461, 21124, 20776, 27786, 27926, 28066, 28206, 28346, 27787, 27927, 28067, 28207, 28347}, -- 138 [slips.storages[5]] = L{15225, 14473, 14890, 15561, 15352, 15226, 14474, 14891, 15562, 15353, 15227, 14475, 14892, 15563, 15354, 15228, 14476, 14893, 15564, 15355, 15229, 14477, 14894, 15565, 15356, 15230, 14478, 14895, 15566, 15357, 15231, 14479, 14896, 15567, 15358, 15232, 14480, 14897, 15568, 15359, 15233, 14481, 14898, 15569, 15360, 15234, 14482, 14899, 15570, 15361, 15235, 14483, 14900, 15362, 15571, 15236, 14484, 14901, 15572, 15363, 15237, 14485, 14902, 15573, 15364, 15238, 14486, 14903, 15574, 15365, 15239, 14487, 14904, 15575, 15366, 11464, 11291, 15024, 16345, 11381, 11467, 11294, 15027, 16348, 11384, 11470, 11297, 15030, 16351, 11387, 11475, 11302, 15035, 16357, 11393, 11476, 11303, 15036, 16358, 11394, 11477, 11304, 15037, 16359, 11395}, -- 105 [slips.storages[6]] = L{15072, 15087, 15102, 15117, 15132, 15871, 15073, 15088, 15103, 15118, 15133, 15478, 15074, 15089, 15104, 15119, 15134, 15872, 15075, 15090, 15105, 15120, 15135, 15874, 15076, 15091, 15106, 15121, 15136, 15873, 15077, 15092, 15107, 15122, 15137, 15480, 15078, 15093, 15108, 15123, 15138, 15481, 15079, 15094, 15109, 15124, 15139, 15479, 15080, 15095, 15110, 15125, 15140, 15875, 15081, 15096, 15111, 15126, 15141, 15482, 15082, 15097, 15112, 15127, 15142, 15876, 15083, 15098, 15113, 15128, 15143, 15879, 15084, 15099, 15114, 15129, 15144, 15877, 15085, 15100, 15115, 15130, 15145, 15878, 15086, 15101, 15116, 15131, 15146, 15484, 11465, 11292, 15025, 16346, 11382, 16244, 11468, 11295, 15028, 16349, 11385, 15920, 11471, 11298, 15031, 16352, 11388, 16245, 11478, 11305, 15038, 16360, 11396, 16248, 11480, 11307, 15040, 16362, 11398, 15925}, -- 120 [slips.storages[7]] = L{15245, 14500, 14909, 15580, 15665, 15246, 14501, 14910, 15581, 15666, 15247, 14502, 14911, 15582, 15667, 15248, 14503, 14912, 15583, 15668, 15249, 14504, 14913, 15584, 15669, 15250, 14505, 14914, 15585, 15670, 15251, 14506, 14915, 15586, 15671, 15252, 14507, 14916, 15587, 15672, 15253, 14508, 14917, 15588, 15673, 15254, 14509, 14918, 15589, 15674, 15255, 14510, 14919, 15590, 15675, 15256, 14511, 14920, 15591, 15676, 15257, 14512, 14921, 15592, 15677, 15258, 14513, 14922, 15593, 15678, 15259, 14514, 14923, 15594, 15679, 11466, 11293, 15026, 16347, 11383, 11469, 11296, 15029, 16350, 11386, 11472, 11299, 15032, 16353, 11389, 11479, 11306, 15039, 16361, 11397, 11481, 11308, 15041, 16363, 11399}, -- 100 From 0e160ca2a8c1d92e65e5ef9370975997de556e25 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Thu, 18 Jan 2024 20:55:16 -0700 Subject: [PATCH 0968/1002] [SpellCheck] Update SpellExceptions.lua the id for Tonko: San -- an unlearnable spell -- was replaced by Siren --- addons/SpellCheck/SpellExceptions.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/SpellCheck/SpellExceptions.lua b/addons/SpellCheck/SpellExceptions.lua index 7db8f265fe..62f87c443c 100644 --- a/addons/SpellCheck/SpellExceptions.lua +++ b/addons/SpellCheck/SpellExceptions.lua @@ -17,7 +17,6 @@ spell_exceptions = { [351] = {id=351,en="Dokumori: Ni",ja="毒盛の術:弐"}, [342] = {id=342,en="Jubaku: Ni",ja="呪縛の術:弐"}, [349] = {id=349,en="Kurayami: San",ja="暗闇の術:参"}, - [355] = {id=355,en="Tonko: San",ja="遁甲の術:参"}, [416] = {id=416,en="Cactuar Fugue",ja="サボテンダーフーガ"}, [407] = {id=407,en="Chocobo Hum",ja="チョコボのハミング"}, [363] = {id=363,en="Sleepga",ja="スリプガ"}, From 44278f971458e8b824ecf5e1d6a799fbc2945da2 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sun, 4 Feb 2024 15:53:32 +0000 Subject: [PATCH 0969/1002] Update author field for battlemod.lua --- addons/battlemod/battlemod.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/battlemod/battlemod.lua b/addons/battlemod/battlemod.lua index 4283ca60d0..623ff2b1c0 100644 --- a/addons/battlemod/battlemod.lua +++ b/addons/battlemod/battlemod.lua @@ -15,7 +15,7 @@ require 'statics' _addon.version = '3.33' _addon.name = 'BattleMod' -_addon.author = 'Byrth, maintainer: SnickySnacks' +_addon.author = 'Byrth, SnickySnacks, Kenshi' _addon.commands = {'bm','battlemod'} windower.register_event('load',function() From 515075755445d422217219800ec5a345487620df Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sat, 10 Feb 2024 21:39:27 +0000 Subject: [PATCH 0970/1002] Update extdata.lua Add 'Rank' field to augment system 4 (Ultimate Weapons, Odyssey Armor, Dynamis Divergence Weapons and Necks, Unity Rewards) --- addons/libs/extdata.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/libs/extdata.lua b/addons/libs/extdata.lua index 0537a4375e..63df81a8eb 100644 --- a/addons/libs/extdata.lua +++ b/addons/libs/extdata.lua @@ -1753,7 +1753,8 @@ function decode.Augmented(str) rettab.augment_system = 4 local path_map = {[0] = 'A',[1] = 'B', [2] = 'C', [3] = 'D'} rettab.path = path_map[math.floor(str:byte(5)%4)] - rettab.augments = {'Path: ' ..rettab.path} + rettab.rank = math.floor(str:byte(7)%128 / 4) + rettab.augments = {'Path: ' ..rettab.path, 'Rank: ' ..rettab.rank} elseif flag_2/128 >= 1 then -- Evolith rettab.augment_system = 3 local slot_type_map = {[0] = 'None', [1] = 'Filled Upside-down Triangle', [2] = 'Filled Diamond', [3] = 'Filled Star', [4] = 'Empty Triangle', [5] = 'Empty Square', [6] = 'Empty Circle', [7] = 'Empty Upside-down Triangle', [8] = 'Empty Diamond', [9] = 'Empty Star', [10] = 'Filled Triangle', [11] = 'Filled Square', [12] = 'Filled Circle', [13] = 'Empty Circle', [14] = 'Fire', [15] = 'Ice'} From d9676a101848a42e5ab214eaa077cf10f8ee2cfa Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Sat, 10 Feb 2024 23:42:40 +0000 Subject: [PATCH 0971/1002] Update extdata.lua Partial revert to avoid a potentially breaking change. --- addons/libs/extdata.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/extdata.lua b/addons/libs/extdata.lua index 63df81a8eb..02d137aefd 100644 --- a/addons/libs/extdata.lua +++ b/addons/libs/extdata.lua @@ -1754,7 +1754,7 @@ function decode.Augmented(str) local path_map = {[0] = 'A',[1] = 'B', [2] = 'C', [3] = 'D'} rettab.path = path_map[math.floor(str:byte(5)%4)] rettab.rank = math.floor(str:byte(7)%128 / 4) - rettab.augments = {'Path: ' ..rettab.path, 'Rank: ' ..rettab.rank} + rettab.augments = {'Path: ' ..rettab.path} elseif flag_2/128 >= 1 then -- Evolith rettab.augment_system = 3 local slot_type_map = {[0] = 'None', [1] = 'Filled Upside-down Triangle', [2] = 'Filled Diamond', [3] = 'Filled Star', [4] = 'Empty Triangle', [5] = 'Empty Square', [6] = 'Empty Circle', [7] = 'Empty Upside-down Triangle', [8] = 'Empty Diamond', [9] = 'Empty Star', [10] = 'Filled Triangle', [11] = 'Filled Square', [12] = 'Filled Circle', [13] = 'Empty Circle', [14] = 'Fire', [15] = 'Ice'} From b9d3dd46b4198b2a711c6e25f6dbb90aa806d90e Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Sun, 11 Feb 2024 08:19:50 +0100 Subject: [PATCH 0972/1002] Fixed various issues with resources --- addons/libs/resources.lua | 165 +++++++++++++++++--------------------- 1 file changed, 75 insertions(+), 90 deletions(-) diff --git a/addons/libs/resources.lua b/addons/libs/resources.lua index a33b9cf463..eb323c81b4 100644 --- a/addons/libs/resources.lua +++ b/addons/libs/resources.lua @@ -1,16 +1,16 @@ --[[ - A library to handle ingame resources, as provided by the Radsources XMLs. It will look for the files in Windower/plugins/resources. + A library to handle ingame resources, as provided by ResourceExtractor. It will look for the files in Windower/res/. ]] _libs = _libs or {} require('functions') require('tables') +require('sets') require('strings') +require('bit') local functions, table, string = _libs.functions, _libs.tables, _libs.strings -local files = require('files') -local xml = require('xml') local fns = {} @@ -70,16 +70,7 @@ end resource_mt.__class = 'Resource' resource_mt.__index = function(t, k) - local res = slots[t] and slots[t]:contains(k) and resource_group:endapply(k) - - if not res then - res = table[k] - if class(res) == 'Resource' then - slots[res] = slots[t] - end - end - - return res + return slots[t] and slots[t]:contains(k) and resource_group:endapply(k) or table[k] end resource_mt.__tostring = function(t) @@ -89,32 +80,43 @@ end local resources_path = windower.windower_path .. 'res/' local flag_cache = {} -local parse_flags = function(bits, lookup, values) - flag_cache[lookup] = flag_cache[lookup] or {} - - if values and not flag_cache[lookup][bits] and lookup[bits] then - flag_cache[lookup][bits] = S{lookup[bits]} - elseif not flag_cache[lookup][bits] then - local res = S{} - - local rem - local num = bits - local count = 0 - while num > 0 do - num, rem = (num/2):modf() - if rem > 0 then - res:add(values and lookup[2^count] or count) - end - count = count + 1 - end - flag_cache[lookup][bits] = res +local check_flags = function(bits, lookup) + if lookup.combination == 'replace' and lookup.values[bits] ~= nil then + return S{lookup.values[bits]} end - return flag_cache[lookup][bits] + local flags = S{} + + for flag, value in pairs(lookup.values) do + if bit.band(bits, flag) ~= 0 then + flags:add(value) + end + end + + return flags +end + +local parse_flags = function(bits) + local flags = S{} + + local count = 0 + repeat + local flag = 2 ^ count + if bit.band(flag, bits) ~= 0 then + flags:add(count) + end + count = count + 1 + until flag > bits + + return flags end -local language_strings = S{'english', 'japanese', 'german', 'french'} +local get_flags = function(bits, attribute, lookup) + flag_cache[attribute] = flag_cache[attribute] or {} + flag_cache[attribute][bits] = flag_cache[attribute][bits] or lookup and check_flags(bits, lookup) or parse_flags(bits) + return flag_cache[attribute][bits] +end -- Add resources from files local post_process @@ -129,33 +131,13 @@ for res_name in res_names:it() do end end -local lookup = {} -local flag_keys = S{ - 'flags', - 'targets', -} +local bit_slots = {} local fn_cache = {} post_process = function(t) local slot_set = slots[t] - for key in slot_set:it() do - if lookup[key] then - if flag_keys:contains(key) then - fn_cache[key] = function(flags) - return parse_flags(flags, lookup[key], true) - end - else - fn_cache[key] = function(flags) - return parse_flags(flags, lookup[key], false) - end - end - - elseif lookup[key .. 's'] then - fn_cache[key] = function(value) - return value - end - - end + for key in slot_set:filter(table.get+{bit_slots}):it() do + fn_cache[key] = get_flags-{key, bit_slots[key] ~= true and bit_slots[key] or nil} end for _, entry in pairs(t) do @@ -171,42 +153,45 @@ post_process = function(t) end end -lookup = { - elements = resources.elements, - jobs = resources.jobs, - slots = resources.slots, - races = resources.races, - skills = resources.skills, +bit_slots = { + jobs = true, + slots = true, + races = true, targets = { - [0x01] = 'Self', - [0x02] = 'Player', - [0x04] = 'Party', - [0x08] = 'Ally', - [0x10] = 'NPC', - [0x20] = 'Enemy', - - [0x60] = 'Object', - [0x9D] = 'Corpse', + combination = 'replace', + values = { + [0x01] = 'Self', + [0x02] = 'Player', + [0x04] = 'Party', + [0x08] = 'Ally', + [0x10] = 'NPC', + [0x20] = 'Enemy', + + [0x60] = 'Object', + [0x9D] = 'Corpse', + }, }, flags = { - [0x0001] = 'Flag00', - [0x0002] = 'Flag01', - [0x0004] = 'Flag02', - [0x0008] = 'Flag03', - [0x0010] = 'Can Send POL', - [0x0020] = 'Inscribable', - [0x0040] = 'No Auction', - [0x0080] = 'Scroll', - [0x0100] = 'Linkshell', - [0x0200] = 'Usable', - [0x0400] = 'NPC Tradeable', - [0x0800] = 'Equippable', - [0x1000] = 'No NPC Sale', - [0x2000] = 'No Delivery', - [0x4000] = 'No PC Trade', - [0x8000] = 'Rare', - - [0x6040] = 'Exclusive', + values = { + [0x0001] = 'Flag00', + [0x0002] = 'Flag01', + [0x0004] = 'Flag02', + [0x0008] = 'Flag03', + [0x0010] = 'Can Send POL', + [0x0020] = 'Inscribable', + [0x0040] = 'No Auction', + [0x0080] = 'Scroll', + [0x0100] = 'Linkshell', + [0x0200] = 'Usable', + [0x0400] = 'NPC Tradeable', + [0x0800] = 'Equippable', + [0x1000] = 'No NPC Sale', + [0x2000] = 'No Delivery', + [0x4000] = 'No PC Trade', + [0x8000] = 'Rare', + + [0x6040] = 'Exclusive', + }, }, } From 097df9ec02d92e3713f7feb2c110a2bf40d6842f Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Sun, 11 Feb 2024 17:25:19 +0100 Subject: [PATCH 0973/1002] Libs/Resources: Fixed flag parsing --- addons/libs/resources.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/resources.lua b/addons/libs/resources.lua index eb323c81b4..72b49d36e2 100644 --- a/addons/libs/resources.lua +++ b/addons/libs/resources.lua @@ -89,7 +89,7 @@ local check_flags = function(bits, lookup) local flags = S{} for flag, value in pairs(lookup.values) do - if bit.band(bits, flag) ~= 0 then + if bit.band(flag, bits) >= flag then flags:add(value) end end @@ -103,7 +103,7 @@ local parse_flags = function(bits) local count = 0 repeat local flag = 2 ^ count - if bit.band(flag, bits) ~= 0 then + if bit.band(flag, bits) >= flag then flags:add(count) end count = count + 1 From 5b491ccbe4f0c19c1b4907b08f80452992f80bbf Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Sun, 11 Feb 2024 17:57:41 +0100 Subject: [PATCH 0974/1002] Libs/Resources: Amended behavior when filtering resources by an attribute --- addons/libs/resources.lua | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/addons/libs/resources.lua b/addons/libs/resources.lua index 72b49d36e2..8d0c4e3ae4 100644 --- a/addons/libs/resources.lua +++ b/addons/libs/resources.lua @@ -14,7 +14,8 @@ local functions, table, string = _libs.functions, _libs.tables, _libs.strings local fns = {} -local slots = {} +local slots = setmetatable({}, {__mode = 'k'}) +local bit_slots = {} local language_string = _addon and _addon.language and _addon.language:lower() or windower.ffxi.get_info().language:lower() local language_string_log = language_string .. '_log' @@ -53,12 +54,15 @@ local resource_entry_mt = {__index = function() end()} function resource_group(r, fn, attr) - fn = type(fn) == 'function' and fn or functions.equals(fn) attr = redict[attr] or attr + fn = type(fn) == 'function' and fn or + bit_slots[attr] and class(fn) == 'Set' and set.subset+{fn} or + bit_slots[attr] and set.contains-{fn} or + functions.equals(fn) local res = {} for value, id in table.it(r) do - if fn(value[attr]) then + if value[attr] ~= nil and fn(value[attr]) then res[id] = value end end @@ -131,7 +135,6 @@ for res_name in res_names:it() do end end -local bit_slots = {} local fn_cache = {} post_process = function(t) From 578fd515644a6bd6aa623c55acea93f6efd6a8d1 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Mon, 12 Feb 2024 23:26:47 -0800 Subject: [PATCH 0975/1002] Lib/Strings: Added encoding aware iteration (#2333) * Lib/Strings: Added encoding aware iteration * Libs/Strings: Refactored string.it * Lib/Strings: Fixes/cleanups --- addons/libs/strings.lua | 54 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/addons/libs/strings.lua b/addons/libs/strings.lua index cd7ac1e202..b16469488d 100644 --- a/addons/libs/strings.lua +++ b/addons/libs/strings.lua @@ -24,6 +24,13 @@ debug.setmetatable('', { __unp = functions.equals, }) +string.encoding = { + ascii = {}, + utf8 = {}, + shift_jis = {}, + binary = {}, +} + -- Returns a function that returns the string when called. function string.fn(str) return functions.const(str) @@ -121,9 +128,50 @@ function string.splice(str, from, to, str2) return str:sub(1, from - 1)..str2..str:sub(to + 1) end --- Returns an iterator, that goes over every character of the string. -function string.it(str) - return str:gmatch('.') +-- Returns an iterator, that goes over every character of the string. Handles Japanese text as well as special characters and auto-translate. +do + local process = function(str, fn) + local index = 1 + return function() + if index > #str then + return nil + end + + local length = fn(str:byte(index, index)) + if length == nil then + error('Invalid code point') + end + + index = index + length + return str:sub(index - length, index - 1) + end + end + + local iterators = { + [string.encoding.ascii] = function(str) + return str:gmatch('.') + end, + [string.encoding.utf8] = process(str, function(byte) + return + byte < 0x80 and 1 or + byte < 0xE0 and 2 or + byte < 0xF0 and 3 or + byte < 0xF8 and 4 + end), + [string.encoding.shift_jis] = process(str, function(byte) + return + (byte < 0x80 or byte >= 0xA1 and byte <= 0xDF) and 1 or + (byte >= 0x80 and byte <= 0x9F or byte >= 0xE0 and byte <= 0xEF or byte >= 0xFA and byte <= 0xFC) and 2 or + byte == 0xFD and 6 + end), + [string.encoding.binary] = function(str) + return str:gmatch('.') + end, + } + + function string.it(str, encoding) + return iterators[encoding or string.encoding.ascii](str) + end end -- Removes leading and trailing whitespaces and similar characters (tabs, newlines, etc.). From a8c7e4c1cbb1c51816ee7f18de8bb8ae0b72c5fe Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Mon, 12 Feb 2024 23:45:46 -0800 Subject: [PATCH 0976/1002] Lib/Tabls: Added iterator packing function (#2334) --- addons/libs/tables.lua | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/addons/libs/tables.lua b/addons/libs/tables.lua index 644b33cb26..4db1435a2d 100644 --- a/addons/libs/tables.lua +++ b/addons/libs/tables.lua @@ -83,6 +83,19 @@ function class(o) return mt and mt.__class or type(o) end +-- Packs an iterator function into a table +function functions.pack(fn) + local res = {} + local value = fn() + local count = 0 + while value ~= nil do + count = count + 1 + res[count] = value + value = fn() + end + return setmetatable(res, _meta.T) +end + -- Returns a function that returns the table when called. function table.fn(t) return functions.const(t) From 47abb219103235feb3c27506938ea38308976339 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Wed, 14 Feb 2024 13:29:05 +0000 Subject: [PATCH 0977/1002] Update strings.lua (#2335) Bugfix in the new iterator --- addons/libs/strings.lua | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/addons/libs/strings.lua b/addons/libs/strings.lua index b16469488d..604d18654c 100644 --- a/addons/libs/strings.lua +++ b/addons/libs/strings.lua @@ -151,19 +151,23 @@ do [string.encoding.ascii] = function(str) return str:gmatch('.') end, - [string.encoding.utf8] = process(str, function(byte) - return - byte < 0x80 and 1 or - byte < 0xE0 and 2 or - byte < 0xF0 and 3 or - byte < 0xF8 and 4 - end), - [string.encoding.shift_jis] = process(str, function(byte) - return - (byte < 0x80 or byte >= 0xA1 and byte <= 0xDF) and 1 or - (byte >= 0x80 and byte <= 0x9F or byte >= 0xE0 and byte <= 0xEF or byte >= 0xFA and byte <= 0xFC) and 2 or - byte == 0xFD and 6 - end), + [string.encoding.utf8] = function(str) + return process(str, function(byte) + return + byte < 0x80 and 1 or + byte < 0xE0 and 2 or + byte < 0xF0 and 3 or + byte < 0xF8 and 4 + end) + end, + [string.encoding.shift_jis] = function(str) + return process(str, function(byte) + return + (byte < 0x80 or byte >= 0xA1 and byte <= 0xDF) and 1 or + (byte >= 0x80 and byte <= 0x9F or byte >= 0xE0 and byte <= 0xEF or byte >= 0xFA and byte <= 0xFC) and 2 or + byte == 0xFD and 6 + end) + end, [string.encoding.binary] = function(str) return str:gmatch('.') end, From 50a76dce269a838dbd0dd2020c55236898597902 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Mon, 19 Feb 2024 22:05:44 +0100 Subject: [PATCH 0978/1002] Libs/Strings: Added encoding aware string.find, string.match, string.gmatch and string.sub (#2336) --- addons/libs/strings.lua | 686 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 647 insertions(+), 39 deletions(-) diff --git a/addons/libs/strings.lua b/addons/libs/strings.lua index 604d18654c..4697a2095f 100644 --- a/addons/libs/strings.lua +++ b/addons/libs/strings.lua @@ -14,11 +14,14 @@ local string = require('string') _libs.strings = string +_raw = _raw or {} +_raw.error = _raw.error or error + _meta = _meta or {} debug.setmetatable('', { __index = function(str, k) - return string[k] or type(k) == 'number' and string.sub(str, k, k) or (_raw and _raw.error or error)('"%s" is not defined for strings':format(tostring(k)), 2) + return string[k] or type(k) == 'number' and string.sub(str, k, k) or _raw.error('"%s" is not defined for strings':format(tostring(k)), 2) end, __unm = functions.negate .. functions.equals, __unp = functions.equals, @@ -130,54 +133,659 @@ end -- Returns an iterator, that goes over every character of the string. Handles Japanese text as well as special characters and auto-translate. do - local process = function(str, fn) - local index = 1 - return function() - if index > #str then + local adjust_from = function(str, index) + return + not index and 1 or + index < 0 and #str - index + 1 or + index == 0 and 1 or + index + end + + local adjust_to = function(str, index) + return + not index and #str or + index < 0 and #str - index + 1 or + index + end + + do + local process = function(str, from, to, fn) + local index = from + return function() + if index > to then + return nil + end + + local length = fn(str:byte(index, index)) + if length == nil then + _raw.error('Invalid code point') + end + + index = index + length + return str:sub(index - length, index - 1) + end + end + + local iterators = { + [string.encoding.ascii] = function(str, from, to) + return str:sub(from, to):gmatch('.') + end, + [string.encoding.utf8] = function(str, from, to) + return process(str, from, to, function(byte) + return + byte < 0x80 and 1 or + byte < 0xE0 and 2 or + byte < 0xF0 and 3 or + byte < 0xF8 and 4 + end) + end, + [string.encoding.shift_jis] = function(str, from, to) + return process(str, from, to, function(byte) + return + (byte < 0x80 or byte >= 0xA1 and byte <= 0xDF) and 1 or + (byte >= 0x80 and byte <= 0x9F or byte >= 0xE0 and byte <= 0xEF or byte >= 0xFA and byte <= 0xFC) and 2 or + byte == 0xFD and 6 + end) + end, + [string.encoding.binary] = function(str, from, to) + return str:sub(from, to):gmatch('.') + end, + } + + function string.it(str, encoding, from, to) + if type(encoding) ~= 'table' then + encoding, from, to = string.encoding.ascii, encoding, from + end + return iterators[encoding](str, from or 1, to or #str) + end + end + + local all = function() return true end + local lower = function(b) return b >= 0x61 and b <= 0x7A end + local upper = function(b) return b >= 0x41 and b <= 0x5A end + local control = function(b) return b == 0x7F or b < 0x20 end + local punctuation = function(b) return b >= 0x21 and b <= 0x2F or b >= 0x3A and b <= 0x40 or b >= 0x5B and b <= 0x60 or b >= 0x7B and b <= 0x7E end + local letter = function(b) return lower(b) or upper(b) end + local digit = function(b) return b >= 0x30 and b <= 0x39 end + local space = function(b) return b == 0x20 or b == 0x0A or b == 0x07 or b == 0x09 end + local hex = function(b) return b >= 0x30 and b <= 0x39 or b >= 0x41 and b <= 0x46 or b >= 0x63 and b <= 0x66 end + local zero = function(b) return b == 0x00 end + local utf8_letter = function(b) return not control(b) and not digit(b) and not punctuation(b) and not space(b) end + local shift_jis_letter = function(b) return letter(b) or b >= 0xA1 and b <= 0xDF or b >= 0x823F and b <= 0x8491 or b >= 0x889F and b <= 0x9872 or b >= 0x989F and b <= 0xEAA4 end + local none = function() return false end + local classes = { + [string.encoding.ascii] = { + a = letter, + c = control, + d = digit, + l = lower, + p = punctuation, + u = upper, + s = space, + w = function(b) return letter(b) or digit(b) end, + x = hex, + z = zero, + }, + [string.encoding.utf8] = { + a = utf8_letter, + c = control, + d = digit, + l = lower, + p = punctuation, + u = upper, + s = space, + w = function(b) return utf8_letter(b) or digit(b) end, + x = hex, + z = zero, + }, + [string.encoding.shift_jis] = { + a = shift_jis_letter, + c = control, + d = digit, + l = lower, + p = function(b) return punctuation(b) or b >= 0x8140 and b <= 0x81FC or b >= 0x849F and b <= 0x84BE or b >= 0x8740 and b <= 0x849C end, + u = upper, + s = space, + w = function(b) return shift_jis_letter(b) or digit(b) end, + x = hex, + z = zero, + }, + [string.encoding.binary] = { + a = none, + c = none, + d = none, + l = none, + p = none, + u = none, + s = none, + w = none, + x = none, + z = zero, + }, + } + + do + local rawfind = string.find + + local findplain = function(str, pattern, encoding, from, to) + local offset = #pattern - 1 + local index = from + local search = pattern:it(encoding):pack() + local length = #search + for c in str:it(encoding, from, to - offset + 1) do + local position = 0 + for check in str:it(encoding, index + #c, index + offset) do + position = position + 1 + if check ~= search[position] then + break + end + if position == length then + return index, index + offset + end + end + index = index + #c + end + return nil, nil + end + + local types = { + capture = {}, + fixed = {}, + match = {}, + boundary = {}, + balanced = {}, + } + + local bytes = function(c) + local value = 0 + for i = 1, #c do + value = value * 0x100 + string.byte(c, i, i) + end + return value + end + + local parse + parse = function(iterator, class_lookup, level) + level = level or 0 + local pattern = {} + + local count = 0 + local last = false + local previous_char = nil + for c in iterator do + if last then + return '$ only valid at the end' + end + + local previous = pattern[count] + count = count + 1 + if (c == '-' or c == '?' or c == '*' or c == '+') and previous ~= nil and (previous.type == types.match or previous.type == types.fixed) and not previous.counter then + if previous.type == types.fixed then + if previous.value == previous_char then + count = count - 1 + else + previous.value = previous.value:sub(1, #previous.value - #previous_char) + end + local compare = bytes(c) + pattern[count] = { + type = types.match, + value = function(b) return b == compare end, + } + else + count = count - 1 + end + pattern[count].counter = c + elseif c == '(' then + pattern[count] = { + type = types.capture, + value = parse(iterator, class_lookup, level + 1), + } + elseif c == '.' then + pattern[count] = { + type = types.match, + value = all, + } + elseif c == '[' then + local set = {} + local next = iterator() + while next ~= ']' do + local add = next == '%' and iterator() or next + if add == nil then + return 'missing \']\'' + end + set[bytes(add)] = true + next = iterator() + end + + pattern[count] = { + type = types.match, + value = function(b) return set[b] end, + } + elseif c == '^' then + if count > 1 then + return '^ only valid at the start' + end + + pattern[count] = { + type = types.boundary, + value = '^', + } + elseif c == '$' then + last = true + + pattern[count] = { + type = types.boundary, + value = '$', + } + else + local single = nil + if c == '%' then + local next = iterator() + if next == nil then + return 'ends with \'%\'' + end + + if next == 'b' then + local open = iterator() + if open == nil then + return 'unbalanced pattern' + end + local close = iterator() + if close == nil then + return 'unbalanced pattern' + end + pattern[count] = { + type = types.balanced, + value = {open, close}, + } + else + local fn = class_lookup[next] + if fn ~= nil then + pattern[count] = { + type = types.match, + value = fn, + } + else + single = next + end + end + elseif c == ')' and level > 0 then + break + else + single = c + end + + if single ~= nil then + if previous ~= nil and previous.type == types.fixed then + previous.value = previous.value .. single + count = count - 1 + else + pattern[count] = { + type = types.fixed, + value = single, + } + end + end + end + + previous_char = c + end + + return pattern + end + + local match + match = function(iterate, pos, pattern, index) + if index == #pattern then + return pos - 1 + end + index = index + 1 + + local current = pattern[index] + local type = current.type + local value = current.value + local iterator = iterate(pos) + + if type == types.capture then + local inner_pattern = value + local inner_to, inner_captures = match(iterate, pos, inner_pattern, 0) + if not inner_to then + return nil + end + + local to, captures = match(iterate, inner_to + 1, pattern, index) + if not to then + return nil + end + + local allcaptures = {{pos, inner_to}, unpack(inner_captures or {})} + local count = #allcaptures + for i = 1, #(captures or {}) do + count = count + 1 + allcaptures[count] = captures[i] + end + + return to, allcaptures + + elseif type == types.fixed then + local compare = value + local compare_length = #compare + local length = 0 + while length < compare_length do + local char = iterator() + if char == nil or char ~= compare:sub(length + 1, length + #char) then + return nil + end + + pos = pos + #char + length = length + #char + end + + return match(iterate, pos, pattern, index) + + elseif type == types.match then + local check = function(c) return c ~= nil and value(bytes(c)) end + local counter = current.counter + if not counter then + local char = iterator() + if not check(char) then + return nil + end + + return match(iterate, pos + #char, pattern, index) + + elseif counter == '-' then + local to, captures = match(iterate, pos, pattern, index) + while to == nil do + local char = iterator() + if char == nil or not check(char) then + return nil + end + + to, captures = match(iterate, pos + #char, pattern, index) + end + + return to, captures + + else + if counter == '?' then + local char = iterator() + if check(char) then + local to, captures = match(iterate, pos + #char, pattern, index) + if to then + return to, captures + end + end + + return match(iterate, pos, pattern, index) + + elseif counter == '*' then + local char = iterator() + + local positions = {} + local count = 0 + while (check(char)) do + local prev = positions[count] or pos + count = count + 1 + positions[count] = prev + #char + char = iterator() + end + + for i = count, 1, -1 do + local to, captures = match(iterate, positions[i], pattern, index) + if to then + return to, captures + end + end + + return match(iterate, pos, pattern, index) + + elseif counter == '+' then + local char = iterator() + + local positions = {} + local count = 0 + while (check(char)) do + local prev = positions[count] or pos + count = count + 1 + positions[count] = prev + #char + char = iterator() + end + + for i = count, 1, -1 do + local to, captures = match(iterate, positions[i], pattern, index) + if to then + return to, captures + end + end + + return nil + + end + end + + elseif type == types.balanced then + local char = iterator() + local open, close = unpack(value) + if char ~= open then + return nil + end + + local count = 1 + repeat + pos = pos + #char + char = iterator() + if char == nil then + return nil + end + + if char == open then + count = count + 1 + elseif char == close then + count = count - 1 + end + until char == close and count == 0 + + return match(iterate, pos + #close, pattern, index) + + elseif type == types.boundary then + local char = iterator() + if char ~= nil then + return nil + end + return match(iterate, pos, pattern, index) + + end + end + + local pack = function(from, iterate, pattern, offset) + local to, captures = match(iterate, from, pattern, offset or 0) + if to == nil then return nil end - local length = fn(str:byte(index, index)) - if length == nil then - error('Invalid code point') + return { + from = from, + to = to, + captures = captures or {}, + } + end + + local findpattern = function(iterate, length, pattern) + local first = pattern[1] + local matches + if first.type == types.boundary and first.value == '^' then + matches = pack(1, iterate, pattern, 1) + else + for i = 1, length do + matches = pack(i, iterate, pattern) + if matches then + break + end + end + end + + return matches + end + + local encoding_mt = { + __index = function(encoding_cache, rawpattern) + local pattern = parse(rawpattern:it(encoding_cache.encoding), classes[encoding_cache.encoding]) + rawset(encoding_cache, rawpattern, pattern) + return pattern + end, + } + + local pattern_cache = setmetatable({}, { + __index = function(pattern_cache, encoding) + local encoding_cache = setmetatable({ encoding = encoding }, encoding_mt) + rawset(pattern_cache, encoding, encoding_cache) + return encoding_cache + end, + }) + + local find = function(plain, str, pattern, encoding, from, to) + if plain then + return findplain(str, pattern, encoding, from, to) + else + local offset = from - 1 + local matches = findpattern(function(pos) return str:it(encoding, pos + offset, to) end, to - offset, pattern_cache[encoding][pattern]) + if not matches then + return nil + end + + for i = 1, #matches.captures do + local first, last = unpack(matches.captures[i]) + matches.captures[i] = str:sub(first + offset, last + offset) + end + + return matches.from + offset, matches.to + offset, unpack(matches.captures) + end + end + + function string.find(str, pattern, encoding, from, to, plain) + if type(encoding) == 'number' then + encoding, from, to, plain = type(to) == 'table' and to or nil, encoding, type(from) == 'number' and from or plain, type(from) == 'boolean' and from or nil + end + encoding = encoding or string.encoding.ascii + + if encoding == string.encoding.ascii and to == nil then + return rawfind(str, pattern, from, plain) end - index = index + length - return str:sub(index - length, index - 1) + return find(plain, str, pattern, encoding, adjust_from(str, from), adjust_to(str, to)) end end - local iterators = { - [string.encoding.ascii] = function(str) - return str:gmatch('.') - end, - [string.encoding.utf8] = function(str) - return process(str, function(byte) - return - byte < 0x80 and 1 or - byte < 0xE0 and 2 or - byte < 0xF0 and 3 or - byte < 0xF8 and 4 - end) - end, - [string.encoding.shift_jis] = function(str) - return process(str, function(byte) - return - (byte < 0x80 or byte >= 0xA1 and byte <= 0xDF) and 1 or - (byte >= 0x80 and byte <= 0x9F or byte >= 0xE0 and byte <= 0xEF or byte >= 0xFA and byte <= 0xFC) and 2 or - byte == 0xFD and 6 - end) - end, - [string.encoding.binary] = function(str) - return str:gmatch('.') - end, - } + do + local rawmatch = string.match + + local process = function(str, first, last, ...) + if not first then + return nil + end + + if select('#', ...) == 0 then + return str:sub(first, last) + end + + return ... + end + + function string.match(str, pattern, encoding, from, to) + if (type(encoding) == 'number') then + encoding, from, to = type(from) == 'table' and from or nil, encoding, type(from) == 'number' and from or to + end + encoding = encoding or string.encoding.ascii + + if encoding == string.encoding.ascii and to == nil then + return rawmatch(str, pattern, from) + end - function string.it(str, encoding) - return iterators[encoding or string.encoding.ascii](str) + return process(str, string.find(str, pattern, adjust_from(str, from), false, encoding, adjust_to(str, to))) + end + end + + do + local rawgmatch = string.gmatch + + function string.gmatch(str, pattern, encoding, from, to) + if (type(encoding) == 'number') then + encoding, from, to = type(from) == 'table' and from or nil, encoding, type(from) == 'number' and from or to + end + encoding = encoding or string.encoding.ascii + + if encoding == string.encoding.ascii and to == nil then + return rawgmatch(str, pattern, from) + end + + local pos = adjust_from(str, from) + local process = function(first, last, ...) + if not first then + return nil + end + + if last >= pos then + pos = last + 1 + else + local char = str:it(encoding, pos)() + pos = pos + #char + end + + if select('#', ...) == 0 then + return str:sub(first, last) + end + + return ... + end + + return function() + return process(string.find(str, pattern, encoding, pos, adjust_to(str, to))) + end + end + end + + do + local rawgsub = string.gsub + + function string.gsub(str, pattern, repl, n, encoding, from, to) + if type(n) == 'table' then + n, encoding, from, to = nil, n, encoding, from + elseif type(encoding) == 'number' then + encoding, from, to = nil, encoding, from + end + encoding = encoding or string.encoding.ascii + + if encoding == string.encoding.ascii and to == nil then + return rawgsub(str, pattern, from) + end + + local repltype = type(repl) + repl = + repltype == 'function' and repl or + repltype == 'table' and function(match) return repl[match] end or + function() return repl end + + local pos = adjust_from(str, from) + local fragments = {} + local count = 0 + repeat + local first, last = string.find(str, pattern, encoding, pos, adjust_to(str, to)) + if first then + count = count + 1 + fragments[count] = str:sub(pos, first - 1) + count = count + 1 + fragments[count] = repl(str:sub(first, last)) + end + pos = last + 1 + until first == nil or count == n + + return table.concat(fragments) .. str:sub(pos) + end end end + -- Removes leading and trailing whitespaces and similar characters (tabs, newlines, etc.). function string.trim(str) return str:match('^%s*(.-)%s*$') @@ -284,7 +892,7 @@ end function string.parse_hex(str) local interpreted_string = str:gsub('0x', ''):gsub('[^%w]', '') if #interpreted_string % 2 ~= 0 then - (_raw and _raw.error or error)('Invalid input string length', 2) + _raw.error('Invalid input string length', 2) end return (interpreted_string:gsub('%w%w', hex_r)) @@ -296,7 +904,7 @@ end function string.parse_binary(str) local interpreted_string = str:gsub('0b', ''):gsub('[^01]', '') if #interpreted_string % 8 ~= 0 then - (_raw and _raw.error or error)('Invalid input string length', 2) + _raw.error('Invalid input string length', 2) end return (interpreted_string:gsub(binary_pattern, binary_r)) From f56668d5f08fd4fff3b87ef5e1d7c181573b0c88 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Tue, 20 Feb 2024 12:12:16 +0100 Subject: [PATCH 0979/1002] Lib/Strings: Fixed argument parser for new string functions --- addons/libs/strings.lua | 51 +++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/addons/libs/strings.lua b/addons/libs/strings.lua index 4697a2095f..c8553d2fb4 100644 --- a/addons/libs/strings.lua +++ b/addons/libs/strings.lua @@ -664,10 +664,13 @@ do end function string.find(str, pattern, encoding, from, to, plain) - if type(encoding) == 'number' then - encoding, from, to, plain = type(to) == 'table' and to or nil, encoding, type(from) == 'number' and from or plain, type(from) == 'boolean' and from or nil + if type(encoding) ~= 'table' then + if type(from) == 'boolean' then + encoding, from, to, plain = string.encoding.ascii, encoding, nil, from + else + encoding, from, to, plain = string.encoding.ascii, encoding, from, to + end end - encoding = encoding or string.encoding.ascii if encoding == string.encoding.ascii and to == nil then return rawfind(str, pattern, from, plain) @@ -693,10 +696,9 @@ do end function string.match(str, pattern, encoding, from, to) - if (type(encoding) == 'number') then - encoding, from, to = type(from) == 'table' and from or nil, encoding, type(from) == 'number' and from or to + if type(encoding) ~= 'table' then + encoding, from, to = string.encoding.ascii, encoding, from end - encoding = encoding or string.encoding.ascii if encoding == string.encoding.ascii and to == nil then return rawmatch(str, pattern, from) @@ -710,15 +712,16 @@ do local rawgmatch = string.gmatch function string.gmatch(str, pattern, encoding, from, to) - if (type(encoding) == 'number') then - encoding, from, to = type(from) == 'table' and from or nil, encoding, type(from) == 'number' and from or to + if type(encoding) ~= 'table' then + encoding, from, to = string.encoding.ascii, encoding, from end - encoding = encoding or string.encoding.ascii if encoding == string.encoding.ascii and to == nil then return rawgmatch(str, pattern, from) end + to = adjust_to(str, to) + local pos = adjust_from(str, from) local process = function(first, last, ...) if not first then @@ -740,7 +743,7 @@ do end return function() - return process(string.find(str, pattern, encoding, pos, adjust_to(str, to))) + return process(string.find(str, pattern, encoding, pos, to)) end end end @@ -751,34 +754,37 @@ do function string.gsub(str, pattern, repl, n, encoding, from, to) if type(n) == 'table' then n, encoding, from, to = nil, n, encoding, from - elseif type(encoding) == 'number' then - encoding, from, to = nil, encoding, from + elseif type(encoding) ~= 'table' then + encoding, from, to = string.encoding.ascii, encoding, from end - encoding = encoding or string.encoding.ascii if encoding == string.encoding.ascii and to == nil then return rawgsub(str, pattern, from) end + to = adjust_to(str, to) + local repltype = type(repl) repl = repltype == 'function' and repl or repltype == 'table' and function(match) return repl[match] end or function() return repl end - local pos = adjust_from(str, from) local fragments = {} local count = 0 - repeat - local first, last = string.find(str, pattern, encoding, pos, adjust_to(str, to)) - if first then - count = count + 1 - fragments[count] = str:sub(pos, first - 1) - count = count + 1 - fragments[count] = repl(str:sub(first, last)) + local pos = adjust_from(str, from) + local first, last = string.find(str, pattern, encoding, pos, to) + while first do + count = count + 1 + fragments[count] = str:sub(pos, first - 1) + count = count + 1 + fragments[count] = repl(str:sub(first, last)) + if count / 2 == n then + break end pos = last + 1 - until first == nil or count == n + first, last = string.find(str, pattern, encoding, pos, to) + end return table.concat(fragments) .. str:sub(pos) end @@ -786,6 +792,7 @@ do end + -- Removes leading and trailing whitespaces and similar characters (tabs, newlines, etc.). function string.trim(str) return str:match('^%s*(.-)%s*$') From d2d2eec5765d11f3ce32a7234f2902ec98be20c9 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Wed, 21 Feb 2024 08:42:11 +0100 Subject: [PATCH 0980/1002] Lib/Strings: Fixed argument processing --- addons/libs/strings.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/strings.lua b/addons/libs/strings.lua index c8553d2fb4..240c2ba593 100644 --- a/addons/libs/strings.lua +++ b/addons/libs/strings.lua @@ -717,7 +717,7 @@ do end if encoding == string.encoding.ascii and to == nil then - return rawgmatch(str, pattern, from) + return rawgmatch(str, pattern) end to = adjust_to(str, to) @@ -759,7 +759,7 @@ do end if encoding == string.encoding.ascii and to == nil then - return rawgsub(str, pattern, from) + return rawgsub(str, pattern, repl) end to = adjust_to(str, to) From 49a57ef9a72429eecc8b06af1b799acdae2a942f Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Tue, 27 Feb 2024 23:12:53 +0100 Subject: [PATCH 0981/1002] [slips] Updating new items (#2337) Updating new items for the slips lib --- addons/libs/slips.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 49c6fcebe4..682ace591a 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757, 25909}, -- 192 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912, 3753, 23806, 3754, 23810, 23811, 3755, 26496, 26497, 21786, 21787, 21996, 21997, 23802, 25777, 25778, 21933, 21934, 21993, 21994}, -- 177 SE Skipped an index hence the 0 as one of the items + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912, 3753, 23806, 3754, 23810, 23811, 3755, 26496, 26497, 21786, 21787, 21996, 21997, 23802, 25777, 25778, 21933, 21934, 21993, 21994, 23866, 20670, 21537, 21538}, -- 181 SE Skipped an index hence the 0 as one of the items [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067, 21680, 22071}, -- 177 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, -- 115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, -- 115 @@ -43,7 +43,7 @@ slips.items = { [slips.storages[28]] = L{21515, 21561, 21617, 21670, 21718, 21775, 21826, 21879, 21918, 21971, 22027, 22082, 22108, 22214, 21516, 21562, 21618, 21671, 21719, 21776, 21827, 21880, 21919, 21972, 22028, 22083, 22109, 22215, 21517, 21563, 21619, 21672, 21720, 21777, 21828, 21881, 21920, 21973, 22029, 22084, 22110, 22216, 21518, 21564, 21620, 21673, 21721, 21778, 21829, 21882, 21921, 21974, 22030, 22085, 22111, 22217, 21519, 21565, 21621, 21674, 21722, 21779, 21830, 21883, 21922, 21975, 22031, 22086, 22107, 22218, 22089}, --71 [slips.storages[29]] = L{23085, 23152, 23219, 23286, 23353, 23086, 23153, 23220, 23287, 23354, 23087, 23154, 23221, 23288, 23355, 23088, 23155, 23222, 23289, 23356, 23089, 23156, 23223, 23290, 23357, 23090, 23157, 23224, 23291, 23358, 23091, 23158, 23225, 23292, 23359, 23092, 23159, 23226, 23293, 23360, 23093, 23160, 23227, 23294, 23361, 23094, 23161, 23228, 23295, 23362, 23095, 23162, 23229, 23296, 23363, 23096, 23163, 23230, 23297, 23364, 23097, 23164, 23231, 23298, 23365, 23098, 23165, 23232, 23299, 23366, 23099, 23166, 23233, 23300, 23367, 23100, 23167, 23234, 23301, 23368, 23101, 23168, 23235, 23302, 23369, 23102, 23169, 23236, 23303, 23370, 23103, 23170, 23237, 23304, 23371, 23104, 23171, 23238, 23305, 23372, 23105, 23172, 23239, 23306, 23373, 23106, 23173, 23240, 23307, 23374}, -- 110 [slips.storages[30]] = L{23420, 23487, 23554, 23621, 23688, 23421, 23488, 23555, 23622, 23689, 23422, 23489, 23556, 23623, 23690, 23423, 23490, 23557, 23624, 23691, 23424, 23491, 23558, 23625, 23692, 23425, 23492, 23559, 23626, 23693, 23426, 23493, 23560, 23627, 23694, 23427, 23494, 23561, 23628, 23695, 23428, 23495, 23562, 23629, 23696, 23429, 23496, 23563, 23630, 23697, 23430, 23497, 23564, 23631, 23698, 23431, 23498, 23565, 23632, 23699, 23432, 23499, 23566, 23633, 23700, 23433, 23500, 23567, 23634, 23701, 23434, 23501, 23568, 23635, 23702, 23435, 23502, 23569, 23636, 23703, 23436, 23503, 23570, 23637, 23704, 23437, 23504, 23571, 23638, 23705, 23438, 23505, 23572, 23639, 23706, 23439, 23506, 23573, 23640, 23707, 23440, 23507, 23574, 23641, 23708, 23441, 23508, 23575, 23642, 23709}, -- 110 - [slips.storages[31]] = L{23812, 23813, 23814, 23815, 23816, 23817, 23818, 23819, 23820, 23821, 23832, 23833, 23834, 23835, 23836}, -- 15 + [slips.storages[31]] = L{23812, 23813, 23814, 23815, 23816, 23817, 23818, 23819, 23820, 23821, 23832, 23833, 23834, 23835, 23836, 23822, 23823, 23824, 23825, 23826, 23827, 23828, 23829, 23830, 23831}, -- 25 } function slips.get_slip_id(n) From 192cf73030719dd70b871fe16da54dda9f7c3ee3 Mon Sep 17 00:00:00 2001 From: RubenatorX Date: Tue, 2 Apr 2024 16:55:08 -0600 Subject: [PATCH 0982/1002] [Clock] display settings bugfix --- addons/Clock/Clock.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/Clock/Clock.lua b/addons/Clock/Clock.lua index b3ae51540a..9ba5f9c440 100644 --- a/addons/Clock/Clock.lua +++ b/addons/Clock/Clock.lua @@ -50,7 +50,7 @@ redraw = function() end, 0) local format_string = settings.ShowTimeZones and '%s%s: ${%s}' or '${%s}' local strings = sorted:map(function(tz) - local display = settings.Display[tz] or tz_format[tz] + local display = settings.Display[tz:lower()] or tz_format[tz] return format_string:format(display, ' ':rep(width - #display), tz) end) From b51f86e49230c56724a213a21a20959055d20bde Mon Sep 17 00:00:00 2001 From: KenshiDRK Date: Wed, 3 Apr 2024 13:59:55 +0200 Subject: [PATCH 0983/1002] [Slips] Adding new items (#2343) Adding Esoteric Athame and Eyre Cap to Storage slips 22 --- addons/libs/slips.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/slips.lua b/addons/libs/slips.lua index 682ace591a..f39b44f8eb 100644 --- a/addons/libs/slips.lua +++ b/addons/libs/slips.lua @@ -34,7 +34,7 @@ slips.items = { [slips.storages[19]] = L{27715, 27866, 27716, 27867, 278, 281, 284, 3680, 3681, 27859, 28149, 27860, 28150, 21107, 21108, 27625, 27626, 26693, 26694, 26707, 26708, 27631, 27632, 26705, 26706, 27854, 27855, 26703, 26704, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 21097, 21098, 26717, 26718, 26728,26719,26720,26889,26890, 21095, 21096, 26738, 26739, 26729, 26730, 26788, 26946, 27281, 27455, 26789, 3698, 20713, 20714, 26798, 26954, 26799, 26955, 3706, 26956, 26957, 3705, 26964, 26965, 27291, 26967, 27293, 26966, 27292, 26968, 27294, 21153, 21154, 21086, 21087, 25606, 26974, 27111, 27296, 27467, 25607, 26975, 27112, 27297, 27468, 14195, 14830, 14831, 13945, 13946, 14832, 13947, 17058, 13948, 14400, 14392, 14393, 14394, 14395, 14396, 14397, 14398, 14399, 11337, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 15819, 15820, 15821, 15822, 15823, 15824, 15825, 15826, 3670, 3672, 3661, 3595, 3665, 3668, 3663, 3674, 3667, 191, 28, 153, 151, 198, 202, 142, 134, 137, 340, 341, 334, 335, 337, 339, 336, 342, 338, 3631, 3632, 3625, 3626, 3628, 3630, 3627, 3633, 3629, 25632, 25633, 25604, 25713, 27325, 25714, 27326, 3651, 25711, 25712, 10925, 10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, 25657, 25756, 25658, 25757, 25909}, -- 192 [slips.storages[20]] = L{26740, 26898, 27052, 27237, 27411, 26742, 26900, 27054, 27239, 27413, 26744, 26902, 27056, 27241, 27415, 26746, 26904, 27058, 27243, 27417, 26748, 26906, 27060, 27245, 27419, 26750, 26908, 27062, 27247, 27421, 26752, 26910, 27064, 27249, 27423, 26754, 26912, 27066, 27251, 27425, 26756, 26914, 27068, 27253, 27427, 26758, 26916, 27070, 27255, 27429, 26760, 26918, 27072, 27257, 27431, 26762, 26920, 27074, 27259, 27433, 26764, 26922, 27076, 27261, 27435, 26766, 26924, 27078, 27263, 27437, 26768, 26926, 27080, 27265, 27439, 26770, 26928, 27082, 27267, 27441, 26772, 26930, 27084, 27269, 27443, 26774, 26932, 27086, 27271, 27445, 26776, 26934, 27088, 27273, 27447, 26778, 26936, 27090, 27275, 27449, 26780, 26938, 27092, 27277, 27451, 26782, 26940, 27094, 27279, 27453}, -- 110 [slips.storages[21]] = L{26741, 26899, 27053, 27238, 27412, 26743, 26901, 27055, 27240, 27414, 26745, 26903, 27057, 27242, 27416, 26747, 26905, 27059, 27244, 27418, 26749, 26907, 27061, 27246, 27420, 26751, 26909, 27063, 27248, 27422, 26753, 26911, 27065, 27250, 27424, 26755, 26913, 27067, 27252, 27426, 26757, 26915, 27069, 27254, 27428, 26759, 26917, 27071, 27256, 27430, 26761, 26919, 27073, 27258, 27432, 26763, 26921, 27075, 27260, 27434, 26765, 26923, 27077, 27262, 27436, 26767, 26925, 27079, 27264, 27438, 26769, 26927, 27081, 27266, 27440, 26771, 26929, 27083, 27268, 27442, 26773, 26931, 27085, 27270, 27444, 26775, 26933, 27087, 27272, 27446, 26777, 26935, 27089, 27274, 27448, 26779, 26937, 27091, 27276, 27450, 26781, 26939, 27093, 27278, 27452, 26783, 26941, 27095, 27280, 27454}, -- 110 - [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912, 3753, 23806, 3754, 23810, 23811, 3755, 26496, 26497, 21786, 21787, 21996, 21997, 23802, 25777, 25778, 21933, 21934, 21993, 21994, 23866, 20670, 21537, 21538}, -- 181 SE Skipped an index hence the 0 as one of the items + [slips.storages[22]] = L{25639, 25715, 25638, 3707, 3708, 21074, 26406, 25645, 25726, 25648, 25649, 25650, 25758, 25759, 25672, 25673, 282, 279, 280, 268, 25670, 25671, 26520, 25652, 25669, 22017, 22018, 25586, 25587, 10384, 10385, 22019, 22020, 25722, 25585, 25776, 25677, 25678, 25675, 25679, 20668, 20669, 22069, 25755, 3722, 21608, 3713, 3714, 3715, 3717, 3727, 3728, 20577, 3726, 20666, 20667, 21741, 21609, 3723, 26410, 26411, 25850, 21509, 3725, 3720, 21658, 26524, 20665, 26412, 21965, 21966, 21967, 25774, 25838, 25775, 25839, 3724, 3721, 21682, 22072, 21820, 21821, 23731, 26517, 23730, 20573, 20674, 21742, 21860, 22065, 22039, 22124, 22132, 3719, 3738, 26518, 27623, 21867, 21868, 22283, 26516, 20933, 20578, 20568, 3739, 20569, 20570, 22288, 26352, 23737, 22282, 3740, 0, 26545, 21977, 21978, 3742, 26519, 26514, 26515, 3743, 21636, 23753, 23754, 54, 25910, 20571, 23790, 23791, 26489, 22153, 22154, 20574, 20675, 21743, 21861, 22066, 3748, 21638, 23800, 23801, 3749, 3750, 22045, 22046, 3751, 26490, 26546, 22047, 22048, 22049, 23803, 23804, 22051, 22052, 3752, 23805, 25911, 25912, 3753, 23806, 3754, 23810, 23811, 3755, 26496, 26497, 21786, 21787, 21996, 21997, 23802, 25777, 25778, 21933, 21934, 21993, 21994, 23866, 20670, 21537, 21538, 21572, 23870}, -- 183 SE Skipped an index hence the 0 as one of the items [slips.storages[23]] = L{25659, 25745, 25800, 25858, 25925, 25660, 25746, 25801, 25859, 25926, 25663, 25749, 25804, 25862, 25929, 25664, 25750, 25805, 25863, 25930, 25665, 25751, 25806, 25865, 25931, 25666, 25752, 25807, 25866, 25932, 25661, 25747, 25802, 25860, 25927, 25662, 25748, 25803, 25861, 25928, 25667, 25753, 25808, 25867, 25933, 25668, 25754, 25809, 25868, 25934, 25579, 25779, 25818, 25873, 25940, 25580, 25780, 25819, 25874, 25941, 25590, 25764, 25812, 25871, 25937, 25591, 25765, 25813, 25872, 25938, 25581, 25781, 25820, 25875, 25942, 25582, 25782, 25821, 25876, 25943, 25588, 25762, 25810, 25869, 25935, 25589, 25763, 25811, 25870, 25936, 25583, 25783, 25822, 25877, 25944, 25584, 25784, 25823, 25878, 25945, 25574, 25790, 25828, 25879, 25946, 25575, 25791, 25829, 25880, 25947, 25576, 25792, 25830, 25881, 25948, 25577, 25793, 25831, 25882, 25949, 25578, 25794, 25832, 25883, 25950, 26204, 26205, 26206, 26207, 26208, 25569, 25797, 25835, 25886, 25953, 25573, 25796, 25834, 25885, 25952, 25570, 25798, 25836, 25887, 25954, 25572, 25795, 25833, 25884, 25951, 25571, 25799, 25837, 25888, 25955, 26211, 26210, 26212, 26209, 26213, 21863, 22004, 21744, 21272, 20576, 21761, 26409, 22070, 21681, 22005, 21745, 22068, 21759, 21770, 22067, 21680, 22071}, -- 177 [slips.storages[24]] = L{23040, 23107, 23174, 23241, 23308, 23041, 23108, 23175, 23242, 23309, 23042, 23109, 23176, 23243, 23310, 23043, 23110, 23177, 23244, 23311, 23044, 23111, 23178, 23245, 23312, 23045, 23112, 23179, 23246, 23313, 23046, 23113, 23180, 23247, 23314, 23047, 23114, 23181, 23248, 23315, 23048, 23115, 23182, 23249, 23316, 23049, 23116, 23183, 23250, 23317, 23050, 23117, 23184, 23251, 23318, 23051, 23118, 23185, 23252, 23319, 23052, 23119, 23186, 23253, 23320, 23053, 23120, 23187, 23254, 23321, 23054, 23121, 23188, 23255, 23322, 23055, 23122, 23189, 23256, 23323, 23056, 23123, 23190, 23257, 23324, 23057, 23124, 23191, 23258, 23325, 23058, 23125, 23192, 23259, 23326, 23059, 23126, 23193, 23260, 23327, 23060, 23127, 23194, 23261, 23328, 23061, 23128, 23195, 23262, 23329, 23062, 23129, 23196, 23263, 23330}, -- 115 [slips.storages[25]] = L{23375, 23442, 23509, 23576, 23643, 23376, 23443, 23510, 23577, 23644, 23377, 23444, 23511, 23578, 23645, 23378, 23445, 23512, 23579, 23646, 23379, 23446, 23513, 23580, 23647, 23380, 23447, 23514, 23581, 23648, 23381, 23448, 23515, 23582, 23649, 23382, 23449, 23516, 23583, 23650, 23383, 23450, 23517, 23584, 23651, 23384, 23451, 23518, 23585, 23652, 23385, 23452, 23519, 23586, 23653, 23386, 23453, 23520, 23587, 23654, 23387, 23454, 23521, 23588, 23655, 23388, 23455, 23522, 23589, 23656, 23389, 23456, 23523, 23590, 23657, 23390, 23457, 23524, 23591, 23658, 23391, 23458, 23525, 23592, 23659, 23392, 23459, 23526, 23593, 23660, 23393, 23460, 23527, 23594, 23661, 23394, 23461, 23528, 23595, 23662, 23395, 23462, 23529, 23596, 23663, 23396, 23463, 23530, 23597, 23664, 23397, 23464, 23531, 23598, 23665}, -- 115 From b65625c27c7bbc7b1d62368ce459894ad02a64e3 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Wed, 3 Apr 2024 22:28:54 +0100 Subject: [PATCH 0984/1002] Update send.lua (#2339) * Update send.lua Adjust string processing to reinstate double quotes removed by the command processor. * Update send.lua * Update send.lua Spaces after commas. * Update send.lua Fixed an oversight around the `` functionality. * Update send.lua Added toggle command for the debug functionality. * Update send.lua * Update send.lua Rename dbg to debug --- addons/send/send.lua | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/addons/send/send.lua b/addons/send/send.lua index 7289c78f71..c25fe441ad 100644 --- a/addons/send/send.lua +++ b/addons/send/send.lua @@ -1,17 +1,35 @@ -_addon.version = '1.0' +_addon.version = '1.1' _addon.name = 'Send' _addon.command = 'send' _addon.author = 'Byrth' -windower.register_event('addon command',function (...) - local term = table.concat({...}, ' ') +local debug = false - term = term:gsub('<(%a+)id>', function(target_string) +require('chat') + +windower.register_event('addon command', function (...) + if ...:lower() == '@debug' then + debug = not debug + windower.add_to_chat(55, 'send: debug ' .. tostring(dbg)) + return + end + + local term = T{...}:map(function(str) + str = windower.convert_auto_trans(str):strip_format() + if str:find(' ', string.encoding.shift_jis) then + return str:enclose('"') + end + return str + end):sconcat():gsub('<(%a+)id>', function(target_string) local entity = windower.ffxi.get_mob_by_target(target_string) return entity and entity.id or '<' .. target_string .. 'id>' end) - local broken_init = split(term, ' ') + if dbg then + windower.add_to_chat(207, 'send (debug): '..term) + end + + local broken_init = split(term,' ') local qual = table.remove(broken_init,1) local player = windower.ffxi.get_player() @@ -42,21 +60,21 @@ windower.register_event('ipc message',function (msg) local qual = table.remove(broken,1) local player = windower.ffxi.get_player() if player and qual:lower()==player.name:lower() then - relevant_msg(table.concat(broken,' ')) + relevant_msg(table.concat(broken, ' ')) end if string.char(qual:byte(1)) == '@' then local arg = string.char(qual:byte(2, qual:len())) if player and arg:upper() == player.main_job:upper() then if broken ~= nil then - relevant_msg(table.concat(broken,' ')) + relevant_msg(table.concat(broken, ' ')) end elseif arg:upper() == 'ALL' then if broken ~= nil then - relevant_msg(table.concat(broken,' ')) + relevant_msg(table.concat(broken, ' ')) end elseif arg:upper() == 'OTHERS' then if broken ~= nil then - relevant_msg(table.concat(broken,' ')) + relevant_msg(table.concat(broken, ' ')) end end end @@ -68,7 +86,7 @@ function split(msg, match) local splitarr = {} local u = 1 while u <= length do - local nextanch = msg:find(match,u) + local nextanch = msg:find(match, string.encoding.shift_jis, u) if nextanch ~= nil then splitarr[#splitarr+1] = msg:sub(u,nextanch-match:len()) if nextanch~=length then @@ -96,4 +114,3 @@ function relevant_msg(msg) end end - From f09e84ffd289101f6a4ad600072f6f4dba125cc8 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Thu, 4 Apr 2024 07:51:42 +0100 Subject: [PATCH 0985/1002] Update send.lua (#2344) * Update send.lua Extensive code revision Added two new targets: @party and @zone * Update send.lua All commas are now properly married to a space each * Update send.lua Removed all trailing spaces --- addons/send/send.lua | 118 +++++++++++++++++++++++++++---------------- 1 file changed, 74 insertions(+), 44 deletions(-) diff --git a/addons/send/send.lua b/addons/send/send.lua index c25fe441ad..65c53f0ca0 100644 --- a/addons/send/send.lua +++ b/addons/send/send.lua @@ -1,7 +1,7 @@ -_addon.version = '1.1' +_addon.version = '1.2' _addon.name = 'Send' _addon.command = 'send' -_addon.author = 'Byrth' +_addon.author = 'Byrth, Lili' local debug = false @@ -10,13 +10,13 @@ require('chat') windower.register_event('addon command', function (...) if ...:lower() == '@debug' then debug = not debug - windower.add_to_chat(55, 'send: debug ' .. tostring(dbg)) + windower.add_to_chat(55, 'send: debug ' .. tostring(debug)) return end local term = T{...}:map(function(str) str = windower.convert_auto_trans(str):strip_format() - if str:find(' ', string.encoding.shift_jis) then + if str:find(' ', string.encoding.shift_jis) then return str:enclose('"') end return str @@ -25,55 +25,86 @@ windower.register_event('addon command', function (...) return entity and entity.id or '<' .. target_string .. 'id>' end) - if dbg then + if debug then windower.add_to_chat(207, 'send (debug): '..term) end - local broken_init = split(term,' ') - local qual = table.remove(broken_init,1) + local broken_init = split(term, ' ') + local qual = table.remove(broken_init, 1):lower() local player = windower.ffxi.get_player() - if player and qual:lower()==player['name']:lower() then - if broken_init ~= nil then - relevant_msg(table.concat(broken_init,' ')) + if #broken_init < 1 then + return + end + + if player and qual == player['name']:lower() then + relevant_msg(table.concat(broken_init, ' ')) + return + elseif qual == '@all' or qual == '@'..player.main_job:lower() then + if player then + relevant_msg(table.concat(broken_init, ' ')) end - elseif qual:lower()=='@all' or qual:lower()=='@'..player.main_job:lower() then - if broken_init ~= nil then - relevant_msg(table.concat(broken_init,' ')) + elseif qual:startswith('@party') then + if player then + relevant_msg(table.concat(broken_init, ' ')) end - windower.send_ipc_message('send ' .. term) - else - windower.send_ipc_message('send ' .. term) + local qual = qual .. windower.ffxi.get_player().name + term = qual .. ' ' .. table.concat(broken_init, ' ') + elseif qual:startswith('@zone') then + if player then + relevant_msg(table.concat(broken_init, ' ')) + end + local qual = qual .. windower.ffxi.get_info().zone + term = qual .. ' ' .. table.concat(broken_init, ' ') end + + windower.send_ipc_message('send ' .. term) end) -windower.register_event('ipc message',function (msg) - local broken = split(msg, ' ') +windower.register_event('ipc message', function (msg) + if debug then + windower.add_to_chat(207, 'send receive (debug): ' .. msg) + end + local broken = split(msg, ' ') local command = table.remove(broken, 1) - if command ~= 'send' then + + if command ~= 'send' or #broken < 2 then return end - if #broken < 2 then return end - - local qual = table.remove(broken,1) + local qual = table.remove(broken, 1) local player = windower.ffxi.get_player() - if player and qual:lower()==player.name:lower() then - relevant_msg(table.concat(broken, ' ')) + if not player then + return end - if string.char(qual:byte(1)) == '@' then - local arg = string.char(qual:byte(2, qual:len())) - if player and arg:upper() == player.main_job:upper() then - if broken ~= nil then - relevant_msg(table.concat(broken, ' ')) - end - elseif arg:upper() == 'ALL' then - if broken ~= nil then + + if qual:lower() == player.name:lower() then + relevant_msg(table.concat(broken, ' ')) + elseif string.char(qual:byte(1)) == '@' then + local arg = string.char(qual:byte(2, qual:len())):upper() + + if arg == player.main_job:upper() or arg == 'ALL' or arg == 'OTHERS' then + relevant_msg(table.concat(broken, ' ')) + elseif arg:startswith('PARTY') then + local name = arg:sub(6, #arg):lower() + local party = windower.ffxi.get_party() + local sameparty = function() + for i=1, 5 do + local idx = 'p'..i + if party[idx] and party[idx].name:lower() == name then + return true + end + end + end() + + if sameparty then relevant_msg(table.concat(broken, ' ')) end - elseif arg:upper() == 'OTHERS' then - if broken ~= nil then + elseif arg:upper():startswith('ZONE') then + local samezone = tonumber(arg:sub(5, #arg)) == windower.ffxi.get_info().zone + + if samezone then relevant_msg(table.concat(broken, ' ')) end end @@ -88,29 +119,28 @@ function split(msg, match) while u <= length do local nextanch = msg:find(match, string.encoding.shift_jis, u) if nextanch ~= nil then - splitarr[#splitarr+1] = msg:sub(u,nextanch-match:len()) - if nextanch~=length then - u = nextanch+match:len() + splitarr[#splitarr + 1] = msg:sub(u, nextanch - match:len()) + if nextanch ~= length then + u = nextanch + match:len() else u = length end else - splitarr[#splitarr+1] = msg:sub(u,length) - u = length+1 + splitarr[#splitarr + 1] = msg:sub(u, length) + u = length + 1 end end return splitarr end function relevant_msg(msg) - if msg:sub(1,2)=='//' then + if msg:sub(1, 2) == '//' then windower.send_command(msg:sub(3)) - elseif msg:sub(1,1)=='/' then + elseif msg:sub(1, 1) == '/' then windower.send_command('input '..msg) - elseif msg:sub(1,3)=='atc' then - windower.add_to_chat(55,msg:sub(5)) + elseif msg:sub(1, 3) == 'atc' then + windower.add_to_chat(55, msg:sub(5)) else windower.send_command(msg) end - end From 5b22812f2438282c3a7e378b43740540f8f0470a Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Thu, 4 Apr 2024 10:45:06 +0200 Subject: [PATCH 0986/1002] Libs/Strings: Added encoding-aware string.split --- addons/libs/strings.lua | 167 ++++++++++++++++++++-------------------- 1 file changed, 84 insertions(+), 83 deletions(-) diff --git a/addons/libs/strings.lua b/addons/libs/strings.lua index 240c2ba593..ca316e3b22 100644 --- a/addons/libs/strings.lua +++ b/addons/libs/strings.lua @@ -44,83 +44,6 @@ function string.contains(str, sub) return str:find(sub, nil, true) ~= nil end --- Splits a string into a table by a separator pattern. -function string.psplit(str, sep, maxsplit, include) - maxsplit = maxsplit or 0 - - return str:split(sep, maxsplit, include, false) -end - -local rawsplit = function(str, sep, maxsplit, include, raw) - if not sep or sep == '' then - local res = {} - local key = 0 - for c in str:gmatch('.') do - key = key + 1 - res[key] = c - end - - return res, key - end - - maxsplit = maxsplit or 0 - if raw == nil then - raw = true - end - - local res = {} - local key = 0 - local i = 1 - local startpos, endpos - local match - while i <= #str + 1 do - -- Find the next occurence of sep. - startpos, endpos = str:find(sep, i, raw) - -- If found, get the substring and append it to the table. - if startpos then - match = str:sub(i, startpos - 1) - key = key + 1 - res[key] = match - - if include then - key = key + 1 - res[key] = str:sub(startpos, endpos) - end - - -- If maximum number of splits reached, return - if key == maxsplit - 1 then - key = key + 1 - res[key] = str:sub(endpos + 1) - break - end - i = endpos + 1 - -- If not found, no more separators to split, append the remaining string. - else - key = key + 1 - res[key] = str:sub(i) - break - end - end - - return res, key -end - --- Splits a string into a table by a separator string. -function string.split(str, sep, maxsplit, include, raw) - local res, key = rawsplit(str, sep, maxsplit, include, raw) - - if _meta.L then - res.n = key - return setmetatable(res, _meta.L) - end - - if _meta.T then - return setmetatable(res, _meta.T) - end - - return res -end - -- Alias to string.sub, with some syntactic sugar. function string.slice(str, from, to) return str:sub(from or 1, to or #str) @@ -751,11 +674,9 @@ do do local rawgsub = string.gsub - function string.gsub(str, pattern, repl, n, encoding, from, to) - if type(n) == 'table' then - n, encoding, from, to = nil, n, encoding, from - elseif type(encoding) ~= 'table' then - encoding, from, to = string.encoding.ascii, encoding, from + function string.gsub(str, pattern, repl, encoding, n, from, to) + if type(encoding) ~= 'table' then + encoding, n, from, to = string.encoding.ascii, encoding, n, from end if encoding == string.encoding.ascii and to == nil then @@ -789,9 +710,90 @@ do return table.concat(fragments) .. str:sub(pos) end end + + do + local rawsplit = function(str, sep, encoding, maxsplit, include, raw, from, to) + if not sep or sep == '' then + local res = {} + local count = 0 + for c in str:it(encoding, from, to) do + count = count + 1 + res[count] = c + end + + return res, count + end + + maxsplit = maxsplit or 0 + if raw == nil then + raw = true + end + + local res = {} + local count = 0 + local pos = 1 + local startpos, endpos + local match + while pos <= to do + -- Find the next occurence of sep. + startpos, endpos = str:find(sep, encoding, pos, to, raw) + -- If found, get the substring and append it to the table. + if startpos then + match = str:sub(pos, startpos - 1) + count = count + 1 + res[count] = match + + if include then + count = count + 1 + res[count] = str:sub(startpos, endpos) + end + + -- If maximum number of splits reached, return + if count == maxsplit - 1 then + count = count + 1 + res[count] = str:sub(endpos + 1) + break + end + pos = endpos + 1 + -- If not found, no more separators to split, append the remaining string. + else + count = count + 1 + res[count] = str:sub(pos) + break + end + end + + return res, count + end + + -- Splits a string into a table by a separator string. + function string.split(str, sep, encoding, maxsplit, include, raw, from, to) + if type(encoding) ~= 'table' then + encoding, maxsplit, include, raw, from, to = string.encoding.ascii, encoding, maxsplit, include, raw, from + end + + local res, key = rawsplit(str, sep, encoding, maxsplit, include, raw, from or 1, to or #str) + + if _meta.L then + res.n = key + return setmetatable(res, _meta.L) + end + + if _meta.T then + return setmetatable(res, _meta.T) + end + + return res + end + end end +-- Splits a string into a table by a separator pattern. +function string.psplit(str, sep, maxsplit, include) + maxsplit = maxsplit or 0 + return str:split(sep, maxsplit, include, false) +end -- Removes leading and trailing whitespaces and similar characters (tabs, newlines, etc.). function string.trim(str) @@ -1041,7 +1043,6 @@ end -- A string.gsub wrapper for case-insensitive patterns. function string.igsub(str, pattern, ...) - if not ... then print(debug.traceback()) end return str:gsub(pattern:ipattern(), ...) end From f31b504e547246c7714511c51e78224f41036dac Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Thu, 4 Apr 2024 15:26:25 +0200 Subject: [PATCH 0987/1002] Libs: Various string related fixes --- addons/libs/functions.lua | 13 ++++++++++ addons/libs/strings.lua | 54 +++++++++++++++++++-------------------- addons/libs/tables.lua | 13 ---------- 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/addons/libs/functions.lua b/addons/libs/functions.lua index 5dc15f3004..7478f59ff0 100644 --- a/addons/libs/functions.lua +++ b/addons/libs/functions.lua @@ -145,6 +145,19 @@ function functions.it(fn, ...) end end +-- Packs an iterator function into a table +function functions.pack(fn) + local res = {} + local value = fn() + local count = 0 + while value ~= nil do + count = count + 1 + res[count] = value + value = fn() + end + return res +end + -- Schedules the current function to run delayed by the provided time in seconds and returns the coroutine function functions.schedule(fn, time, ...) return coroutine.schedule(fn:prepare(...), time) diff --git a/addons/libs/strings.lua b/addons/libs/strings.lua index ca316e3b22..78db8a64d3 100644 --- a/addons/libs/strings.lua +++ b/addons/libs/strings.lua @@ -27,12 +27,16 @@ debug.setmetatable('', { __unp = functions.equals, }) -string.encoding = { - ascii = {}, - utf8 = {}, - shift_jis = {}, - binary = {}, -} +local enum = function(...) + local res = {} + for i = 1, select('#', ...) do + local name = select(i, ...) + res[name] = setmetatable({}, {__tostring = function() return 'enum: ' .. name end}) + end + return res +end + +string.encoding = enum('ascii', 'utf8', 'shift_jis', 'binary') -- Returns a function that returns the string when called. function string.fn(str) @@ -195,9 +199,9 @@ do local index = from local search = pattern:it(encoding):pack() local length = #search - for c in str:it(encoding, from, to - offset + 1) do + for c in str:it(encoding, from, to - offset) do local position = 0 - for check in str:it(encoding, index + #c, index + offset) do + for check in str:it(encoding, index, index + offset) do position = position + 1 if check ~= search[position] then break @@ -735,32 +739,28 @@ do local startpos, endpos local match while pos <= to do - -- Find the next occurence of sep. startpos, endpos = str:find(sep, encoding, pos, to, raw) - -- If found, get the substring and append it to the table. - if startpos then - match = str:sub(pos, startpos - 1) + if not startpos then count = count + 1 - res[count] = match + res[count] = str:sub(pos) + break + end - if include then - count = count + 1 - res[count] = str:sub(startpos, endpos) - end + match = str:sub(pos, startpos - 1) + count = count + 1 + res[count] = match - -- If maximum number of splits reached, return - if count == maxsplit - 1 then - count = count + 1 - res[count] = str:sub(endpos + 1) - break - end - pos = endpos + 1 - -- If not found, no more separators to split, append the remaining string. - else + if include then count = count + 1 - res[count] = str:sub(pos) + res[count] = str:sub(startpos, endpos) + end + + if count == maxsplit - 1 then + count = count + 1 + res[count] = str:sub(endpos + 1) break end + pos = endpos + 1 end return res, count diff --git a/addons/libs/tables.lua b/addons/libs/tables.lua index 4db1435a2d..644b33cb26 100644 --- a/addons/libs/tables.lua +++ b/addons/libs/tables.lua @@ -83,19 +83,6 @@ function class(o) return mt and mt.__class or type(o) end --- Packs an iterator function into a table -function functions.pack(fn) - local res = {} - local value = fn() - local count = 0 - while value ~= nil do - count = count + 1 - res[count] = value - value = fn() - end - return setmetatable(res, _meta.T) -end - -- Returns a function that returns the table when called. function table.fn(t) return functions.const(t) From dfc416ee609b99b603e33211b6f31a87792073a6 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Fri, 5 Apr 2024 14:29:19 +0100 Subject: [PATCH 0988/1002] Update send.lua (#2345) * Update send.lua Initial refactoring by Arcon * Update send.lua Tentative fix for a couple quirks caused by splitting the `target` arg off `...` * Update send.lua Added obligatory `` argument to `@debug` Moved debug prints around for simplicity Fixed bugs: - a stray `:upper()` had survived the refactoring - a `@job` target that was different from the sender main job would be lost in the void and not passed on * Update send.lua --- addons/send/send.lua | 150 ++++++++++++++++++------------------------- 1 file changed, 62 insertions(+), 88 deletions(-) diff --git a/addons/send/send.lua b/addons/send/send.lua index 65c53f0ca0..b1ab80a413 100644 --- a/addons/send/send.lua +++ b/addons/send/send.lua @@ -5,60 +5,61 @@ _addon.author = 'Byrth, Lili' local debug = false +require('functions') require('chat') -windower.register_event('addon command', function (...) - if ...:lower() == '@debug' then - debug = not debug - windower.add_to_chat(55, 'send: debug ' .. tostring(debug)) +windower.register_event('addon command', function(target, ...) + if not target then + error('No target provided.') return end - local term = T{...}:map(function(str) - str = windower.convert_auto_trans(str):strip_format() - if str:find(' ', string.encoding.shift_jis) then - return str:enclose('"') - end - return str + if not ... then + error('No command provided.') + return + end + + target = target:lower() + + if target == '@debug' then + local arg = (... == 'on' or ... == 'off') and ... or error('Invalid argument. Usage: send @debug ') + debug = arg == 'on' + return windower.add_to_chat(55, 'send: debug ' .. tostring(debug)) + end + + local command = T{...}:map(string.strip_format .. windower.convert_auto_trans):map(function(str) + return str:find(' ', string.encoding.shift_jis) and str:enclose('"') or str end):sconcat():gsub('<(%a+)id>', function(target_string) local entity = windower.ffxi.get_mob_by_target(target_string) return entity and entity.id or '<' .. target_string .. 'id>' end) - if debug then - windower.add_to_chat(207, 'send (debug): '..term) - end - - local broken_init = split(term, ' ') - local qual = table.remove(broken_init, 1):lower() local player = windower.ffxi.get_player() - if #broken_init < 1 then - return - end - - if player and qual == player['name']:lower() then - relevant_msg(table.concat(broken_init, ' ')) + if player and target == player['name']:lower() then + execute_command(command) return - elseif qual == '@all' or qual == '@'..player.main_job:lower() then - if player then - relevant_msg(table.concat(broken_init, ' ')) - end - elseif qual:startswith('@party') then + elseif player and target == '@all' or target == '@'..player.main_job:lower() then + execute_command(command) + elseif target == '@party' then if player then - relevant_msg(table.concat(broken_init, ' ')) + execute_command(command) end - local qual = qual .. windower.ffxi.get_player().name - term = qual .. ' ' .. table.concat(broken_init, ' ') - elseif qual:startswith('@zone') then + target = target .. player.name + elseif target == '@zone' then if player then - relevant_msg(table.concat(broken_init, ' ')) + execute_command(command) end - local qual = qual .. windower.ffxi.get_info().zone - term = qual .. ' ' .. table.concat(broken_init, ' ') + target = target .. windower.ffxi.get_info().zone end - windower.send_ipc_message('send ' .. term) + command = 'send ' .. target .. ' ' .. command + + if debug then + windower.add_to_chat(207, 'send (debug): ' .. command) + end + + windower.send_ipc_message(command) end) windower.register_event('ipc message', function (msg) @@ -66,74 +67,47 @@ windower.register_event('ipc message', function (msg) windower.add_to_chat(207, 'send receive (debug): ' .. msg) end - local broken = split(msg, ' ') - local command = table.remove(broken, 1) - - if command ~= 'send' or #broken < 2 then + local info = windower.ffxi.get_info() + if not info.logged_in then return end - local qual = table.remove(broken, 1) - local player = windower.ffxi.get_player() - if not player then + local split = msg:split(' ', string.encoding.shift_jis, 3) + if #split < 3 or split[1] ~= 'send' then return end - if qual:lower() == player.name:lower() then - relevant_msg(table.concat(broken, ' ')) - elseif string.char(qual:byte(1)) == '@' then - local arg = string.char(qual:byte(2, qual:len())):upper() + local target = split[2] + local command = split[3] + + local player = windower.ffxi.get_player() + + if target:lower() == player.name:lower() then + execute_command(command) + elseif target:startswith('@') then + local arg = target:sub(2):lower() - if arg == player.main_job:upper() or arg == 'ALL' or arg == 'OTHERS' then - relevant_msg(table.concat(broken, ' ')) - elseif arg:startswith('PARTY') then - local name = arg:sub(6, #arg):lower() + if arg == player.main_job:lower() or arg == 'all' or arg == 'others' then + execute_command(command) + elseif arg:startswith('party') then + local sender = arg:sub(6, #arg):lower() local party = windower.ffxi.get_party() - local sameparty = function() - for i=1, 5 do - local idx = 'p'..i - if party[idx] and party[idx].name:lower() == name then - return true - end + for i = 1, 5 do + local idx = 'p'..i + if party[idx] and party[idx].name:lower() == sender then + execute_command(command) + return end - end() - - if sameparty then - relevant_msg(table.concat(broken, ' ')) end - elseif arg:upper():startswith('ZONE') then - local samezone = tonumber(arg:sub(5, #arg)) == windower.ffxi.get_info().zone - - if samezone then - relevant_msg(table.concat(broken, ' ')) + elseif arg:startswith('zone') then + if tonumber(arg:sub(5)) == info.zone then + execute_command(command) end end end end) -function split(msg, match) - if msg == nil then return '' end - local length = msg:len() - local splitarr = {} - local u = 1 - while u <= length do - local nextanch = msg:find(match, string.encoding.shift_jis, u) - if nextanch ~= nil then - splitarr[#splitarr + 1] = msg:sub(u, nextanch - match:len()) - if nextanch ~= length then - u = nextanch + match:len() - else - u = length - end - else - splitarr[#splitarr + 1] = msg:sub(u, length) - u = length + 1 - end - end - return splitarr -end - -function relevant_msg(msg) +function execute_command(msg) if msg:sub(1, 2) == '//' then windower.send_command(msg:sub(3)) elseif msg:sub(1, 1) == '/' then From 3713505e00ca0b61cdab892c4878875a60053bfb Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Fri, 5 Apr 2024 15:30:05 +0200 Subject: [PATCH 0989/1002] Updated .gitignore --- .gitignore | 215 +---------------------------------------------------- 1 file changed, 1 insertion(+), 214 deletions(-) diff --git a/.gitignore b/.gitignore index b9d6bd92f5..faa18382a3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,215 +1,2 @@ -################# -## Eclipse -################# +.vscode -*.pydevproject -.project -.metadata -bin/ -tmp/ -*.tmp -*.bak -*.swp -*~.nib -local.properties -.classpath -.settings/ -.loadpath - -# External tool builders -.externalToolBuilders/ - -# Locally stored "Eclipse launch configurations" -*.launch - -# CDT-specific -.cproject - -# PDT-specific -.buildpath - - -################# -## Visual Studio -################# - -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. - -# User-specific files -*.suo -*.user -*.sln.docstates - -# Build results - -[Dd]ebug/ -[Rr]elease/ -x64/ -build/ -[Bb]in/ -[Oo]bj/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -*_i.c -*_p.c -*.ilk -*.meta -*.obj -*.pch -*.pdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.log -*.scc - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opensdf -*.sdf -*.cachefile - -# Visual Studio profiler -*.psess -*.vsp -*.vspx - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# NCrunch -*.ncrunch* -.*crunch*.local.xml - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.Publish.xml -*.pubxml - -# NuGet Packages Directory -## TODO: If you have NuGet Package Restore enabled, uncomment the next line -#packages/ - -# Windows Azure Build Output -csx -*.build.csdef - -# Windows Store app package directory -AppPackages/ - -# Others -sql/ -*.Cache -ClientBin/ -[Ss]tyle[Cc]op.* -~$* -*~ -*.dbmdl -*.[Pp]ublish.xml -*.pfx -*.publishsettings - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file to a newer -# Visual Studio version. Backup files are not needed, because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm - -# SQL Server files -App_Data/*.mdf -App_Data/*.ldf - -############# -## Windows detritus -############# - -# Windows image file caches -Thumbs.db -ehthumbs.db - -# Folder config file -Desktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Mac crap -.DS_Store - - -############# -## Python -############# - -*.py[co] - -# Packages -*.egg -*.egg-info -dist/ -build/ -eggs/ -parts/ -var/ -sdist/ -develop-eggs/ -.installed.cfg - -# Installer logs -pip-log.txt - -# Unit test / coverage reports -.coverage -.tox - -#Translations -*.mo - -#Mr Developer -.mr.developer.cfg From 904441319153041cfa316eea66dc099e80cac5d4 Mon Sep 17 00:00:00 2001 From: Stjepan Bakrac Date: Tue, 9 Apr 2024 09:55:43 +0200 Subject: [PATCH 0990/1002] Libs/Tables: Adjusted table functions to iterate generically --- addons/libs/tables.lua | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/addons/libs/tables.lua b/addons/libs/tables.lua index 644b33cb26..6f6c4fd614 100644 --- a/addons/libs/tables.lua +++ b/addons/libs/tables.lua @@ -90,18 +90,13 @@ end -- Checks if a table is an array, only having sequential integer keys. function table.isarray(t) - local count = 0 - for _, _ in pairs(t) do - count = count + 1 - end - - return count == #t + return table.count(t) == #t end -- Returns the number of elements in a table. function table.length(t) local count = 0 - for _ in pairs(t) do + for _ in table.it(t) do count = count + 1 end @@ -123,7 +118,7 @@ end -- Returns true if searchval is in t. function table.contains(t, searchval) - for key, val in pairs(t) do + for val in table.it(t) do if val == searchval then return true end @@ -148,7 +143,8 @@ function table.extend(t, t_extend) if type(t_extend) ~= 'table' then return table.append(t, t_extend) end - for _, val in ipairs(t_extend) do + + for val in table.it(t_extend) do table.append(t, val) end @@ -164,7 +160,7 @@ function table.count(t, fn) end local count = 0 - for _, val in pairs(t) do + for val in table.it(t) do if fn(val) then count = count + 1 end @@ -247,7 +243,6 @@ function table.keyset(t) return setmetatable(res, _meta.S) end - local res = {} local i = 0 for key in pairs(t) do i = i + 1 @@ -578,7 +573,7 @@ function table.empty(t, rec) return next(t) == nil end - for _, val in pairs(t) do + for val in table.it(t) do if type(val) ~= 'table' then return false; else From 3d730cdb4a4b3965c08543a6a8c72d706146bffb Mon Sep 17 00:00:00 2001 From: defxi Date: Mon, 15 Apr 2024 19:30:52 -0400 Subject: [PATCH 0991/1002] Fixed 0x00A field typo --- addons/libs/packets/fields.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/libs/packets/fields.lua b/addons/libs/packets/fields.lua index 3fc1231b1e..40591df1d4 100644 --- a/addons/libs/packets/fields.lua +++ b/addons/libs/packets/fields.lua @@ -1296,7 +1296,7 @@ fields.incoming[0x00A] = L{ {ctype='signed short', label='DEX'}, -- CE {ctype='signed short', label='VIT'}, -- D0 {ctype='signed short', label='AGI'}, -- D2 - {ctype='signed short', label='IND'}, -- F4 + {ctype='signed short', label='INT'}, -- F4 {ctype='signed short', label='MND'}, -- D6 {ctype='signed short', label='CHR'}, -- D8 {ctype='signed short', label='STR Bonus'}, -- DA From 85ce74f19dcb1f5b1ef2aabe5af5816b39004b62 Mon Sep 17 00:00:00 2001 From: Posimagi Date: Sat, 20 Apr 2024 03:11:28 -0700 Subject: [PATCH 0992/1002] [pointwatch] support true master levels --- addons/pointwatch/pointwatch.lua | 56 +++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/addons/pointwatch/pointwatch.lua b/addons/pointwatch/pointwatch.lua index aa67a7a4a5..cbed5ce58f 100644 --- a/addons/pointwatch/pointwatch.lua +++ b/addons/pointwatch/pointwatch.lua @@ -46,6 +46,60 @@ box = texts.new('${current_string}',settings.text_box_settings,settings) box.current_string = '' box:show() +tnml = { + [2500] = 0, + [5550] = 1, + [8721] = 2, + [11919] = 3, + [15122] = 4, + [18327] = 5, + [21532] = 6, + [24737] = 7, + [27942] = 8, + [31147] = 9, + [41205] = 10, + [48130] = 11, + [53677] = 12, + [58618] = 13, + [63292] = 14, + [67848] = 15, + [72353] = 16, + [76835] = 17, + [81307] = 18, + [85775] = 19, + [109112] = 20, + [127014] = 21, + [141329] = 22, + [153277] = 23, + [163663] = 24, + [173018] = 25, + [181692] = 26, + [189917] = 27, + [197845] = 28, + [205578] = 29, + [258409] = 30, + [307400] = 31, + [353012] = 32, + [395691] = 33, + [435673] = 34, + [473392] = 35, + [509085] = 36, + [542995] = 37, + [575336] = 38, + [606296] = 39, + [769426] = 40, + [951369] = 41, + [1154006] = 42, + [1379407] = 43, + [1629848] = 44, + [1907833] = 45, + [2216116] = 46, + [2557728] = 47, + [2936001] = 48, + [3354601] = 49, + [3817561] = 50 +} + granule_KIs = res.key_items:en(function(x) return x:endswith('granules of time') end):map(function(ki) return { id=ki.id, @@ -120,7 +174,7 @@ packet_handlers = { accolades.current = p['Unity Points'] ep.current = p['Current Exemplar Points'] ep.tnml = p['Required Exemplar Points'] - ep.master_level = p['Master Level'] + ep.master_level = tnml[p['Required Exemplar Points']] end, [0x063] = function(org) local p = packets.parse('incoming',org) From dd8743f593838c6f32c8e0e81ac1f76fb30a55d1 Mon Sep 17 00:00:00 2001 From: Posimagi Date: Sat, 20 Apr 2024 23:07:21 -0700 Subject: [PATCH 0993/1002] [pointwatch] clean up tnml table --- addons/pointwatch/pointwatch.lua | 54 ------------------------------- addons/pointwatch/statics.lua | 55 ++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 54 deletions(-) diff --git a/addons/pointwatch/pointwatch.lua b/addons/pointwatch/pointwatch.lua index cbed5ce58f..f1986c5de6 100644 --- a/addons/pointwatch/pointwatch.lua +++ b/addons/pointwatch/pointwatch.lua @@ -46,60 +46,6 @@ box = texts.new('${current_string}',settings.text_box_settings,settings) box.current_string = '' box:show() -tnml = { - [2500] = 0, - [5550] = 1, - [8721] = 2, - [11919] = 3, - [15122] = 4, - [18327] = 5, - [21532] = 6, - [24737] = 7, - [27942] = 8, - [31147] = 9, - [41205] = 10, - [48130] = 11, - [53677] = 12, - [58618] = 13, - [63292] = 14, - [67848] = 15, - [72353] = 16, - [76835] = 17, - [81307] = 18, - [85775] = 19, - [109112] = 20, - [127014] = 21, - [141329] = 22, - [153277] = 23, - [163663] = 24, - [173018] = 25, - [181692] = 26, - [189917] = 27, - [197845] = 28, - [205578] = 29, - [258409] = 30, - [307400] = 31, - [353012] = 32, - [395691] = 33, - [435673] = 34, - [473392] = 35, - [509085] = 36, - [542995] = 37, - [575336] = 38, - [606296] = 39, - [769426] = 40, - [951369] = 41, - [1154006] = 42, - [1379407] = 43, - [1629848] = 44, - [1907833] = 45, - [2216116] = 46, - [2557728] = 47, - [2936001] = 48, - [3354601] = 49, - [3817561] = 50 -} - granule_KIs = res.key_items:en(function(x) return x:endswith('granules of time') end):map(function(ki) return { id=ki.id, diff --git a/addons/pointwatch/statics.lua b/addons/pointwatch/statics.lua index 5afd4af9e0..2c3f4752c5 100644 --- a/addons/pointwatch/statics.lua +++ b/addons/pointwatch/statics.lua @@ -78,6 +78,61 @@ other_table = {Crimson=10,Azure=10,Amber=10,Alabaster=10,Obsidian=20} dynamis_map = {[185]=city_table,[186]=city_table,[187]=city_table,[188]=city_table, [134]=other_table,[135]=other_table,[39]=other_table,[40]=other_table,[41]=other_table,[42]=other_table} +-- Master Level EP table +tnml = { + [2500] = 0, + [5550] = 1, + [8721] = 2, + [11919] = 3, + [15122] = 4, + [18327] = 5, + [21532] = 6, + [24737] = 7, + [27942] = 8, + [31147] = 9, + [41205] = 10, + [48130] = 11, + [53677] = 12, + [58618] = 13, + [63292] = 14, + [67848] = 15, + [72353] = 16, + [76835] = 17, + [81307] = 18, + [85775] = 19, + [109112] = 20, + [127014] = 21, + [141329] = 22, + [153277] = 23, + [163663] = 24, + [173018] = 25, + [181692] = 26, + [189917] = 27, + [197845] = 28, + [205578] = 29, + [258409] = 30, + [307400] = 31, + [353012] = 32, + [395691] = 33, + [435673] = 34, + [473392] = 35, + [509085] = 36, + [542995] = 37, + [575336] = 38, + [606296] = 39, + [769426] = 40, + [951369] = 41, + [1154006] = 42, + [1379407] = 43, + [1629848] = 44, + [1907833] = 45, + [2216116] = 46, + [2557728] = 47, + [2936001] = 48, + [3354601] = 49, + [3817561] = 50 +} + -- Not technically static, but sets the initial values for all features: function initialize() cp = { From 26179d356a10a95c8e6049b0c94240e8707cbc46 Mon Sep 17 00:00:00 2001 From: Posimagi Date: Sun, 21 Apr 2024 01:18:40 -0700 Subject: [PATCH 0994/1002] [pointwatch] update version number --- addons/pointwatch/pointwatch.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/pointwatch/pointwatch.lua b/addons/pointwatch/pointwatch.lua index f1986c5de6..3a5afeb2b6 100644 --- a/addons/pointwatch/pointwatch.lua +++ b/addons/pointwatch/pointwatch.lua @@ -36,7 +36,7 @@ require('chat') _addon.name = 'PointWatch' _addon.author = 'Byrth' -_addon.version = 0.220327 +_addon.version = 0.240420 _addon.command = 'pw' settings = config.load('data\\settings.xml',default_settings) From 4366e999f6d08733cf5ff6c4233bac4d7bb33edc Mon Sep 17 00:00:00 2001 From: Posimagi Date: Sun, 21 Apr 2024 12:36:51 -0700 Subject: [PATCH 0995/1002] [pointwatch] create a new var ep.true_master_level to support display of true master level under level sync without removing synced master level option --- addons/pointwatch/pointwatch.lua | 3 ++- addons/pointwatch/statics.lua | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/addons/pointwatch/pointwatch.lua b/addons/pointwatch/pointwatch.lua index 3a5afeb2b6..045c6080bb 100644 --- a/addons/pointwatch/pointwatch.lua +++ b/addons/pointwatch/pointwatch.lua @@ -120,7 +120,8 @@ packet_handlers = { accolades.current = p['Unity Points'] ep.current = p['Current Exemplar Points'] ep.tnml = p['Required Exemplar Points'] - ep.master_level = tnml[p['Required Exemplar Points']] + ep.master_level = p['Master Level'] + ep.true_master_level = tnml[p['Required Exemplar Points']] end, [0x063] = function(org) local p = packets.parse('incoming',org) diff --git a/addons/pointwatch/statics.lua b/addons/pointwatch/statics.lua index 2c3f4752c5..e4c72469bc 100644 --- a/addons/pointwatch/statics.lua +++ b/addons/pointwatch/statics.lua @@ -174,6 +174,7 @@ function initialize() rate = 0, tnml = 0, master_level = 0, + true_master_level = 0; } sparks = { From 3cbde153da4d989305e91d758efb66903595d055 Mon Sep 17 00:00:00 2001 From: Posimagi Date: Sun, 21 Apr 2024 12:41:19 -0700 Subject: [PATCH 0996/1002] [pointwatch] add "ep" format string for watching only EP --- addons/pointwatch/statics.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/pointwatch/statics.lua b/addons/pointwatch/statics.lua index e4c72469bc..78dc749cdb 100644 --- a/addons/pointwatch/statics.lua +++ b/addons/pointwatch/statics.lua @@ -31,7 +31,8 @@ default_settings = { default = "string.format('%d/%dXP %sMerits XP/hr:%.1fk %sJP CP/hr:%.1fk %d/%dEP EP/hr:%.1fk',xp.current,xp.tnl,max_color('%5.2f':format(math.floor(lp.current/lp.tnm*100)/100+lp.number_of_merits),lp.current/lp.tnm+lp.number_of_merits,lp.maximum_merits,58,147,191),math.floor(xp.rate/100)/10,max_color('%6.2f':format(math.floor(cp.current/cp.tnjp*100)/100+cp.number_of_job_points),cp.current/cp.tnjp+cp.number_of_job_points,500,58,147,191),math.floor(cp.rate/100)/10,ep.current,ep.tnml,math.floor(ep.rate/100)/10)", dynamis = "string.format('%d/%dXP %sMerits XP/hr:%.1fk %sJP CP/hr:%.1fk %d/%dEP %s %s',xp.current,xp.tnl,max_color('%5.2f':format(math.floor(lp.current/lp.tnm*100)/100+lp.number_of_merits),lp.current/lp.tnm+lp.number_of_merits,lp.maximum_merits,58,147,191),math.floor(xp.rate/100)/10,max_color('%6.2f':format(math.floor(cp.current/cp.tnjp*100)/100+cp.number_of_job_points),cp.current/cp.tnjp+cp.number_of_job_points,500,58,147,191),math.floor(cp.rate/100)/10,ep.current,ep.tnml,dynamis.KIs,dynamis.time_remaining or 0)", abyssea = "string.format('%d/%dXP %sMerits XP/hr:%.1fk %sJP CP/hr:%.1fk %d/%dEP Amber:%d Azure:%d Ruby:%d Pearl:%d Ebon:%d Silver:%d Gold:%d Time-Remaining:%d',xp.current,xp.tnl,max_color('%5.2f':format(math.floor(lp.current/lp.tnm*100)/100+lp.number_of_merits),lp.current/lp.tnm+lp.number_of_merits,lp.maximum_merits,58,147,191),math.floor(xp.rate/100)/10,max_color('%6.2f':format(math.floor(cp.current/cp.tnjp*100)/100+cp.number_of_job_points),cp.current/cp.tnjp+cp.number_of_job_points,500,58,147,191),math.floor(cp.rate/100)/10,ep.current,ep.tnml,abyssea.amber or 0,abyssea.azure or 0,abyssea.ruby or 0,abyssea.pearlescent or 0,abyssea.ebon or 0,abyssea.silvery or 0,abyssea.golden or 0,abyssea.time_remaining or 0)", - }, + ep = "string.format('ML%d %d/%dEP EP/hr:%.1fk',ep.true_master_level,ep.current,ep.tnml,math.floor(ep.rate/100)/10)", + }, text_box_settings = { pos = { x = 0, From 6f48dffabba421c16be3037f083feeb00a32b5fd Mon Sep 17 00:00:00 2001 From: Posimagi Date: Sun, 28 Apr 2024 14:05:53 -0700 Subject: [PATCH 0997/1002] [pointwatch] make true master level the default --- addons/pointwatch/pointwatch.lua | 4 ++-- addons/pointwatch/statics.lua | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/addons/pointwatch/pointwatch.lua b/addons/pointwatch/pointwatch.lua index 045c6080bb..5e3f3890ac 100644 --- a/addons/pointwatch/pointwatch.lua +++ b/addons/pointwatch/pointwatch.lua @@ -120,8 +120,8 @@ packet_handlers = { accolades.current = p['Unity Points'] ep.current = p['Current Exemplar Points'] ep.tnml = p['Required Exemplar Points'] - ep.master_level = p['Master Level'] - ep.true_master_level = tnml[p['Required Exemplar Points']] + ep.master_level = tnml[p['Required Exemplar Points']] + ep.synced_master_level = p['Master Level'] end, [0x063] = function(org) local p = packets.parse('incoming',org) diff --git a/addons/pointwatch/statics.lua b/addons/pointwatch/statics.lua index 78dc749cdb..ca1f2d7c3a 100644 --- a/addons/pointwatch/statics.lua +++ b/addons/pointwatch/statics.lua @@ -28,10 +28,9 @@ --Default settings file: default_settings = { strings = { - default = "string.format('%d/%dXP %sMerits XP/hr:%.1fk %sJP CP/hr:%.1fk %d/%dEP EP/hr:%.1fk',xp.current,xp.tnl,max_color('%5.2f':format(math.floor(lp.current/lp.tnm*100)/100+lp.number_of_merits),lp.current/lp.tnm+lp.number_of_merits,lp.maximum_merits,58,147,191),math.floor(xp.rate/100)/10,max_color('%6.2f':format(math.floor(cp.current/cp.tnjp*100)/100+cp.number_of_job_points),cp.current/cp.tnjp+cp.number_of_job_points,500,58,147,191),math.floor(cp.rate/100)/10,ep.current,ep.tnml,math.floor(ep.rate/100)/10)", - dynamis = "string.format('%d/%dXP %sMerits XP/hr:%.1fk %sJP CP/hr:%.1fk %d/%dEP %s %s',xp.current,xp.tnl,max_color('%5.2f':format(math.floor(lp.current/lp.tnm*100)/100+lp.number_of_merits),lp.current/lp.tnm+lp.number_of_merits,lp.maximum_merits,58,147,191),math.floor(xp.rate/100)/10,max_color('%6.2f':format(math.floor(cp.current/cp.tnjp*100)/100+cp.number_of_job_points),cp.current/cp.tnjp+cp.number_of_job_points,500,58,147,191),math.floor(cp.rate/100)/10,ep.current,ep.tnml,dynamis.KIs,dynamis.time_remaining or 0)", - abyssea = "string.format('%d/%dXP %sMerits XP/hr:%.1fk %sJP CP/hr:%.1fk %d/%dEP Amber:%d Azure:%d Ruby:%d Pearl:%d Ebon:%d Silver:%d Gold:%d Time-Remaining:%d',xp.current,xp.tnl,max_color('%5.2f':format(math.floor(lp.current/lp.tnm*100)/100+lp.number_of_merits),lp.current/lp.tnm+lp.number_of_merits,lp.maximum_merits,58,147,191),math.floor(xp.rate/100)/10,max_color('%6.2f':format(math.floor(cp.current/cp.tnjp*100)/100+cp.number_of_job_points),cp.current/cp.tnjp+cp.number_of_job_points,500,58,147,191),math.floor(cp.rate/100)/10,ep.current,ep.tnml,abyssea.amber or 0,abyssea.azure or 0,abyssea.ruby or 0,abyssea.pearlescent or 0,abyssea.ebon or 0,abyssea.silvery or 0,abyssea.golden or 0,abyssea.time_remaining or 0)", - ep = "string.format('ML%d %d/%dEP EP/hr:%.1fk',ep.true_master_level,ep.current,ep.tnml,math.floor(ep.rate/100)/10)", + default = "string.format('%d/%dXP %sMerits XP/hr:%.1fk %sJP CP/hr:%.1fk ML%d %d/%dEP EP/hr:%.1fk',xp.current,xp.tnl,max_color('%5.2f':format(math.floor(lp.current/lp.tnm*100)/100+lp.number_of_merits),lp.current/lp.tnm+lp.number_of_merits,lp.maximum_merits,58,147,191),math.floor(xp.rate/100)/10,max_color('%6.2f':format(math.floor(cp.current/cp.tnjp*100)/100+cp.number_of_job_points),cp.current/cp.tnjp+cp.number_of_job_points,500,58,147,191),math.floor(cp.rate/100)/10,ep.master_level,ep.current,ep.tnml,math.floor(ep.rate/100)/10)", + dynamis = "string.format('%d/%dXP %sMerits XP/hr:%.1fk %sJP CP/hr:%.1fk ML%d %d/%dEP %s %s',xp.current,xp.tnl,max_color('%5.2f':format(math.floor(lp.current/lp.tnm*100)/100+lp.number_of_merits),lp.current/lp.tnm+lp.number_of_merits,lp.maximum_merits,58,147,191),math.floor(xp.rate/100)/10,max_color('%6.2f':format(math.floor(cp.current/cp.tnjp*100)/100+cp.number_of_job_points),cp.current/cp.tnjp+cp.number_of_job_points,500,58,147,191),math.floor(cp.rate/100)/10,ep.master_level,ep.current,ep.tnml,dynamis.KIs,dynamis.time_remaining or 0)", + abyssea = "string.format('%d/%dXP %sMerits XP/hr:%.1fk %sJP CP/hr:%.1fk ML%d %d/%dEP Amber:%d Azure:%d Ruby:%d Pearl:%d Ebon:%d Silver:%d Gold:%d Time-Remaining:%d',xp.current,xp.tnl,max_color('%5.2f':format(math.floor(lp.current/lp.tnm*100)/100+lp.number_of_merits),lp.current/lp.tnm+lp.number_of_merits,lp.maximum_merits,58,147,191),math.floor(xp.rate/100)/10,max_color('%6.2f':format(math.floor(cp.current/cp.tnjp*100)/100+cp.number_of_job_points),cp.current/cp.tnjp+cp.number_of_job_points,500,58,147,191),math.floor(cp.rate/100)/10,ep.master_level,ep.current,ep.tnml,abyssea.amber or 0,abyssea.azure or 0,abyssea.ruby or 0,abyssea.pearlescent or 0,abyssea.ebon or 0,abyssea.silvery or 0,abyssea.golden or 0,abyssea.time_remaining or 0)", }, text_box_settings = { pos = { @@ -175,7 +174,7 @@ function initialize() rate = 0, tnml = 0, master_level = 0, - true_master_level = 0; + synced_master_level = 0; } sparks = { From 5e11831617fd01e2b1ce87e55af62a5a7ebc6167 Mon Sep 17 00:00:00 2001 From: lili-ffxi <40600148+lili-ffxi@users.noreply.github.com> Date: Wed, 1 May 2024 22:05:05 +0100 Subject: [PATCH 0998/1002] Update helper_functions.lua (#2352) Preserve numerical values for spell.skill and spell.element as they're potentially useful in multiple scenarios, most often when comparing stuff against resources --- addons/GearSwap/helper_functions.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/GearSwap/helper_functions.lua b/addons/GearSwap/helper_functions.lua index 1afaa222c0..68f82c909d 100644 --- a/addons/GearSwap/helper_functions.lua +++ b/addons/GearSwap/helper_functions.lua @@ -1072,10 +1072,12 @@ function spell_complete(rline) end if rline.skill and tonumber(rline.skill) then + rline.skill_id = rline.skill rline.skill = res.skills[rline.skill][language] end if rline.element and tonumber(rline.element) then + rline.element_id = rline.element rline.element = res.elements[rline.element][language] end From d0e7b5bdbbb3a777789305986011f96a33a35f44 Mon Sep 17 00:00:00 2001 From: Posimagi Date: Thu, 2 May 2024 12:03:57 -0700 Subject: [PATCH 0999/1002] [pointwatch] minor fix for EP table value (#2353) --- addons/pointwatch/statics.lua | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/addons/pointwatch/statics.lua b/addons/pointwatch/statics.lua index ca1f2d7c3a..eb53cb521d 100644 --- a/addons/pointwatch/statics.lua +++ b/addons/pointwatch/statics.lua @@ -69,7 +69,6 @@ approved_commands = {show={n=0},hide={n=0},pos={n=2,t='number'},pos_x={n=1,t='nu font={n=2,t='string'},size={n=1,t='number'},pad={n=1,t='number'},color={n=3,t='number'},alpha={n=1,t='number'}, transparency={n=1,t='number'},bg_color={n=3,t='number'},bg_alpha={n=1,t='number'},bg_transparency={n=1,t='number'}} - -- Dynamis TE lists: city_table = {Crimson=10,Azure=10,Amber=10,Alabaster=15,Obsidian=15} other_table = {Crimson=10,Azure=10,Amber=10,Alabaster=10,Obsidian=20} @@ -113,7 +112,7 @@ tnml = { [258409] = 30, [307400] = 31, [353012] = 32, - [395691] = 33, + [395651] = 33, [435673] = 34, [473392] = 35, [509085] = 36, @@ -145,7 +144,6 @@ function initialize() maximum_job_points = 500, } - xp = { registry = {}, total = 0, @@ -199,7 +197,6 @@ function initialize() time_remaining = 0, } - local info = windower.ffxi.get_info() frame_count = 0 From fa7696abcdc43fa295d1709b51db1191e0e49bf9 Mon Sep 17 00:00:00 2001 From: Traelblaser Date: Sun, 5 May 2024 14:43:25 -0400 Subject: [PATCH 1000/1002] Fix the /drieddate1 issue --- addons/shortcuts/helper_functions.lua | 30 +++++++++++++++++++++++++++ addons/shortcuts/shortcuts.lua | 12 +++++++++-- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/addons/shortcuts/helper_functions.lua b/addons/shortcuts/helper_functions.lua index 8ce9ca5838..ae21e9825d 100644 --- a/addons/shortcuts/helper_functions.lua +++ b/addons/shortcuts/helper_functions.lua @@ -107,7 +107,37 @@ function strip_non_alphanumeric_keep_plus(name) return name:gsub('[^%w+]',''):lower() end +----------------------------------------------------------------------------------- +--Name: strip_non_alphanumeric_keep_plus_fix_hq() +--Args: +---- name (string): Name to be stripped +----------------------------------------------------------------------------------- +--Returns: +---- string with a gsubbed version of name that removes non-alphanumeric characters, +-------- but allows the character '+', and forces the string to lower-case. Does not +-------- convert numbers to roman numerals. If the resulting string ends with a +-------- number or numbers, will add a + in front of those numbers +----------------------------------------------------------------------------------- +function strip_non_alphanumeric_keep_plus_fix_hq(name) + return name:gsub('[^%w+]',''):lower():gsub('(%d+)$',fixhq):gsub("[+]+", "+") + --[[ + local first_step = name:gsub('[^%w+]',''):lower() + local second_step = first_step:gsub('(? Date: Sun, 5 May 2024 19:20:40 -0400 Subject: [PATCH 1001/1002] Fix issue with job point spells not being treated as spell Fix issue with scrolls and indi plates colliding with spells --- addons/shortcuts/helper_functions.lua | 25 ++++++------------------- addons/shortcuts/shortcuts.lua | 5 +++-- addons/shortcuts/statics.lua | 3 +++ 3 files changed, 12 insertions(+), 21 deletions(-) diff --git a/addons/shortcuts/helper_functions.lua b/addons/shortcuts/helper_functions.lua index ae21e9825d..80844b156a 100644 --- a/addons/shortcuts/helper_functions.lua +++ b/addons/shortcuts/helper_functions.lua @@ -118,24 +118,11 @@ end -------- convert numbers to roman numerals. If the resulting string ends with a -------- number or numbers, will add a + in front of those numbers ----------------------------------------------------------------------------------- - function strip_non_alphanumeric_keep_plus_fix_hq(name) return name:gsub('[^%w+]',''):lower():gsub('(%d+)$',fixhq):gsub("[+]+", "+") - --[[ - local first_step = name:gsub('[^%w+]',''):lower() - local second_step = first_step:gsub('(?= 99 and res.spells[id].levels[player.main_job_id] <= player.job_points[player.main_job:lower()].jp_spent))) or (res.spells[id].levels[player.sub_job_id] and res.spells[id].levels[player.sub_job_id] <= player.sub_job_level) ) then -- Should check to see if you know the spell return true elseif L(windower.ffxi.get_abilities()[resource] or {}):contains(id) then - return true + return true elseif resource == 'monster_skills' and player.main_job_id == 23 and (res.monstrosity[windower.ffxi.get_mjob_data().species].tp_moves[id] or 0) <= player.main_job_level then - return true + return true elseif resource == 'mounts' and math.floor((windower.packets.last_incoming(0x0AE):byte(math.floor(id/8)+5)%2^(id%8+1))/2^(id%8)) == 1 then - return true + return true elseif resource == 'items' then - return true + return true end end @@ -252,4 +239,4 @@ function debug_chat(str) else error('Debug chat is not a string',2) end -end \ No newline at end of file +end diff --git a/addons/shortcuts/shortcuts.lua b/addons/shortcuts/shortcuts.lua index 6f341ca6a4..7243d02868 100644 --- a/addons/shortcuts/shortcuts.lua +++ b/addons/shortcuts/shortcuts.lua @@ -344,7 +344,6 @@ end ---- string (sometimes '') depending what the logic says to do. ---- Sends a command if the command needs to be changed. ----------------------------------------------------------------------------------- -require("logger") function interp_text(splitline,offset,modified) -- Assume there was not a target suffix on the command. local preliminary_action_name = table.concat(splitline,' ',1+offset,splitline.n) @@ -375,6 +374,7 @@ function interp_text(splitline,offset,modified) local finalized_action_name_normalized_as_item = strip_non_alphanumeric_keep_plus_fix_hq(finalized_action_name) local finalized_action_name_normalized_as_nonitem = strip_non_alphanumeric_convert_digits_to_roman(finalized_action_name) + log(preliminary_action_name) log(preliminary_action_name_normalized_as_item) log(preliminary_action_name_normalized_as_nonitem) @@ -382,6 +382,7 @@ function interp_text(splitline,offset,modified) log('finalized') log(finalized_action_name_normalized_as_item) log(finalized_action_name_normalized_as_nonitem) + -- Note: The normalized 'item' name is almost strictly more specific than -- the normalized 'nonitem' name, and thus the former must be searched -- before the latter to avoid falsely matching the wrong entry. @@ -470,4 +471,4 @@ function interp_text(splitline,offset,modified) end lastsent = '' return modified,false -end +end \ No newline at end of file diff --git a/addons/shortcuts/statics.lua b/addons/shortcuts/statics.lua index 7c6e05a6e7..4b32c1e0ec 100644 --- a/addons/shortcuts/statics.lua +++ b/addons/shortcuts/statics.lua @@ -123,6 +123,8 @@ command2_list = { ['kneel']=emote_table, ['laugh']=emote_table, ['muted']=emote_table, + ['kneel']=emote_table, + ['laugh']=emote_table, ['no']=emote_table, ['nod']=emote_table, ['yes']=emote_table, @@ -190,6 +192,7 @@ language = 'english' -- windower.ffxi.get_info()['language']:lower() ----------------------------------------------------------------------------------- function make_abil(ind,res,id) validabils[ind] = validabils[ind] or L{} + if res == "items" and validabils[ind].n > 0 then return end validabils[ind]:append({res=res,id=id}) end From 1e6b34bdd788a4a24b9fe88ae1de467581b8f530 Mon Sep 17 00:00:00 2001 From: Traelblaser Date: Sun, 5 May 2024 19:26:25 -0400 Subject: [PATCH 1002/1002] Removed settings stuff Cleaned up debug statements Removed some duplicates with kneel/laugh --- addons/shortcuts/shortcuts.lua | 17 +---------------- addons/shortcuts/statics.lua | 2 -- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/addons/shortcuts/shortcuts.lua b/addons/shortcuts/shortcuts.lua index 7243d02868..3bb8d4ed40 100644 --- a/addons/shortcuts/shortcuts.lua +++ b/addons/shortcuts/shortcuts.lua @@ -117,16 +117,10 @@ default_aliases = { cw5="Curing Waltz V", hw="Healing Waltz" } -default_settings = { - include_items = false, -} aliases = config.load('data/aliases.xml', default_aliases) -settings = config.load('data/settings.xml', default_settings) config.save(aliases) -config.save(settings) setmetatable(aliases,nil) -setmetatable(settings,nil) require 'statics' @@ -374,15 +368,6 @@ function interp_text(splitline,offset,modified) local finalized_action_name_normalized_as_item = strip_non_alphanumeric_keep_plus_fix_hq(finalized_action_name) local finalized_action_name_normalized_as_nonitem = strip_non_alphanumeric_convert_digits_to_roman(finalized_action_name) - - log(preliminary_action_name) - log(preliminary_action_name_normalized_as_item) - log(preliminary_action_name_normalized_as_nonitem) - log('normalized: ', normalized_preliminary_action_name) - log('finalized') - log(finalized_action_name_normalized_as_item) - log(finalized_action_name_normalized_as_nonitem) - -- Note: The normalized 'item' name is almost strictly more specific than -- the normalized 'nonitem' name, and thus the former must be searched -- before the latter to avoid falsely matching the wrong entry. @@ -471,4 +456,4 @@ function interp_text(splitline,offset,modified) end lastsent = '' return modified,false -end \ No newline at end of file +end diff --git a/addons/shortcuts/statics.lua b/addons/shortcuts/statics.lua index 4b32c1e0ec..d01d825186 100644 --- a/addons/shortcuts/statics.lua +++ b/addons/shortcuts/statics.lua @@ -123,8 +123,6 @@ command2_list = { ['kneel']=emote_table, ['laugh']=emote_table, ['muted']=emote_table, - ['kneel']=emote_table, - ['laugh']=emote_table, ['no']=emote_table, ['nod']=emote_table, ['yes']=emote_table,