summaryrefslogtreecommitdiff
path: root/Data/BuiltIn/Libraries/lua-addons/addons/capetrader
diff options
context:
space:
mode:
Diffstat (limited to 'Data/BuiltIn/Libraries/lua-addons/addons/capetrader')
-rw-r--r--Data/BuiltIn/Libraries/lua-addons/addons/capetrader/README.md159
-rw-r--r--Data/BuiltIn/Libraries/lua-addons/addons/capetrader/allAugPaths.lua87
-rw-r--r--Data/BuiltIn/Libraries/lua-addons/addons/capetrader/capetrader.lua521
-rw-r--r--Data/BuiltIn/Libraries/lua-addons/addons/capetrader/jobToCapeMap.lua50
-rw-r--r--Data/BuiltIn/Libraries/lua-addons/addons/capetrader/maxAugMap.lua81
-rw-r--r--Data/BuiltIn/Libraries/lua-addons/addons/capetrader/validItemNames.lua54
6 files changed, 952 insertions, 0 deletions
diff --git a/Data/BuiltIn/Libraries/lua-addons/addons/capetrader/README.md b/Data/BuiltIn/Libraries/lua-addons/addons/capetrader/README.md
new file mode 100644
index 0000000..f870836
--- /dev/null
+++ b/Data/BuiltIn/Libraries/lua-addons/addons/capetrader/README.md
@@ -0,0 +1,159 @@
+# Cape Trader
+Cape Trader is used to automate the process of augmenting ambuscade capes. The cape trader addon injects packets extensively so please take that into consideration and use this addon at you own risk. While there are some safeguards in this addon, there is still a risk that you can lose your abdhaljs thread,dust,sap and dye if you use this addon. Please read the usage notes and information on the prep and go commands carefully as well as the warnings section before deciding to use this addon.
+
+___
+### Usage notes
+
+Load the addon by using the following command:
+
+ //lua load capetrader
+
+There are some conditions that you need to meet in order to use the important go and prep commands:
+
+1. You must be in Mhaura and be within a distance of 6 to the Gorpa-Masorpa npc.
+
+2. If you have recently zoned into Mhaura you will have to wait to use the go command until your inventory loads, or if you have only recently logged in.
+
+3. Make sure there is only one of the given cape you want to augment in your inventory. For example if you are intending to augment an ogma's cape, there should only be one ogma's cape in your inventory.
+
+4. The go command takes a number as an input that represents the number of times you wish to augment your cape. It is possible you will lose your thread,dust,sap and dye if you enter a number that would take your augment past its possible maximum. For example suppose you have an ogma's cape already augmented with Dex+5 from a thread item. After using the **//ct prep run thread dex** command you enter **//ct go 20** command. There is a safeguard that will stop the augmentation process after augmenting your cape 15 times. However it is highly recommended that you enter the exact number of times you need to max a particular augment path just in case.
+
+5. It is also possible to lose augment items if you try to augment a cape with a different path than is already present. Suppose again you have an ogma's cape augmented with DEX+5 via threads. If you enter the **//ct prep run thread str** and then the **//ct go 15** command intending to augment your cape with str, **you might lose these 15 threads**. There is now a safeguard to avoid this, but it is highly recommended you make sure your intended augment path already matches what is on the cape.
+
+6. Make sure you do not move items around your various inventory bags while the augmentation process is ongoing. You can mess around with your inventory after you get the ending message, otherwise you might interrupt the augmentation process and need to reload the addon.
+
+7. The augmentation process can occasionally stall. If this ever happens you can use the **//ct r** command to reload the addon and start the process over again.
+
+
+Suppose you want to augment an ogma's cape from scratch with dex, accuracy and attack, and double attack. You can use the following steps:
+
+1. Enter //ct prep run thread dex
+
+2. Enter //ct go 20
+
+3. Wait for the ending message
+
+4. Enter //ct prep run dust acc/atk
+
+5. Enter //ct go 20
+
+6. Wait for the ending message.
+
+7. Enter //ct prep run sap doubleattack
+
+8. Enter //ct go 10
+
+9. Upon receiving the completion message you can then consider augmenting another cape.
+
+___
+
+### Commands
+
+The **help** command displays all of the possible commands of CapeTrader in your chat windower. Below are the equivalent ways of calling the command:
+
+ //ct help
+ //ct h
+ //capetrader help
+ //capetrader h
+
+The **reload** command reloads the addon. Useful if the capetrader addon ever gets stuck during the augmentation process. The below are equivalent:
+
+ //ct reload
+ //ct r
+ //capetrader reload
+ //capetrader r
+
+The **unload** command reloads the addon. Useful if the capetrader addon ever gets stuck during the augmentation process or you want to unload the addon quickly. The below are equivalent:
+
+ //ct unload
+ //ct u
+ //capetrader unload
+ //capetrader u
+
+The **prep** command is one of the key components of this addon's function. This command tells the go command how to augment your cape. There are three inputs to the prep command. First is the 3 letter abbreviation of the job on the cape, for example: cor blm whm pup. The second is the type of augment item you need to use: thread, dust, sap and dye. Third is the augment path. Note that none of these inputs are case sensitive. Also in case you are not sure exactly what to input for the augment path, you can use the list command or use the following list for reference. Below are all of the possible combinations of valid augment paths:
+
+ //ct prep war thread hp
+ //ct prep mnk thread mp
+ //ct prep whm thread str
+ //ct prep blm thread dex
+ //ct prep rdm thread vit
+ //ct prep thf thread agi
+ //ct prep pld thread int
+ //ct prep drk thread mnd
+ //ct prep bst thread chr
+ //ct prep brd thread petmelee
+ //ct prep rng thread petmagic
+
+ //ct prep sam dust acc/atk
+ //ct prep nin dust racc/ratk
+ //ct prep drg dust macc/mdmg
+ //ct prep smn dust eva/meva
+
+ //ct prep blu sap wsd
+ //ct prep cor sap critrate
+ //ct prep pup sap stp
+ //ct prep dnc sap doubleattack
+ //ct prep sch sap haste
+ //ct prep geo sap dw
+ //ct prep run sap enmity+
+ //ct prep war sap enmity-
+ //ct prep mnk sap snapshot
+ //ct prep whm sap mab
+ //ct prep blm sap fc
+ //ct prep rdm sap curepotency
+ //ct prep thf sap waltzpotency
+ //ct prep pld sap petregen
+ //ct prep drk sap pethaste
+
+ //ct prep bst dye hp
+ //ct prep brd dye mp
+ //ct prep rng dye str
+ //ct prep sam dye dex
+ //ct prep nin dye vit
+ //ct prep drg dye agi
+ //ct prep smn dye int
+ //ct prep blu dye mnd
+ //ct prep cor dye chr
+ //ct prep pup dye acc
+ //ct prep dnc dye atk
+ //ct prep sch dye racc
+ //ct prep geo dye ratk
+ //ct prep run dye macc
+ //ct prep war dye mdmg
+ //ct prep mnk dye eva
+ //ct prep whm dye meva
+ //ct prep blm dye petacc
+ //ct prep rdm dye petatk
+ //ct prep thf dye petmacc
+ //ct prep pld dye petmdmg
+
+The **go** command is the second key component of the CapeTrader addon and requires that you have used the prep command correctly beforehand. Remember again that using this command carries with it some risks as described in the usage notes section. If you do not provide an input the go command will by default only augment your cape once. Below are equivalent ways of augmenting your cape 20 times:
+
+ //ct go 20
+ //capetrader go 20
+
+The **list** command is used as a reminder of what are valid inputs for the augmentpath input of the prep command. Below are the equivalent ways of calling this command:
+
+ //ct list
+ //capetrader list
+ //ct l
+ //capetrader l
+___
+
+
+### Warnings and notes on the relevant packets
+There are four parts to the process of augmenting your ambuscade cape:
+
+1. Part 1: Targetting gorpa-masorpa plus putting together and trading the relevant items. This takes me about 10 seconds to complete manually. (Involves outgoing packet 0x036)
+
+2. Part 2: Waiting for the dialog menu to pop up and become usable. This takes about 1 second and can't be controlled by the player. (Involves the incoming 0x034 packet.)
+
+3. Part 3: Navigating the menu to confirm and augment your cape. This takes me 2-3 seconds to confirm manually. (Involves 2 outgoing 0x05B packets)
+
+4. Part 4: Waiting and receiving your newly augmented cape. This takes anywhere from 1 to 3 seconds and can't be controlled by the player. (Involves the incoming 0x01D packet)
+
+The cape trader addon uses packets in order to substantially speed up parts one and three from above at a speed that would not normally be possible. Therefore if you use this addon you could potentially look suspicious. Part 1 of the process takes only 1 second using this addon. If this makes you uncomfortable you can change the value of the dustSapThreadTradeDelay and dyeTradeDelay variables in the capeTrader.lua file to a more reasonable amount if you wish. Please note that the augmenting with dyes needs a bit longer of a delay to work. This addon does part 3 pretty much instantaneously once the incoming 0x034 packet is received from part 2. So once again you can look suspicious again during this stage. The time it takes for part 2 and 4 should not be that different from you augmenting capes manually.
+
+The possibility of the loss of augment items comes from part 3. When augmenting manually you will get denied by the npc if you try to trade an already maxed cape. Injecting the 0x036 packet and later the 0x05B packets bypasses this check but you lose your augment items but receive your cape back unchanged if you have already maxed an augment path. There are some safeguards to prevent this happening in this addon but it has not been tested on every single augment path. So please use the go command with caution.
+
+Please keep all of the above in mind before deciding to use this addon. If you do decide to use CapeTrader I hope you find it useful!
diff --git a/Data/BuiltIn/Libraries/lua-addons/addons/capetrader/allAugPaths.lua b/Data/BuiltIn/Libraries/lua-addons/addons/capetrader/allAugPaths.lua
new file mode 100644
index 0000000..e8f337b
--- /dev/null
+++ b/Data/BuiltIn/Libraries/lua-addons/addons/capetrader/allAugPaths.lua
@@ -0,0 +1,87 @@
+--[[Copyright © 2016, Burntwaffle@Odin
+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 CapeTrader 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 Lygre,Burntwaffle@Odin 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 T{
+ ['abdhaljs thread'] = {
+ [0] = 'HP',
+ [1] = 'MP',
+ [2] = 'STR',
+ [3] = 'DEX',
+ [4] = 'VIT',
+ [5] = 'AGI',
+ [6] = 'INT',
+ [7] = 'MND',
+ [8] = 'CHR',
+ [9] = 'PetMelee',
+ [10] = 'PetMagic'
+ },
+ ['abdhaljs dust'] = {
+ [0] = 'Acc/Atk',
+ [1] = 'RAcc/RAtk',
+ [2] = 'MAcc/MDmg',
+ [3] = 'Eva/MEva'
+ },
+ ['abdhaljs sap'] = {
+ [0] = 'WSD',
+ [1] = 'CritRate',
+ [2] = 'STP',
+ [3] = 'DoubleAttack',
+ [4] = 'Haste',
+ [5] = 'DW',
+ [6] = 'Enmity+',
+ [7] = 'Enmity-',
+ [8] = 'Snapshot',
+ [9] = 'MAB',
+ [10] = 'FC',
+ [11] = 'CurePotency',
+ [12] = 'WaltzPotency',
+ [13] = 'PetRegen',
+ [14] = 'PetHaste',
+ },
+ ['abdhaljs dye'] = {
+ [0] = 'HP',
+ [1] = 'MP',
+ [2] = 'STR',
+ [3] = 'DEX',
+ [4] = 'VIT',
+ [5] = 'AGI',
+ [6] = 'INT',
+ [7] = 'MND',
+ [8] = 'CHR',
+ [9] = 'Acc',
+ [10] = 'Atk',
+ [11] = 'Racc',
+ [12] = 'Ratk',
+ [13] = 'MAcc',
+ [14] = 'MDmg',
+ [15] = 'Eva',
+ [16] = 'MEva',
+ [17] = 'PetAcc',
+ [18] = 'PetAtk',
+ [19] = 'PetMAcc',
+ [20] = 'PetMDmg',
+ },
+}
diff --git a/Data/BuiltIn/Libraries/lua-addons/addons/capetrader/capetrader.lua b/Data/BuiltIn/Libraries/lua-addons/addons/capetrader/capetrader.lua
new file mode 100644
index 0000000..40fbbf7
--- /dev/null
+++ b/Data/BuiltIn/Libraries/lua-addons/addons/capetrader/capetrader.lua
@@ -0,0 +1,521 @@
+--[[Copyright © 2016, Lygre, Burntwaffle@Odin
+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 CapeTrader 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 Lygre, Burntwaffle@Odin 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 = 'CapeTrader'
+_addon.author = 'Lygre, Burntwaffle'
+_addon.version = '1.0.2'
+_addon.commands = {'capetrader', 'ct'}
+
+require('luau')
+require('pack')
+require('sets')
+require('tables')
+require('functions')
+require('strings')
+local res = require('resources')
+local packets = require('packets')
+local augPaths = require('allAugPaths')
+local maxAugMap = require('maxAugMap')
+local extData = require('extdata')
+local jobToCapeMap = require('jobToCapeMap')
+local validItemNames = require('validItemNames')
+
+function getValidItems()
+ local allItems = res.items
+ local itemTable = T{}
+ local counter = 0
+ local numberOfValidItems = validItemNames:length()
+
+ for key, item in pairs(allItems) do
+ if counter >= numberOfValidItems then
+ break
+ end
+
+ if validItemNames:contains(item.english) then
+ itemTable:update(T{ [item.english:lower()] = item })
+ counter = counter + 1
+ end
+ end
+
+ return itemTable
+end
+local validItemTable = getValidItems()
+
+--The following variables need to be carefully tracked and updated throughout all parts of this file.
+--TODO: Find ways to reduce the amount of global variables in this list
+local currentCape = nil
+local pathItem = nil
+local pathName = nil
+local pathIndex
+local capeHasBeenPrepared = false
+local currentlyAugmenting = false
+local firstTimeAug = false
+local timesAugmentedCount = 0
+local numberOfTimesToAugment = 0
+local tradeReady = false
+local maxAugKey = nil
+local zoneHasLoaded = true
+local inventory = nil
+
+--The following are constants.
+local dustSapThreadTradeDelay = 1
+local dyeTradeDelay = 2
+local endMessageDelay = 2
+local threadIndex = 1
+local dustIndex = 2
+local dyeIndex = 3
+local sapIndex = 4
+local inventoryBagNumber = 0
+local maxAmountDustAndThread = 20
+local maxAmountSapAndDye = 10
+local blueTextColor = 466
+local redTextColor = 123
+local greenTextColor = 158
+
+--NOTE: It is possible that the correct values for the following variables can change after a version update.
+local gorpaID = nil
+local gorpaTargetIndex = nil
+local gorpaMenuID = 0x183
+local mhauraID = res.zones:with('english','Mhaura').id
+
+windower.register_event('addon command', function(input, ...)
+ local cmd = string.lower(input)
+ local args = {...}
+
+ updateGorpaID()
+
+ if cmd == 'prep' then
+ if args[1] and args[2] and args[3] then
+ prepareCapeForAugments(args[2], args[1], args[3])
+ else
+ windower.add_to_chat(redTextColor, "You are missing at least one input to the prep command.")
+ end
+ elseif cmd == 'go' then
+ if zoneHasLoaded and not currentlyAugmenting then
+ if args[1] then
+ if tonumber(args[1]) then
+ startAugmentingCape(args[1], true)
+ else
+ windower.add_to_chat(redTextColor, 'Error: Not given a numerical argument.')
+ end
+ else
+ startAugmentingCape(1, true)
+ end
+ elseif not zoneHasLoaded then
+ windower.add_to_chat(redTextColor, 'Your inventory has not yet loaded, please try the go command again when your inventory loads.')
+ elseif currentlyAugmenting then
+ windower.add_to_chat(redTextColor, 'You are currently still augmenting a cape, please wait until the process finishes.')
+ end
+ elseif cmd == 'list' or cmd == 'l' then
+ printAugList()
+ elseif cmd == 'help' or cmd == 'h' then
+ printHelp()
+ elseif cmd == 'unload' or cmd == 'u' then
+ windower.send_command('lua unload ' .. _addon.name)
+ elseif cmd == 'reload' or cmd == 'r' then
+ windower.send_command('lua reload ' .. _addon.name)
+ else
+ windower.add_to_chat(redTextColor, 'You entered an unknown command, enter //ct help if you forget your commands.')
+ end
+end)
+
+function getItemIndex(capeOrAugItem)
+ for itemIndex, item in pairs(inventory) do
+ if item.id == capeOrAugItem.id then
+ return itemIndex
+ end
+ end
+end
+
+function getItem(itemName)
+ return validItemTable[itemName:lower()]
+end
+
+function buildTrade(capeIndex,augmentItemIndex)
+ local packet = packets.new('outgoing', 0x036, {
+ ["Target"] = gorpaID,
+ ["Target Index"] = gorpaTargetIndex,
+ ["Item Count 1"] = 1,
+ ["Item Count 2"] = 1,
+ ["Item Index 1"] = capeIndex,
+ ["Item Index 2"] = augmentItemIndex,
+ ["Number of Items"] = 2
+ })
+ packets.inject(packet)
+end
+
+windower.register_event('incoming chunk', function(id, data, modified, injected, blocked)
+ if id == 0x00B or id == 0x00A then
+ zoneHasLoaded = false --NOTE: This idea was taken from Zohno's findall addon.
+ end
+
+ if id == 0x034 or id == 0x032 then
+ if currentlyAugmenting then
+
+ injectAugmentConfirmationPackets()
+
+ timesAugmentedCount = timesAugmentedCount + 1
+ if timesAugmentedCount <= tonumber(numberOfTimesToAugment) then
+ windower.add_to_chat(greenTextColor, timesAugmentedCount - 1 .. '/' .. numberOfTimesToAugment .. ' augments completed.')
+ tradeReady = true
+ else
+ capeHasBeenPrepared = false
+ currentlyAugmenting = false
+ currentCape = nil
+ pathItem = nil
+ tradeReady = false
+ windower.add_to_chat:schedule(endMessageDelay,blueTextColor,'You have finished augmenting your cape.')
+ end
+
+ return true
+ end
+ end
+
+ if id == 0x01D then
+ if not zoneHasLoaded then
+ zoneHasLoaded = true
+ end
+ if tradeReady then
+ tradeReady = false
+
+ if not pathItem.english:lower():endswith(' dye') then
+ startAugmentingCape:schedule(dustSapThreadTradeDelay, numberOfTimesToAugment - timesAugmentedCount + 1, false)
+ else
+ startAugmentingCape:schedule(dyeTradeDelay, numberOfTimesToAugment - timesAugmentedCount + 1, false)
+ end
+ end
+ end
+end)
+
+function checkDistanceToGorpa()
+ local zoneID = tonumber(windower.ffxi.get_info().zone)
+ if zoneID == mhauraID then
+ local gorpa = windower.ffxi.get_mob_by_id(gorpaID)
+
+ if gorpa and gorpa.distance < 36 then
+ return true
+ else
+ windower.add_to_chat(redTextColor, "You're not close enough to Gorpa-Masorpa, please get closer!")
+ return false
+ end
+ else
+ windower.add_to_chat(redTextColor, "You are not in Mhaura!")
+ currentlyAugmenting = false
+ return false
+ end
+end
+
+function checkAugItemCount(numberOfAugmentAttempts)
+ if pathItem then
+ local pathItemCount = 0
+
+ for key, itemTable in pairs(inventory) do
+ if key ~= 'max' and key ~= 'count' and key ~= 'enabled' then
+ if itemTable.id == pathItem.id then
+ pathItemCount = pathItemCount + itemTable.count
+ end
+ end
+ end
+
+ if tonumber(numberOfAugmentAttempts) < 1 then
+ windower.add_to_chat(redTextColor, 'Please enter a number of 1 or greater.')
+ return false
+ elseif tonumber(numberOfAugmentAttempts) > maxAmountSapAndDye and (pathItem.english:lower():endswith(' dye') or pathItem.english:lower():endswith(' sap')) then
+ windower.add_to_chat(redTextColor, 'For sap or dye, the max number of times you can augment a cape is ' .. maxAmountSapAndDye .. ' times. You entered: ' .. numberOfAugmentAttempts)
+ return false
+ elseif tonumber(numberOfAugmentAttempts) > maxAmountDustAndThread and (pathItem.english:lower():endswith(' dust') or pathItem.english:lower():endswith(' thread')) then
+ windower.add_to_chat(redTextColor, 'For dust or thread, the max number of times you can augment a cape is ' .. maxAmountDustAndThread .. ' times. You entered: ' .. numberOfAugmentAttempts)
+ return false
+ elseif tonumber(numberOfAugmentAttempts) > pathItemCount then
+ local temp
+ if tonumber(numberOfAugmentAttempts) > 1 then
+ temp = ' times.'
+ elseif tonumber(numberOfAugmentAttempts) == 1 then
+ temp = ' time.'
+ end
+
+ if pathItemCount ~= 0 then
+ windower.add_to_chat(redTextColor, 'You do not have enough ' .. pathItem.name .. ' to augment that cape ' .. numberOfAugmentAttempts .. temp ..' You only have ' .. pathItemCount .. ' in your inventory.')
+ else
+ windower.add_to_chat(redTextColor, 'You do not have enough ' .. pathItem.name .. ' to augment that cape ' .. numberOfAugmentAttempts .. temp ..' You have none in your inventory.')
+ end
+ return false
+ else
+ return true
+ end
+ end
+end
+
+function checkCapeCount()
+ local capeCount = 0
+
+ if currentCape then
+ for key, itemTable in pairs(inventory) do
+ if key ~= 'max' and key ~= 'count' and key ~= 'enabled' then
+ if itemTable.id == currentCape.id then
+ capeCount = capeCount + 1
+ end
+ end
+ end
+
+ if capeCount > 1 then
+ windower.add_to_chat(redTextColor, 'You have multiple ' .. currentCape.name .. 's in your inventory! Please keep only the one you intend to augment in your inventory.')
+ return false
+ elseif capeCount == 0 then
+ windower.add_to_chat(redTextColor, 'You have zero ' .. currentCape.name .. 's in your inventory. Please find the one you intend to augment and move it to your inventory.')
+ return false
+ elseif capeCount == 1 then
+ return true
+ end
+ else
+ return false
+ end
+end
+
+function prepareCapeForAugments(augItemType, jobName, augPath)
+ if not currentlyAugmenting then
+ local validArguments = true
+ local augItemTypeIsValid = false
+
+ if not S{'sap', 'dye', 'thread', 'dust'}:contains(augItemType:lower()) then
+ windower.add_to_chat(redTextColor, 'Error with the type of augment item you entered. The second input should be sap or dye or thread or dust. You entered: ' .. augItemType:lower())
+ validArguments = false
+ else
+ pathItem = getItem('abdhaljs ' .. augItemType)
+ augItemTypeIsValid = true
+ end
+
+ if jobToCapeMap[jobName] then
+ currentCape = getItem(jobToCapeMap[jobName])
+ else
+ windower.add_to_chat(redTextColor, 'The job name you entered is not valid. You entered: ' .. jobName)
+ validArguments = false
+ end
+
+ if augPath and augItemTypeIsValid and validArguments then
+ local isValidPath = false
+ for i, v in pairs(augPaths[pathItem.english:lower()]) do
+ if augPath:lower() == v:lower() then
+ pathIndex = i
+ pathName = augPath
+ isValidPath = true
+ break
+ end
+ end
+
+ if not isValidPath then
+ windower.add_to_chat(redTextColor, 'The augment path you entered is not valid. Please check the possible augment list for ' .. augItemType:lower() .. ' using the //ct list command. You entered: ' .. augPath)
+ validArguments = false
+ end
+ end
+
+ if validArguments then
+ maxAugKey = string.lower(augItemType .. augPath)
+ capeHasBeenPrepared = true
+ timesAugmentedCount = 1
+ windower.add_to_chat(greenTextColor, 'You can now augment your ' .. jobToCapeMap[jobName] .. ' with ' .. augPath:lower() .. ' using abdhaljs ' .. augItemType:lower() .. '.')
+ else
+ capeHasBeenPrepared = false
+ currentCape = nil
+ pathItem = nil
+ end
+ else
+ windower.add_to_chat(redTextColor, 'You can\'t setup another cape while you are currently augmenting one.')
+ end
+end
+
+function startAugmentingCape(numberOfRepeats, firstAttempt)
+ inventory = windower.ffxi.get_items(inventoryBagNumber)
+ currentlyAugmenting = true
+ local augStatus = nil
+ local capeIndex
+ local augmentItemIndex
+ if capeHasBeenPrepared and checkCapeCount() and checkAugItemCount(numberOfRepeats) and checkDistanceToGorpa() then
+ augStatus = checkAugLimits():lower()
+ capeIndex = getItemIndex(currentCape)
+ augmentItemIndex = getItemIndex(pathItem)
+ end
+
+ if firstAttempt and augStatus then
+ if augStatus ~= 'maxed' and augStatus ~= 'notmatching' then
+ if augStatus:lower() ~= 'empty' then
+ firstTimeAug = false
+ else
+ firstTimeAug = true
+ end
+
+ local temp
+ if tonumber(numberOfRepeats) == 1 then
+ temp = 'time.'
+ else
+ temp = 'times.'
+ end
+
+ numberOfTimesToAugment = numberOfRepeats
+ windower.add_to_chat(blueTextColor, 'Starting to augment your ' .. currentCape.name .. ' ' .. numberOfRepeats .. ' ' .. temp)
+
+ tradeReady = false
+ buildTrade(capeIndex,augmentItemIndex)
+ else
+ currentlyAugmenting = false
+ tradeReady = false
+ end
+ elseif not firstAttempt and augStatus then
+ if augStatus and augStatus ~= 'maxed' then
+ tradeReady = false
+ buildTrade(capeIndex,augmentItemIndex)
+ else
+ capeHasBeenPrepared = false
+ currentlyAugmenting = false
+ tradeReady = false
+ pathItem = nil
+ currentCape = nil
+ windower.add_to_chat(blueTextColor, 'Your cape is currently maxed in that augment path, ending the augment process now.')
+ end
+ elseif not capeHasBeenPrepared then
+ currentlyAugmenting = false
+ windower.add_to_chat(redTextColor, 'You have not yet setup your cape and augment information with the //ct prep command!')
+ else
+ currentlyAugmenting = false
+ end
+end
+
+function checkAugLimits()
+ local capeItem
+ for index, item in pairs(inventory) do
+ if index ~= 'max' and index ~= 'count' and index ~= 'enabled' then
+ if item.id == currentCape.id then
+ capeItem = item
+ break
+ end
+ end
+ end
+
+ local augmentTable
+ if extData.decode(capeItem).augments then
+ augmentTable = extData.decode(capeItem).augments
+ end
+
+ local augValue
+ if augmentTable then
+ if pathItem.english:lower():endswith(' thread') then
+ augValue = augmentTable[threadIndex]
+ elseif pathItem.english:lower():endswith(' dust') then
+ augValue = augmentTable[dustIndex]
+ elseif pathItem.english:lower():endswith(' dye') then
+ augValue = augmentTable[dyeIndex]
+ elseif pathItem.english:lower():endswith(' sap') then
+ augValue = augmentTable[sapIndex]
+ end
+ else
+ augValue = 'none'
+ end
+
+ if augValue:lower() == 'none' or not augmentTable then
+ return 'empty'
+ end
+
+ local max = maxAugMap[maxAugKey].max
+ if augValue:contains(max) then
+ windower.add_to_chat(redTextColor, 'You have augmented your ' .. currentCape.name .. ' to the max already with ' .. pathItem.name .. '.')
+ return 'maxed'
+ end
+
+ local mustContainTable = maxAugMap[maxAugKey].mustcontain
+ for k, augmentString in pairs(mustContainTable) do
+ if not augValue:lower():contains(augmentString:lower()) then
+ windower.add_to_chat(redTextColor,'You can\'t augment your ' .. currentCape.name .. ' with ' .. pathName .. ' because it has already been augmented with: ' .. augValue .. ' using ' .. pathItem.name .. '.')
+ return 'notmatching'
+ end
+ end
+
+ local cantContainTable = maxAugMap[maxAugKey].cantcontain
+ if table.length(cantContainTable) > 0 then
+ for k, augmentString in pairs(cantContainTable) do
+ if augValue:lower():contains(augmentString:lower()) then
+ windower.add_to_chat(redTextColor,'You can\'t augment your ' .. currentCape.name .. 'with ' .. pathName .. ' because it has already been augmented with: ' .. augValue .. ' using ' .. pathItem.name .. '.')
+ return 'notmatching'
+ end
+ end
+ end
+
+ return 'allclear'
+end
+
+function injectAugmentConfirmationPackets()
+ local optionIndex
+ if firstTimeAug then
+ firstTimeAug = false
+ optionIndex = 512
+ else
+ optionIndex = 256
+ end
+
+ local augmentChoicePacket = packets.new('outgoing', 0x05B)
+ augmentChoicePacket["Target"] = gorpaID
+ augmentChoicePacket["Option Index"] = optionIndex
+ augmentChoicePacket["_unknown1"] = pathIndex
+ augmentChoicePacket["Target Index"] = gorpaTargetIndex
+ augmentChoicePacket["Automated Message"] = true
+ augmentChoicePacket["Zone"] = mhauraID
+ augmentChoicePacket["Menu ID"] = gorpaMenuID
+ packets.inject(augmentChoicePacket)
+
+ augmentChoicePacket["Automated Message"] = false
+ packets.inject(augmentChoicePacket)
+
+ local playerUpdatePacket = packets.new('outgoing', 0x016, {
+ ["Target Index"] = windower.ffxi.get_mob_by_target('me').index,
+ })
+ packets.inject(playerUpdatePacket)
+end
+
+function updateGorpaID()
+ if not gorpaID then
+ local zoneID = tonumber(windower.ffxi.get_info().zone)
+ if zoneID == mhauraID then
+ local gorpa = windower.ffxi.get_mob_by_name('Gorpa-Masorpa')
+ gorpaID = gorpa.id
+ gorpaTargetIndex = gorpa.index
+ end
+ end
+end
+
+function printAugList()
+ windower.add_to_chat(blueTextColor, 'Thread: hp mp str dex vit agi int mnd chr petmelee petmagic')
+ windower.add_to_chat(blueTextColor, 'Dust: acc/atk racc/ratk macc/mdmg eva/meva')
+ windower.add_to_chat(blueTextColor, 'Sap: wsd critrate stp doubleattack haste dw enmity+ enmity- snapshot mab fc curepotency waltzpotency petregen pethaste')
+ windower.add_to_chat(blueTextColor, 'Dye: hp mp str dex vit agi int mnd chr acc atk racc ratk macc mdmg eva meva petacc petatk petmacc petmdmg')
+end
+
+function printHelp()
+ windower.add_to_chat(blueTextColor, string.format('%s Version: %s Command Listing:', _addon.name, _addon.version))
+ windower.add_to_chat(blueTextColor, ' reload|r Reload CapeTrader.')
+ windower.add_to_chat(blueTextColor, ' unload|u Unload CapeTrader.')
+ windower.add_to_chat(blueTextColor, ' prep <jobName> <augItem> <augPath> Prepares a given job\'s cape with augItem on augPath. Need to use this before using //ct go.')
+ windower.add_to_chat(blueTextColor, ' go <#repeats> Starts augmenting cape with the info gathered from the prep command. The repeats input defaults to one if not provided.')
+ windower.add_to_chat(blueTextColor, ' list|l Lists all possible augitems and their valid paths. Use to know what the valid inputs for //ct prep are.')
+end
diff --git a/Data/BuiltIn/Libraries/lua-addons/addons/capetrader/jobToCapeMap.lua b/Data/BuiltIn/Libraries/lua-addons/addons/capetrader/jobToCapeMap.lua
new file mode 100644
index 0000000..552923c
--- /dev/null
+++ b/Data/BuiltIn/Libraries/lua-addons/addons/capetrader/jobToCapeMap.lua
@@ -0,0 +1,50 @@
+--[[Copyright © 2016, Lygre, Burntwaffle@Odin
+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 CapeTrader 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 Lygre, Burntwaffle@Odin 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 T{
+ ['war'] = "Cichol's Mantle",
+ ['mnk'] = "Segomo's Mantle",
+ ['whm'] = "Alaunus's Cape",
+ ['blm'] = "Taranus's Cape",
+ ['rdm'] = "Sucellos's Cape",
+ ['thf'] = "Toutatis's Cape",
+ ['pld'] = "Rudianos's Mantle",
+ ['drk'] = "Ankou's Mantle",
+ ['bst'] = "Artio's Mantle",
+ ['brd'] = "Intarabus's Cape",
+ ['rng'] = "Belenus's Cape",
+ ['sam'] = "Smertrios's Mantle",
+ ['nin'] = "Andartia's Mantle",
+ ['drg'] = "Brigantia's Mantle",
+ ['smn'] = "Campestres's Cape",
+ ['blu'] = "Rosmerta's Cape",
+ ['cor'] = "Camulus's Mantle",
+ ['pup'] = "Visucius's Mantle",
+ ['dnc'] = "Senuna's Mantle",
+ ['sch'] = "Lugh's Cape",
+ ['geo'] = "Nantosuelta's Cape",
+ ['run'] = "Ogma's cape",
+}
diff --git a/Data/BuiltIn/Libraries/lua-addons/addons/capetrader/maxAugMap.lua b/Data/BuiltIn/Libraries/lua-addons/addons/capetrader/maxAugMap.lua
new file mode 100644
index 0000000..c4d1737
--- /dev/null
+++ b/Data/BuiltIn/Libraries/lua-addons/addons/capetrader/maxAugMap.lua
@@ -0,0 +1,81 @@
+--[[Copyright © 2016, Lygre, Burntwaffle@Odin
+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 CapeTrader 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 Lygre, Burntwaffle@Odin 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 T{
+ ['threadhp'] = {['max'] = '60', ['mustcontain'] = T{'hp'},['cantcontain'] = T{}},
+ ['threadmp'] = {['max'] = '60', ['mustcontain'] = T{'mp'},['cantcontain'] = T{}},
+ ['threadstr'] = {['max'] = '20', ['mustcontain'] = T{'str'},['cantcontain'] = T{}},
+ ['threaddex'] = {['max'] = '20', ['mustcontain'] = T{'dex'},['cantcontain'] = T{}},
+ ['threadvit'] = {['max'] = '20', ['mustcontain'] = T{'vit'},['cantcontain'] = T{}},
+ ['threadagi'] = {['max'] = '20', ['mustcontain'] = T{'agi'},['cantcontain'] = T{}},
+ ['threadint'] = {['max'] = '20', ['mustcontain'] = T{'int'},['cantcontain'] = T{}},
+ ['threadmnd'] = {['max'] = '20', ['mustcontain'] = T{'mnd'},['cantcontain'] = T{}},
+ ['threadchr'] = {['max'] = '20', ['mustcontain'] = T{'chr'},['cantcontain'] = T{}},
+ ['threadpetmelee'] = {['max'] = '20', ['mustcontain'] = T{'acc','r.acc','atk.','r.atk'},['cantcontain'] = T{}},
+ ['threadpetmagic'] = {['max'] = '20', ['mustcontain'] = T{'pet','m.acc.','m.dmg.'},['cantcontain'] = T{}},
+
+ ['dustacc/atk'] = {['max'] = '20', ['mustcontain'] = T{'accuracy','attack'},['cantcontain'] = T{}},
+ ['dustracc/ratk'] = {['max'] = '20', ['mustcontain'] = T{'rng.acc','rng.atk'},['cantcontain'] = T{}},
+ ['dustmacc/mdmg'] = {['max'] = '20', ['mustcontain'] = T{'mag. acc','mag. dmg.'},['cantcontain'] = T{}},
+ ['dusteva/meva'] = {['max'] = '20', ['mustcontain'] = T{'eva.','mag. eva.'},['cantcontain'] = T{}},
+
+ ['sapwsd'] = {['max'] = '10', ['mustcontain'] = T{'weapon skill damage'},['cantcontain'] = T{}},
+ ['sapcritrate'] = {['max'] = '10', ['mustcontain'] = T{'crit'},['cantcontain'] = T{}},
+ ['sapstp'] = {['max'] = '10', ['mustcontain'] = T{'store tp'},['cantcontain'] = T{}},
+ ['sapdoubleattack'] = {['max'] = '10', ['mustcontain'] = T{'dbl.atk.'},['cantcontain'] = T{}},
+ ['saphaste'] = {['max'] = '10', ['mustcontain'] = T{'haste'},['cantcontain'] = T{'pet'}},
+ ['sapdw'] = {['max'] = '10', ['mustcontain'] = T{'dual'},['cantcontain'] = T{}},
+ ['sapenmity+'] = {['max'] = '10', ['mustcontain'] = T{'enmity','+'},['cantcontain'] = T{}},
+ ['sapenmity-'] = {['max'] = '10', ['mustcontain'] = T{'enmity','-'},['cantcontain'] = T{}},
+ ['sapsnapshot'] = {['max'] = '10', ['mustcontain'] = T{'snapshot'},['cantcontain'] = T{}},
+ ['sapmab'] = {['max'] = '10', ['mustcontain'] = T{'mag.atk.bns.'},['cantcontain'] = T{}},
+ ['sapfc'] = {['max'] = '10', ['mustcontain'] = T{'fast cast'},['cantcontain'] = T{}},
+ ['sapcurepotency'] = {['max'] = '10', ['mustcontain'] = T{'cure'},['cantcontain'] = T{}},
+ ['sapwaltzpotency'] = {['max'] = '10', ['mustcontain'] = T{'waltz'},['cantcontain'] = T{}},
+ ['sappetregen'] = {['max'] = '10', ['mustcontain'] = T{'pet','regen'},['cantcontain'] = T{}},
+ ['sappethaste'] = {['max'] = '10', ['mustcontain'] = T{'pet','haste'},['cantcontain'] = T{}},
+
+ ['dyehp'] = {['max'] = '20', ['mustcontain'] = T{'hp'},['cantcontain'] = T{}},
+ ['dyemp'] = {['max'] = '20', ['mustcontain'] = T{'mp'},['cantcontain'] = T{}},
+ ['dyestr'] = {['max'] = '10', ['mustcontain'] = T{'str'},['cantcontain'] = T{}},
+ ['dyedex'] = {['max'] = '10', ['mustcontain'] = T{'dex'},['cantcontain'] = T{}},
+ ['dyevit'] = {['max'] = '10', ['mustcontain'] = T{'vit'},['cantcontain'] = T{}},
+ ['dyeagi'] = {['max'] = '10', ['mustcontain'] = T{'agi'},['cantcontain'] = T{}},
+ ['dyeint'] = {['max'] = '10', ['mustcontain'] = T{'int'},['cantcontain'] = T{}},
+ ['dyemnd'] = {['max'] = '10', ['mustcontain'] = T{'mnd'},['cantcontain'] = T{}},
+ ['dyechr'] = {['max'] = '10', ['mustcontain'] = T{'chr'},['cantcontain'] = T{}},
+ ['dyeacc'] = {['max'] = '10', ['mustcontain'] = T{'accuracy'},['cantcontain'] = T{'pet'}},
+ ['dyeatk'] = {['max'] = '10', ['mustcontain'] = T{'attack'},['cantcontain'] = T{'pet'}},
+ ['dyeracc'] = {['max'] = '10', ['mustcontain'] = T{'rng', 'acc'},['cantcontain'] = T{'pet'}},
+ ['dyeratk'] = {['max'] = '10', ['mustcontain'] = T{'rng', 'atk'},['cantcontain'] = T{'pet'}},
+ ['dyemacc'] = {['max'] = '10', ['mustcontain'] = T{'mag', 'acc'},['cantcontain'] = T{'pet'}},
+ ['dyemdmg'] = {['max'] = '10', ['mustcontain'] = T{'magic', 'damage'},['cantcontain'] = T{'pet'}},
+ ['dyeeva'] = {['max'] = '10', ['mustcontain'] = T{'evasion'}, ['cantcontain'] = T{'mag'}},
+ ['dyemeva'] = {['max'] = '10', ['mustcontain'] = T{'mag', 'evasion'},['cantcontain'] = T{}},
+ ['dyepetacc'] = {['max'] = '10', ['mustcontain'] = T{'pet','accuracy','rng', 'acc'},['cantcontain'] = T{}},
+ ['dyepetatk'] = {['max'] = '10', ['mustcontain'] = T{'pet','attack','rng', 'atk'},['cantcontain'] = T{}},
+ ['dyepetmacc'] = {['max'] = '10', ['mustcontain'] = T{'pet','mag' , 'acc'},['cantcontain'] = T{}},
+ ['dyepetmdmg'] = {['max'] = '10', ['mustcontain'] = T{'pet','magic', 'damage'},['cantcontain'] = T{}},
+}
diff --git a/Data/BuiltIn/Libraries/lua-addons/addons/capetrader/validItemNames.lua b/Data/BuiltIn/Libraries/lua-addons/addons/capetrader/validItemNames.lua
new file mode 100644
index 0000000..9e4fa5f
--- /dev/null
+++ b/Data/BuiltIn/Libraries/lua-addons/addons/capetrader/validItemNames.lua
@@ -0,0 +1,54 @@
+--[[Copyright © 2016, Lygre, Burntwaffle@Odin
+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 CapeTrader 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 Lygre, Burntwaffle@Odin 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 T{
+ "Cichol's Mantle",
+ "Segomo's Mantle",
+ "Alaunus's Cape",
+ "Taranus's Cape",
+ "Sucellos's Cape",
+ "Toutatis's Cape",
+ "Rudianos's Mantle",
+ "Ankou's Mantle",
+ "Artio's Mantle",
+ "Intarabus's Cape",
+ "Belenus's Cape",
+ "Smertrios's Mantle",
+ "Andartia's Mantle",
+ "Brigantia's Mantle",
+ "Campestres's Cape",
+ "Rosmerta's Cape",
+ "Camulus's Mantle",
+ "Visucius's Mantle",
+ "Senuna's Mantle",
+ "Lugh's Cape",
+ "Nantosuelta's Cape",
+ "Ogma's cape",
+ "Abdhaljs Thread",
+ "Abdhaljs Dust",
+ "Abdhaljs Dye",
+ "Abdhaljs Sap",
+}