├── .gitignore ├── SND Legacy ├── Fate Farming │ ├── img │ │ ├── SNDBasics.png │ │ ├── ScriptSettings.png │ │ ├── ImportFromClipboard.png │ │ ├── RSREngageSettings.png │ │ ├── RSRFatePriorities.png │ │ ├── RSRGapCloserDistance.png │ │ ├── RSRMapSpecificPriorities.png │ │ └── FateFarmingStateMachine.drawio.png │ ├── Companion Scripts │ │ ├── Multi Zone Farming.lua │ │ ├── Atma Farming.lua │ │ ├── Anima Luminous Crystal Farming.lua │ │ └── Occult Demiatmas.lua │ └── README.md ├── Jump Puzzles │ ├── 3 - Stormblood │ │ ├── 26 - Shiokaze Hostelry (Kugane Tower).txt │ │ └── 23 - Bokairo Inn.lua │ ├── README.md │ ├── 5 - Endwalker │ │ └── 14 - Ruveydah Fibers Rooftop Garden (Radz-at-Han).lua │ └── 6 - Dawntrail │ │ └── 5 - Hunu'iliy (Tuliyollal Tower).lua ├── Weeklies │ ├── CapTomes.lua │ └── WondrousTails.lua ├── Hunt Train Helper.lua ├── MacroChainer.lua ├── Gold Saucer │ ├── Triple Triad Card Packs.lua │ ├── MiniCactpot.lua │ ├── Any Way the Wind Blows.lua │ └── JumboCactpot.lua ├── Crafters and Gatherers │ └── Firmament │ │ ├── FirmamentCraftAll.lua │ │ └── FirmamentCrafting.lua ├── Dailies │ ├── PoeticsToSoil.lua │ ├── ProcessSubs.lua │ ├── Treasure Hunt Helper.lua │ ├── Treasure Map Gatherer.lua │ ├── IslandSanctuary.lua │ ├── Allied Society Quests.lua │ └── DailyHunts.lua └── Field Expeditions │ └── Occult Crescent │ └── OCH Helper.lua ├── Fate Farming.txt ├── Weeklies └── Wondrous Tails.txt ├── Jump Puzzles ├── README.md ├── 5 - Endwalker │ └── Sightseeing Log 14 - Ruveydah Fibers Rooftop Garden (Radz-at-Han).lua ├── 3 - Stormblood │ ├── Sightseeing Log 23 - Bokairo Inn.lua │ └── Sightseeing Log 26 - Shiokaze Hostelry (Kugane Tower).lua └── 6 - Dawntrail │ └── Sightseeing Log 5 - Hunu'iliy (Tuliyollal Tower).lua └── Gold Saucer ├── Mini Cactpot.lua └── Jumbo Cactpot.lua /.gitignore: -------------------------------------------------------------------------------- 1 | .luarc.json 2 | .vscode 3 | **/Personal/ 4 | **/SND Legacy/ -------------------------------------------------------------------------------- /SND Legacy/Fate Farming/img/SNDBasics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pot0to/pot0to-SND-Scripts/HEAD/SND Legacy/Fate Farming/img/SNDBasics.png -------------------------------------------------------------------------------- /SND Legacy/Fate Farming/img/ScriptSettings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pot0to/pot0to-SND-Scripts/HEAD/SND Legacy/Fate Farming/img/ScriptSettings.png -------------------------------------------------------------------------------- /Fate Farming.txt: -------------------------------------------------------------------------------- 1 | Fate farming is now maintained by baanderson40. You can find their repo at: 2 | https://github.com/baanderson40/SND_Scripts/tree/main/Fates -------------------------------------------------------------------------------- /SND Legacy/Fate Farming/img/ImportFromClipboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pot0to/pot0to-SND-Scripts/HEAD/SND Legacy/Fate Farming/img/ImportFromClipboard.png -------------------------------------------------------------------------------- /SND Legacy/Fate Farming/img/RSREngageSettings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pot0to/pot0to-SND-Scripts/HEAD/SND Legacy/Fate Farming/img/RSREngageSettings.png -------------------------------------------------------------------------------- /SND Legacy/Fate Farming/img/RSRFatePriorities.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pot0to/pot0to-SND-Scripts/HEAD/SND Legacy/Fate Farming/img/RSRFatePriorities.png -------------------------------------------------------------------------------- /SND Legacy/Fate Farming/img/RSRGapCloserDistance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pot0to/pot0to-SND-Scripts/HEAD/SND Legacy/Fate Farming/img/RSRGapCloserDistance.png -------------------------------------------------------------------------------- /SND Legacy/Fate Farming/img/RSRMapSpecificPriorities.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pot0to/pot0to-SND-Scripts/HEAD/SND Legacy/Fate Farming/img/RSRMapSpecificPriorities.png -------------------------------------------------------------------------------- /Weeklies/Wondrous Tails.txt: -------------------------------------------------------------------------------- 1 | Wondrous Tails script has been adopted by Censored. You can find it here: https://github.com/CensoredFFXIV/snd-scripts/blob/main/wondrousTails.lua -------------------------------------------------------------------------------- /SND Legacy/Fate Farming/img/FateFarmingStateMachine.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pot0to/pot0to-SND-Scripts/HEAD/SND Legacy/Fate Farming/img/FateFarmingStateMachine.drawio.png -------------------------------------------------------------------------------- /SND Legacy/Jump Puzzles/3 - Stormblood/26 - Shiokaze Hostelry (Kugane Tower).txt: -------------------------------------------------------------------------------- 1 | Someone else has already made a Kugane Tower one. You can find it at: 2 | https://github.com/Jaksuhn/SomethingNeedDoing/blob/master/Community%20Scripts/Misc/Kugane%20Tower%20Climb.lua 3 | -------------------------------------------------------------------------------- /SND Legacy/Weeklies/CapTomes.lua: -------------------------------------------------------------------------------- 1 | Cap = 450 2 | DutyToRun = 1266 -- The Underkeep 3 | 4 | while not IsAddonVisible("Currency") do 5 | yield("/currency") 6 | yield("/wait 2") 7 | yield("/callback Currency true 12 1") 8 | yield("/wait 2") 9 | end 10 | 11 | local fraction = GetNodeText("Currency", 66, 1) 12 | local numerator, denominator = fraction:match("(%d+)/(%d+)") 13 | numerator = tonumber(numerator) 14 | denominator = tonumber(denominator) 15 | 16 | while IsAddonVisible("Currency") do 17 | yield("/callback Currency true -1") 18 | yield("/wait 2") 19 | end 20 | 21 | yield("/autoduty run Support "..DutyToRun.." "..(math.ceil((denominator - numerator)/50)).." true") 22 | -------------------------------------------------------------------------------- /SND Legacy/Hunt Train Helper.lua: -------------------------------------------------------------------------------- 1 | if not GetCharacterCondition(4) then 2 | yield('/gaction "mount roulette"') 3 | yield("/wait 3") 4 | end 5 | yield("/vnav flyflag") 6 | yield("/wait 3") 7 | yield("/rotation manual") 8 | 9 | while PathfindInProgress() or PathIsRunning() do 10 | yield("/wait 1") 11 | end 12 | 13 | repeat 14 | yield('/ac dismount') 15 | yield("/wait 1") 16 | until not GetCharacterCondition(4) 17 | 18 | yield("/targetenemy") 19 | 20 | if HasTarget() and GetTargetHuntRank() == 2 then 21 | if GetDistanceToTarget() > 20 then 22 | if not PathfindInProgress() and not PathIsRunning() then 23 | PathfindAndMoveTo(GetTargetRawXPos(), GetTargetRawYPos(), GetTargetRawZPos()) 24 | end 25 | else 26 | yield("/vnav stop") 27 | end 28 | else 29 | yield("/nexttarget") 30 | end -------------------------------------------------------------------------------- /SND Legacy/MacroChainer.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | 3 | ******************************************************************************** 4 | * Macro Chainer * 5 | * Version 0.0.1 * 6 | ******************************************************************************** 7 | 8 | Used to chain together a bunch of SND macros, one after the other. I mostly use 9 | it to chain together all my desired dailies, but you can use it for whatever. 10 | ]] 11 | 12 | MacrosToRun = 13 | { 14 | "Mini Cactpot", 15 | "Allied Societies Quests", 16 | "Map Gatherer" 17 | } 18 | 19 | yield("/wait 5") 20 | for _, macro in ipairs(MacrosToRun) do 21 | yield("/snd run "..macro) 22 | repeat 23 | yield("/wait 1") 24 | until not IsMacroRunningOrQueued(macro) 25 | end -------------------------------------------------------------------------------- /Jump Puzzles/README.md: -------------------------------------------------------------------------------- 1 | # Jump Puzzles 2 | 3 | ## Using the Jump Scripts 4 | 1. Walk to the base of the jump puzzle and start the script. 5 | 2. If you fall, but don't fall all the way down, find the number of which jump 6 | you're on and change `JumpNumber` correspondingly to resume from there. 7 | 8 | Jumps are VERY server tick dependent, so you may need to run the script multiple 9 | times to reach the top. 10 | 11 | ## Writing Your Own Jump Puzzles 12 | 13 | The jump puzzles in this folder all follow the same template, just replace the 14 | x,y,z coordinates with the ones corresponding to your jump puzzle locations. 15 | 16 | To get these x,y,z copy the following SND macro and run it. This will copy your 17 | character's current coordinates to you clipboard, so you can paste it into your 18 | code. 19 | ``` 20 | x = math.floor(GetPlayerRawXPos()*100)/100 21 | y = math.floor(GetPlayerRawYPos()*100)/100 22 | z = math.floor(GetPlayerRawZPos()*100)/100 23 | SetClipboard("{ x="..x..", y="..y..", z="..z..", wait=0.08 },") 24 | ``` 25 | 26 | The `wait` parameter determines how many seconds of a running start you get 27 | before you jump. Usually the shorter the wait, the shorter the jump. -------------------------------------------------------------------------------- /SND Legacy/Jump Puzzles/README.md: -------------------------------------------------------------------------------- 1 | # Jump Puzzles 2 | 3 | ## Using the Jump Scripts 4 | 1. Walk to the base of the jump puzzle and start the script. 5 | 2. If you fall, but don't fall all the way down, find the number of which jump 6 | you're on and change `JumpNumber` correspondingly to resume from there. 7 | 8 | Jumps are VERY server tick dependent, so you may need to run the script multiple 9 | times to reach the top. 10 | 11 | ## Writing Your Own Jump Puzzles 12 | 13 | The jump puzzles in this folder all follow the same template, just replace the 14 | x,y,z coordinates with the ones corresponding to your jump puzzle locations. 15 | 16 | To get these x,y,z copy the following SND macro and run it. This will copy your 17 | character's current coordinates to you clipboard, so you can paste it into your 18 | code. 19 | ``` 20 | x = math.floor(GetPlayerRawXPos()*100)/100 21 | y = math.floor(GetPlayerRawYPos()*100)/100 22 | z = math.floor(GetPlayerRawZPos()*100)/100 23 | SetClipboard("{ x="..x..", y="..y..", z="..z..", wait=0.08 },") 24 | ``` 25 | 26 | The `wait` parameter determines how many seconds of a running start you get 27 | before you jump. Usually the shorter the wait, the shorter the jump. -------------------------------------------------------------------------------- /SND Legacy/Gold Saucer/Triple Triad Card Packs.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | 3 | ******************************************************************************** 4 | * Firmament Craft All * 5 | * Version 1.0.0 * 6 | ******************************************************************************** 7 | 8 | Created by: pot0to (https://ko-fi.com/pot0to) 9 | 10 | This script will repeatedly purchase a specific triple triad card pack from the 11 | vender in sets of 10, opens them, and repeats until you find the cards you're 12 | looking for. 13 | 14 | ******************************************************************************** 15 | * Settings * 16 | ******************************************************************************** 17 | 18 | Please download Godbert (https://github.com/ufx/SaintCoinach/releases) and 19 | search through the "Item" page to find the item codes. 20 | ]] 21 | 22 | PackName = "Gold Triad Card" 23 | PackId = 10077 24 | ShopSlot = 38 25 | CardsToLookFor = { 26 | 9840, 27 | 9842, 28 | 9848, 29 | 9851 30 | } 31 | 32 | --[[ 33 | ******************************************************************************** 34 | * Code: Don't touch this unless you know what you're doing * 35 | ******************************************************************************** 36 | ]] 37 | 38 | function Main() 39 | if GetItemCount(PackId) > 0 then 40 | if IsAddonVisible("ShopExchangeCurrency") then 41 | yield("/callback ShopExchangeCurrency true -1") 42 | else 43 | yield("/item "..PackName) 44 | 45 | for i, card in ipairs(CardsToLookFor) do 46 | if GetItemCount(card) > 0 then 47 | table.remove(CardsToLookFor, i) 48 | end 49 | end 50 | if #CardsToLookFor == 0 then 51 | Stop = true 52 | end 53 | end 54 | return 55 | end 56 | 57 | if not HasTarget() or GetTargetName() ~= "Triple Triad Trader" then 58 | yield("/target Triple Triad Trader") 59 | return 60 | end 61 | 62 | if IsAddonVisible("SelectIconString") then 63 | yield("/callback SelectIconString true 0") 64 | return 65 | end 66 | 67 | if IsAddonVisible("SelectYesno") then 68 | yield("/callback SelectYesno true 0") 69 | return 70 | end 71 | 72 | if IsAddonVisible("ShopExchangeCurrency") then 73 | yield("/callback ShopExchangeCurrency true 0 "..ShopSlot.." 10") 74 | return 75 | end 76 | 77 | yield("/interact") 78 | end 79 | 80 | Stop = false 81 | while not Stop do 82 | Main() 83 | yield("/wait 0.5") 84 | end -------------------------------------------------------------------------------- /SND Legacy/Jump Puzzles/5 - Endwalker/14 - Ruveydah Fibers Rooftop Garden (Radz-at-Han).lua: -------------------------------------------------------------------------------- 1 | JumpNumber = 1 -- where to start 2 | 3 | -- wait=0 for a standing jump 4 | -- wait=0.08 for a running short jump 5 | -- wait=0.1 for a running long jump 6 | -- no wait for no jump 7 | JumpPoints = { 8 | { x=-92.61, y=14.0, z=149.47 }, 9 | { x=-93.97, y=14.61, z=148.17, wait=0.02 }, 10 | { x=-95.24, y=15.48, z=147.02, wait=0 }, 11 | { x=-94.5, y=16.62, z=145.71, wait=0.02 }, 12 | { x=-94.56, y=17.61, z=144.06, wait=0.02 }, 13 | { x=-94.84, y=18.48, z=143.32, wait=0 }, 14 | { x=-95.68, y=19.62, z=141.76, wait=0.08 }, 15 | { x=-97.22, y=20.22, z=144.53, wait=0.08 }, 16 | { x=-97.74, y=21.9, z=146.16, wait=0 }, 17 | { x=-99.49, y=17.51, z=152.82, wait=0.1 }, -- 10, on cart 18 | { x=-102.47, y=17.74, z=151.43 }, 19 | { x=-104.6, y=19.62, z=151.26, wait=0.08 }, 20 | { x=-108.02, y=19.4, z=154.95 }, 21 | { x=-107.48, y=21.15, z=157.88, wait=0.1 }, -- 14, on lamp post 22 | { x=-108.82, y=21.98, z=159.65, wait=0.08 }, 23 | { x=-109.32, y=23.78, z=160.26, wait=0.01 }, 24 | { x=-109.86, y=25.49, z=160.13, wait=0.02 }, 25 | { x=-110.08, y=26.94, z=163.32, wait=0.1 }, 26 | { x=-110.82, y=28.25, z=164.09, wait=0.02 }, 27 | { x=-108.48, y=28.25, z=166.44 }, 28 | { x=-108.07, y=29.64, z=166.76, wait=0 }, 29 | { x=-109.1, y=30.82, z=165.82, wait=0.02 }, 30 | { x=-111.13, y=30.82, z=163.77, wait=0.08 }, 31 | { x=-109.65, y=31.81, z=161.06, wait=0.1 }, -- 24, on long angled beam 32 | { x=-110.19, y=33.43, z=159.93, wait=0.02 }, 33 | { x=-108.68, y=34.81, z=156.45, wait=0.1 }, 34 | { x=-105.81, y=36.46, z=153.77, wait=0.2 }, 35 | { x=-100.80, y=36.54, z=152.05, wait=0.2 }, 36 | { x=-100.75, y=36.54, z=149.71 }, 37 | { x=-98.25, y=37.07, z=148.46, wait=0.08 }, -- 30, on platform with crates 38 | { x=-92.01, y=37.07, z=144.02 }, 39 | { x=-89.95, y=37.07, z=146.3 }, 40 | { x=-88.58, y=38.16, z=144.65, wait=0.02 }, -- 33, on barrels 41 | { x=-86.74, y=39.08, z=144.08, wait=0.02 }, 42 | { x=-87.55, y=40.16, z=143.36, wait=0.01 }, 43 | { x=-89.53, y=41.08, z=143.4, wait=0.01 }, 44 | { x=-92.14, y=41.08, z=141.96 }, 45 | { x=-96.66, y=40.34, z=145.5, wait=0.1 }, 46 | { x=-97.45, y=40.34, z=146.42 }, 47 | { x=-98.05, y=41.9, z=148.21, wait=0.08 }, 48 | { x=-99.16, y=42.9, z=148.6, wait=0 }, 49 | { x=-98.63, y=42.9, z=148.5 }, 50 | { x=-97.51, y=44.2, z=148.27, wait=0 }, 51 | { x=-98.72, y=45.19, z=149.13, wait=0 }, 52 | { x=-99.73, y=46.33, z=147.2, wait=0.08 }, -- 44, top 53 | } 54 | 55 | function Jump() 56 | local jumpData = JumpPoints[JumpNumber] 57 | PathMoveTo(jumpData.x, jumpData.y, jumpData.z) 58 | if jumpData.wait ~=nil then 59 | yield("/wait "..jumpData.wait) 60 | yield("/gaction jump") 61 | end 62 | repeat 63 | yield("/wait 0.1") 64 | until not PathIsRunning() 65 | yield("/wait 0.5") 66 | JumpNumber = JumpNumber + 1 67 | end 68 | 69 | while JumpNumber <= #JumpPoints do 70 | Jump() 71 | end -------------------------------------------------------------------------------- /SND Legacy/Jump Puzzles/3 - Stormblood/23 - Bokairo Inn.lua: -------------------------------------------------------------------------------- 1 | JumpNumber = 1 -- where to start 2 | 3 | -- wait=0 for a standing jump 4 | -- wait=0.08 for a running short jump 5 | -- wait=0.1 for a running long jump 6 | -- no wait for no jump 7 | JumpPoints = { 8 | { x=-71.08, y=18.0, z=-163.48 }, 9 | { x=-70.51, y=19.56, z=-163.55, wait=0 }, 10 | { x=-68.75, y=20.67, z=-163.53, wait=0.08 }, 11 | { x=-50.73, y=20.36, z=-164.27 }, -- 4, edge of roof, right before stepping on rope 12 | { x=-50.73, y=18.84, z=-166.43 }, -- 5, on rope 13 | { x=-50.72, y=18.82, z=-173.75 }, -- 6, other end of rope 14 | { x=-50.73, y=20.37, z=-175.9, wait=0.08 }, -- 7, on other roof 15 | { x=-48.93, y=22.54, z=-178.88 }, 16 | { x=-47.27, y=24.4, z=-180.06, wait=0.08 }, 17 | { x=-49.88, y=24.43, z=-180.03 }, -- 10 18 | { x=-51.06, y=25.18, z=-180.01 }, 19 | { x=-61.88, y=31.76, z=-179.93 }, 20 | { x=-62.9, y=32.85, z=-179.99, wait=0.08 }, 21 | { x=-66.15, y=29.84, z=-184.13 }, 22 | { x=-70.91, y=29.79, z=-184.0, wait=0.1 }, -- 15, long jump onto outside edge of balcony 23 | { x=-79.75, y=29.79, z=-184.13 }, 24 | { x=-79.85, y=29.47, z=-180.2 }, 25 | { x=-81.35, y=31.41, z=-179.91, wait=0 }, -- 18, jump onto sign 26 | { x=-86.32, y=33.2, z=-180.04 }, 27 | { x=-90.8, y=31.41, z=-179.86 }, -- 20 28 | { x=-92.22, y=29.47, z=-180.28 }, -- 21, drop down off other edge of sign 29 | { x=-92.2, y=29.79, z=-184.14 }, 30 | { x=-92.34, y=29.79, z=-186.24, wait=0.08 }, --23, jump onto balcony 31 | { x=-98.73, y=29.79, z=-186.06 }, 32 | { x=-103.13, y=30.7, z=-186.13, wait=0.08 }, -- 25, jump out onto roof 33 | { x=-105.47, y=35.42, z=-211.49 }, 34 | { x=-103.32, y=35.76, z=-211.88 }, 35 | { x=-101.19, y=37.0, z=-209.27 }, 36 | { x=-101.01, y=38.26, z=-211.8, wait=0.08 }, 37 | { x=-100.51, y=40.01, z=-211.58, wait=0.08 }, -- 30, onto railing 38 | { x=-100.56, y=40.01, z=-213.45 }, -- 31, onto balcony 39 | { x=-72.41, y=38.26, z=-213.77 }, 40 | { x=-71.68, y=40.01, z=-213.41, wait=0 }, -- 33, onto railing 41 | { x=-71.41, y=40.01, z=-212.62 }, 42 | { x=-71.47, y=40.01, z=-185.29 }, 43 | { x=-81.17, y=39.96, z=-185.46 }, 44 | { x=-81.07, y=41.7, z=-181.94, wait=0.1 }, 45 | { x=-81.05, y=43.5, z=-184.65, wait=0.08 }, 46 | { x=-81.25, y=43.5, z=-184.66 }, 47 | { x=-75.84, y=43.6, z=-184.49, wait=0.2 }, 48 | { x=-72.41, y=45.31, z=-184.6, wait=0.1 }, -- 40 49 | { x=-72.48, y=46.82, z=-185.38, wait=0.08 }, -- 41, on roof 50 | { x=-85.15, y=52.28, z=-191.26 }, 51 | { x=-86.25, y=53.35, z=-193.51, wait=0.08 }, 52 | } 53 | 54 | function Jump() 55 | local jumpData = JumpPoints[JumpNumber] 56 | if jumpData.sprint then 57 | yield("/generalaction sprint") 58 | yield("/wait 1") 59 | end 60 | 61 | PathMoveTo(jumpData.x, jumpData.y, jumpData.z) 62 | if jumpData.wait ~=nil then 63 | yield("/wait "..jumpData.wait) 64 | yield("/gaction jump") 65 | end 66 | repeat 67 | yield("/wait 0.1") 68 | until not PathIsRunning() 69 | yield("/wait 0.5") 70 | JumpNumber = JumpNumber + 1 71 | end 72 | 73 | while JumpNumber <= #JumpPoints do 74 | Jump() 75 | end -------------------------------------------------------------------------------- /SND Legacy/Crafters and Gatherers/Firmament/FirmamentCraftAll.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | 3 | ******************************************************************************** 4 | * Firmament Craft All * 5 | * Version 1.0.0 * 6 | ******************************************************************************** 7 | 8 | Created by: pot0to (https://ko-fi.com/pot0to) 9 | 10 | This script will teleport you to the firmament, switch to each crafter class and 11 | run FirmamentCrafting.lua for each of those classes. You will need 12 | FirmamentCrafting.lua in order for this to work. 13 | 14 | ******************************************************************************** 15 | * Settings * 16 | ******************************************************************************** 17 | ]] 18 | 19 | MacroName = "Craft Skybuilders' Items" -- this is what you named the FirmamentCrafting.lua script in SND 20 | 21 | --[[ 22 | ******************************************************************************** 23 | * Code: Don't touch this unless you know what you're doing * 24 | ******************************************************************************** 25 | ]] 26 | 27 | Classes = { 28 | "Carpenter", 29 | "Blacksmith", 30 | "Armorer", 31 | "Goldsmith", 32 | "Leatherworker", 33 | "Weaver", 34 | "Alchemist", 35 | "Culinarian" 36 | } 37 | 38 | CharacterCondition = { 39 | casting=27, 40 | occupiedInEvent=31, 41 | occupiedInQuestEvent=32, 42 | occupied=33, 43 | betweenAreas=45, 44 | beingMoved=70 45 | } 46 | 47 | local Npcs = 48 | { 49 | turnInNpc = "Potkin", 50 | kupoVouchersNpc = "Lizbeth", 51 | x = 52.750366, y = -16, z = 168.9325 52 | } 53 | 54 | FoundationZoneId = 418 55 | FirmamentZoneId = 886 56 | function TeleportTo(aetheryteName) 57 | yield("/tp "..aetheryteName) 58 | yield("/wait 1") -- wait for casting to begin 59 | while GetCharacterCondition(CharacterCondition.casting) do 60 | LogInfo("[FATE] Casting teleport...") 61 | yield("/wait 1") 62 | end 63 | yield("/wait 1") -- wait for that microsecond in between the cast finishing and the transition beginning 64 | while GetCharacterCondition(CharacterCondition.betweenAreas) do 65 | LogInfo("[FATE] Teleporting...") 66 | yield("/wait 1") 67 | end 68 | yield("/wait 1") 69 | end 70 | 71 | if not (IsInZone(FoundationZoneId) or IsInZone(FirmamentZoneId)) then 72 | TeleportTo("Foundation") 73 | end 74 | if IsInZone(FoundationZoneId) then 75 | yield("/target aetheryte") 76 | yield("/wait 1") 77 | if GetTargetName() == "aetheryte" then 78 | yield("/interact") 79 | end 80 | repeat 81 | yield("/wait 1") 82 | until IsAddonVisible("SelectString") 83 | yield("/callback SelectString true 2") 84 | repeat 85 | yield("/wait 1") 86 | until IsInZone(FirmamentZoneId) and not GetCharacterCondition(CharacterCondition.betweenAreas) 87 | end 88 | 89 | PathfindAndMoveTo(Npcs.x, Npcs.y, Npcs.z) 90 | repeat 91 | yield("/wait 1") 92 | until GetDistanceToPoint(Npcs.x, Npcs.y, Npcs.z) < 20 93 | 94 | yield("/vnav stop") 95 | 96 | for _, class in ipairs(Classes) do 97 | yield("/echo Crafting for "..class) 98 | yield("/gs change "..class) 99 | yield("/wait 5") 100 | 101 | yield("/snd run "..MacroName) 102 | repeat 103 | yield("/wait 5") 104 | until not IsMacroRunningOrQueued(MacroName) 105 | 106 | repeat 107 | yield("/callback RecipeNote true -1") 108 | yield("/wait 1") 109 | until not IsAddonVisible("RecipeNote") 110 | end -------------------------------------------------------------------------------- /SND Legacy/Fate Farming/Companion Scripts/Multi Zone Farming.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | 3 | ******************************************************************************** 4 | * Multi Zone Farming * 5 | * Version 1.0.1 * 6 | ******************************************************************************** 7 | 8 | Multi zone farming script meant to be used with `Fate Farming.lua`. This will go 9 | down the list of zones and farm fates until there are no eligible fates left, 10 | then teleport to the next zone and restart the fate farming script. 11 | 12 | Created by: pot0to (https://ko-fi.com/pot0to) 13 | 14 | -> 1.0.1 Added check for death and unexpected combat 15 | First release 16 | 17 | --#region Settings 18 | 19 | --[[ 20 | ******************************************************************************** 21 | * Settings * 22 | ******************************************************************************** 23 | ]] 24 | 25 | FateMacro = "Fate Farming Companion" -- Name of whatever you nicknamed the base fate farming SND script 26 | 27 | -- Ctrl+F through Fate Farming.lua to find the zoneIds, or find them in Godbert 28 | ZonesToFarm = 29 | { 30 | { zoneName = "Urqopacha", zoneId = 1187 }, 31 | { zoneName = "Kozama'uka", zoneId = 1188 }, 32 | { zoneName = "Yak T'el", zoneId = 1189 }, 33 | { zoneName = "Shaaloani", zoneId = 1190 }, 34 | { zoneName = "Heritage Found", zoneId = 1191 }, 35 | { zoneName = "Living Memory", zoneId = 1192 } 36 | } 37 | 38 | --#endregion Settings 39 | 40 | ------------------------------------------------------------------------------------------------------------------------------------------------------ 41 | 42 | --[[ 43 | ************************************************************** 44 | * Code: Don't touch this unless you know what you're doing * 45 | ************************************************************** 46 | ]] 47 | 48 | CharacterCondition = { 49 | casting=27, 50 | betweenAreas=45 51 | } 52 | 53 | function TeleportTo(aetheryteName) 54 | yield("/tp "..aetheryteName) 55 | yield("/wait 1") -- wait for casting to begin 56 | while GetCharacterCondition(CharacterCondition.casting) do 57 | yield("/wait 1") 58 | end 59 | yield("/wait 1") -- wait for that microsecond in between the cast finishing and the transition beginning 60 | while GetCharacterCondition(CharacterCondition.betweenAreas) do 61 | yield("/wait 1") 62 | end 63 | yield("/wait 1") 64 | end 65 | 66 | yield("/at y") 67 | FarmingZoneIndex = 1 68 | OldBicolorGemCount = GetItemCount(26807) 69 | while true do 70 | if not IsPlayerOccupied() and not IsMacroRunningOrQueued(FateMacro) then 71 | if GetCharacterCondition(2) or GetCharacterCondition(26) or GetZoneID() == ZonesToFarm[FarmingZoneIndex].zoneId then 72 | LogInfo("[MultiZone] Starting FateMacro") 73 | yield("/snd run "..FateMacro) 74 | repeat 75 | yield("/wait 3") 76 | until not IsMacroRunningOrQueued(FateMacro) 77 | LogInfo("[MultiZone] FateMacro has stopped") 78 | NewBicolorGemCount = GetItemCount(26807) 79 | if NewBicolorGemCount == OldBicolorGemCount then 80 | yield("/echo Bicolor Count: "..NewBicolorGemCount) 81 | FarmingZoneIndex = (FarmingZoneIndex % #ZonesToFarm) + 1 82 | else 83 | OldBicolorGemCount = NewBicolorGemCount 84 | end 85 | else 86 | LogInfo("[MultiZone] Teleporting to "..ZonesToFarm[FarmingZoneIndex].zoneName) 87 | TeleportTo(GetAetheryteName(GetAetherytesInZone(ZonesToFarm[FarmingZoneIndex].zoneId)[0])) 88 | end 89 | end 90 | yield("/wait 1") 91 | end -------------------------------------------------------------------------------- /SND Legacy/Gold Saucer/MiniCactpot.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | 3 | ******************************************************************************** 4 | * Mini Cactpot * 5 | * Version 1.1.1 * 6 | ******************************************************************************** 7 | 8 | Created by: pot0to (https://ko-fi.com/pot0to) 9 | Description: Teleports to Gold Saucer, runs mini cactpot. 10 | 11 | ******************************************************************************** 12 | * Required Plugins * 13 | ******************************************************************************** 14 | 15 | 1. Lifestream 16 | 3. TextAdvance 17 | 4. Vnavmesh 18 | 5. Saucy 19 | 20 | ******************************************************************************** 21 | * Code: Don't touch this unless you know what you're doing * 22 | ******************************************************************************** 23 | ]] 24 | 25 | function Teleport(aetheryteName) 26 | yield("/li tp "..aetheryteName) 27 | yield("/wait 1") 28 | while GetCharacterCondition(27) do 29 | yield("/wait 0.1") 30 | end 31 | yield("/wait 1") 32 | while GetCharacterCondition(45) do 33 | yield("/wait 0.1") 34 | end 35 | end 36 | 37 | function Ready() 38 | if not IsInZone(144) then 39 | Teleport("Gold Saucer") 40 | else 41 | State = CharacterStates.goToCashier 42 | end 43 | end 44 | 45 | local Npc = { name = "Mini Cactpot Broker", x=-50, y=1, z=22 } 46 | RewardClaimed = false 47 | function GoToCashier() 48 | if GetDistanceToPoint(-1, 3, -1) <= 8 and PathIsRunning() then 49 | yield("/gaction jump") 50 | yield("/wait 3") 51 | return 52 | end 53 | 54 | if GetDistanceToPoint(Npc.x, Npc.y, Npc.z) > 5 then 55 | if not PathfindInProgress() and not PathIsRunning() then 56 | PathfindAndMoveTo(Npc.x, Npc.y, Npc.z) 57 | end 58 | return 59 | end 60 | 61 | if PathfindInProgress() or PathIsRunning() then 62 | yield("/vnav stop") 63 | end 64 | 65 | State = CharacterStates.playMiniCactpot 66 | end 67 | 68 | TicketsPurchased = false 69 | function PlayMiniCactpot() 70 | -- TODO: replace with mini cactpot name 71 | 72 | if IsAddonVisible("LotteryDaily") then 73 | yield("/wait 1") 74 | elseif IsAddonVisible("SelectIconString") then 75 | yield("/callback SelectIconString true 0") 76 | elseif IsAddonVisible("Talk") then 77 | if not HasPlugin("TextAdvance") then 78 | yield("/click Talk Click") 79 | end 80 | elseif IsAddonVisible("SelectYesno") then 81 | yield("/callback SelectYesno true 0") 82 | elseif GetDistanceToPoint(Npc.x, Npc.y, Npc.z) > 5 then 83 | PathfindAndMoveTo(Npc.x, Npc.y, Npc.z) 84 | elseif PathIsRunning() or PathfindInProgress() then 85 | yield("/vnav stop") 86 | elseif TicketsPurchased and not GetCharacterCondition(32) then 87 | State = CharacterStates.endState 88 | elseif not HasTarget() or GetTargetName() ~= Npc.name then 89 | yield("/target "..Npc.name) 90 | else 91 | yield("/interact") 92 | TicketsPurchased = true 93 | end 94 | end 95 | 96 | function EndState() 97 | if IsAddonVisible("SelectString") then 98 | yield("/callback SelectString true -1") 99 | else 100 | StopFlag = true 101 | end 102 | end 103 | 104 | CharacterStates = 105 | { 106 | ready = Ready, 107 | goToCashier = GoToCashier, 108 | playMiniCactpot = PlayMiniCactpot, 109 | endState = EndState 110 | } 111 | 112 | StopFlag = false 113 | State = CharacterStates.ready 114 | yield("/at y") 115 | while not StopFlag do 116 | State() 117 | yield("/wait 0.1") 118 | end -------------------------------------------------------------------------------- /Jump Puzzles/5 - Endwalker/Sightseeing Log 14 - Ruveydah Fibers Rooftop Garden (Radz-at-Han).lua: -------------------------------------------------------------------------------- 1 | --[=====[ 2 | [[SND Metadata]] 3 | author: pot0to 4 | version: 2.0.0 5 | description: | 6 | Support via https://ko-fi.com/pot0to 7 | Radz-at-Han Palace and sightseeing log: https://www.youtube.com/watch?v=aWir-tIjIRw 8 | plugin_dependencies: 9 | - vnavmesh 10 | configs: 11 | Starting Jump Number: 12 | description: Start with step 1, but if you fall due to server tick issues, 13 | you can use this to restart the jump puzzle from any step. See the 14 | "Jump Points" list 15 | default: 1 16 | [[End Metadata]] 17 | --]=====] 18 | 19 | -- wait=0 for a standing jump 20 | -- wait=0.08 for a running short jump 21 | -- wait=0.1 for a running long jump 22 | -- no wait for no jump 23 | JumpPoints = { 24 | { x=-92.61, y=14.0, z=149.47 }, 25 | { x=-93.97, y=14.61, z=148.17, wait=0.02 }, 26 | { x=-95.24, y=15.48, z=147.02, wait=0 }, 27 | { x=-94.5, y=16.62, z=145.71, wait=0.02 }, 28 | { x=-94.56, y=17.61, z=144.06, wait=0.02 }, 29 | { x=-94.84, y=18.48, z=143.32, wait=0 }, 30 | { x=-95.68, y=19.62, z=141.76, wait=0.08 }, 31 | { x=-97.22, y=20.22, z=144.53, wait=0.08 }, 32 | { x=-97.74, y=21.9, z=146.16, wait=0 }, 33 | { x=-99.49, y=17.51, z=152.82, wait=0.1 }, -- 10, on cart 34 | { x=-102.47, y=17.74, z=151.43 }, 35 | { x=-104.6, y=19.62, z=151.26, wait=0.08 }, 36 | { x=-108.02, y=19.4, z=154.95 }, 37 | { x=-107.48, y=21.15, z=157.88, wait=0.1 }, -- 14, on lamp post 38 | { x=-108.82, y=21.98, z=159.65, wait=0.08 }, 39 | { x=-109.32, y=23.78, z=160.26, wait=0.01 }, 40 | { x=-109.86, y=25.49, z=160.13, wait=0.02 }, 41 | { x=-110.08, y=26.94, z=163.32, wait=0.1 }, 42 | { x=-110.82, y=28.25, z=164.09, wait=0.02 }, 43 | { x=-108.48, y=28.25, z=166.44 }, 44 | { x=-108.07, y=29.64, z=166.76, wait=0 }, 45 | { x=-109.1, y=30.82, z=165.82, wait=0.02 }, 46 | { x=-111.13, y=30.82, z=163.77, wait=0.08 }, 47 | { x=-109.65, y=31.81, z=161.06, wait=0.1 }, -- 24, on long angled beam 48 | { x=-110.19, y=33.43, z=159.93, wait=0.02 }, 49 | { x=-108.68, y=34.81, z=156.45, wait=0.1 }, 50 | { x=-105.81, y=36.46, z=153.77, wait=0.2 }, 51 | { x=-100.80, y=36.54, z=152.05, wait=0.2 }, 52 | { x=-100.75, y=36.54, z=149.71 }, 53 | { x=-98.25, y=37.07, z=148.46, wait=0.08 }, -- 30, on platform with crates 54 | { x=-92.01, y=37.07, z=144.02 }, 55 | { x=-89.95, y=37.07, z=146.3 }, 56 | { x=-88.58, y=38.16, z=144.65, wait=0.02 }, -- 33, on barrels 57 | { x=-86.74, y=39.08, z=144.08, wait=0.02 }, 58 | { x=-87.55, y=40.16, z=143.36, wait=0.01 }, 59 | { x=-89.53, y=41.08, z=143.4, wait=0.01 }, 60 | { x=-92.14, y=41.08, z=141.96 }, 61 | { x=-96.66, y=40.34, z=145.5, wait=0.1 }, 62 | { x=-97.45, y=40.34, z=146.42 }, 63 | { x=-98.05, y=41.9, z=148.21, wait=0.08 }, 64 | { x=-99.16, y=42.9, z=148.6, wait=0 }, 65 | { x=-98.63, y=42.9, z=148.5 }, 66 | { x=-97.51, y=44.2, z=148.27, wait=0 }, 67 | { x=-98.72, y=45.19, z=149.13, wait=0 }, 68 | { x=-99.73, y=46.33, z=147.2, wait=0.08 }, -- 44, top 69 | } 70 | 71 | import ("System") 72 | import("System.Numerics") 73 | GenericListType = Type.GetType("System.Collections.Generic.List`1[System.Numerics.Vector3]") 74 | 75 | function Jump() 76 | local jumpData = JumpPoints[JumpNumber] 77 | if jumpData.sprint then 78 | yield("/generalaction sprint") 79 | yield("/wait 1") 80 | end 81 | 82 | local vectorList = Activator.CreateInstance(GenericListType) 83 | vectorList:Add(Vector3(jumpData.x, jumpData.y, jumpData.z)) 84 | IPC.vnavmesh.MoveTo(vectorList, false) 85 | if jumpData.wait ~= nil then 86 | yield("/wait "..jumpData.wait) 87 | yield("/gaction jump") 88 | end 89 | repeat 90 | yield("/wait 0.1") 91 | until not IPC.vnavmesh.IsRunning() 92 | yield("/wait 0.5") 93 | JumpNumber = JumpNumber + 1 94 | end 95 | 96 | JumpNumber = Config.Get("Starting Jump Number") 97 | while JumpNumber <= #JumpPoints do 98 | Jump() 99 | end -------------------------------------------------------------------------------- /SND Legacy/Gold Saucer/Any Way the Wind Blows.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | 3 | ******************************************************************************** 4 | * Any Way the Wind Blows * 5 | * Version 1.0.0 * 6 | ******************************************************************************** 7 | 8 | Created by: pot0to (https://ko-fi.com/pot0to) 9 | 10 | Plays the Gold Saucer GATE "Any Way the Wind Blows" over and over to farm the 11 | achievement WTF Fungah I, II, III. There's a special spot on the stage that is 12 | statistically less likely to get hit based on the aoe patterns (though never 13 | guaranteed to win). This script will AFK in front of where the NPC will spawn, 14 | talk to him to enter the GATE, place you at the special spot for 5 min (long 15 | enough to finish the GATE or lose), then repeat. 16 | 17 | ******************************************************************************** 18 | * Required Plugins * 19 | ******************************************************************************** 20 | 21 | 1. SND 22 | 2. Vnavmesh 23 | 3. Lifestream 24 | 4. TextAdvance 25 | 26 | ******************************************************************************** 27 | * Code: Don't touch this unless you know what you're doing * 28 | ******************************************************************************** 29 | ]] 30 | 31 | Npc = 32 | { 33 | x=77, y=-6, z=-70, 34 | name="Supercilious Spellweaver" 35 | } 36 | 37 | OnStage = false 38 | function Main() 39 | if OnStage then 40 | PathfindAndMoveTo(67.01, -4.48, -24.57) 41 | yield("/wait "..5*60) 42 | OnStage = false 43 | return 44 | end 45 | 46 | if GetDistanceToPoint(Npc.x, Npc.y, Npc.z) > 7 then 47 | if not PathfindInProgress() and not PathIsRunning() then 48 | PathfindAndMoveTo(Npc.x, Npc.y, Npc.z) 49 | end 50 | return 51 | elseif PathfindInProgress() or PathIsRunning() then 52 | yield("/vnav stop") 53 | return 54 | end 55 | 56 | if GetTargetName() ~= Npc.name then 57 | yield("/target "..Npc.name) 58 | yield("/wait 0.5") 59 | if GetTargetName() ~= Npc.name then 60 | yield("/wait 30") 61 | else 62 | yield("/echo Found "..Npc.name.."! Starting GATE!") 63 | end 64 | return 65 | end 66 | 67 | if IsAddonVisible("SelectYesno") then 68 | yield("/wait 1") 69 | yield("/callback SelectYesno true 0") 70 | yield("/wait 10") 71 | OnStage = true 72 | return 73 | end 74 | 75 | yield("/interact") 76 | end 77 | 78 | function TeleportTo(aetheryteName) 79 | yield("/li tp "..aetheryteName) 80 | yield("/wait 1") -- wait for casting to begin 81 | while GetCharacterCondition(CharacterCondition.casting) do 82 | LogInfo("[FATE] Casting teleport...") 83 | yield("/wait 1") 84 | end 85 | yield("/wait 1") -- wait for that microsecond in between the cast finishing and the transition beginning 86 | while GetCharacterCondition(CharacterCondition.betweenAreas) do 87 | LogInfo("[FATE] Teleporting...") 88 | yield("/wait 1") 89 | end 90 | yield("/wait 1") 91 | end 92 | 93 | CharacterCondition = { 94 | dead=2, 95 | mounted=4, 96 | inCombat=26, 97 | casting=27, 98 | occupiedInEvent=31, 99 | occupiedInQuestEvent=32, 100 | occupied=33, 101 | boundByDuty34=34, 102 | occupiedMateriaExtractionAndRepair=39, 103 | betweenAreas=45, 104 | jumping48=48, 105 | jumping61=61, 106 | occupiedSummoningBell=50, 107 | betweenAreasForDuty=51, 108 | boundByDuty56=56, 109 | mounting57=57, 110 | mounting64=64, 111 | beingMoved=70, 112 | flying=77 113 | } 114 | 115 | yield("/at y") 116 | if not IsInZone(144) then 117 | TeleportTo("Gold Saucer") 118 | end 119 | while true do 120 | Main() 121 | yield("/wait 0.1") 122 | end -------------------------------------------------------------------------------- /Jump Puzzles/3 - Stormblood/Sightseeing Log 23 - Bokairo Inn.lua: -------------------------------------------------------------------------------- 1 | --[=====[ 2 | [[SND Metadata]] 3 | author: pot0to 4 | version: 2.0.0 5 | description: | 6 | Support via https://ko-fi.com/pot0to 7 | Bokairo Inn jump puzzle and sightseeing log: https://www.youtube.com/watch?v=Wl_3FUdCo-o 8 | plugin_dependencies: 9 | - vnavmesh 10 | configs: 11 | Starting Jump Number: 12 | description: Start with step 1, but if you fall due to server tick issues, 13 | you can use this to restart the jump puzzle from any step. See the 14 | "Jump Points" list 15 | default: 1 16 | [[End Metadata]] 17 | --]=====] 18 | 19 | -- wait=0 for a standing jump 20 | -- wait=0.08 for a running short jump 21 | -- wait=0.1 for a running long jump 22 | -- no wait for no jump 23 | JumpPoints = { 24 | { x=-71.08, y=18.0, z=-163.48 }, 25 | { x=-70.51, y=19.56, z=-163.55, wait=0 }, 26 | { x=-68.75, y=20.67, z=-163.53, wait=0.08 }, 27 | { x=-50.73, y=20.36, z=-164.27 }, -- 4, edge of roof, right before stepping on rope 28 | { x=-50.73, y=18.84, z=-166.43 }, -- 5, on rope 29 | { x=-50.72, y=18.82, z=-173.75 }, -- 6, other end of rope 30 | { x=-50.73, y=20.37, z=-175.9, wait=0.08 }, -- 7, on other roof 31 | { x=-48.93, y=22.54, z=-178.88 }, 32 | { x=-47.27, y=24.4, z=-180.06, wait=0.08 }, 33 | { x=-49.88, y=24.43, z=-180.03 }, -- 10 34 | { x=-51.06, y=25.18, z=-180.01 }, 35 | { x=-61.88, y=31.76, z=-179.93 }, 36 | { x=-62.9, y=32.85, z=-179.99, wait=0.08 }, 37 | { x=-66.15, y=29.84, z=-184.13 }, 38 | { x=-70.91, y=29.79, z=-184.0, wait=0.1 }, -- 15, long jump onto outside edge of balcony 39 | { x=-79.75, y=29.79, z=-184.13 }, 40 | { x=-79.85, y=29.47, z=-180.2 }, 41 | { x=-81.35, y=31.41, z=-179.91, wait=0 }, -- 18, jump onto sign 42 | { x=-86.32, y=33.2, z=-180.04 }, 43 | { x=-90.8, y=31.41, z=-179.86 }, -- 20 44 | { x=-92.22, y=29.47, z=-180.28 }, -- 21, drop down off other edge of sign 45 | { x=-92.2, y=29.79, z=-184.14 }, 46 | { x=-92.34, y=29.79, z=-186.24, wait=0.08 }, --23, jump onto balcony 47 | { x=-98.73, y=29.79, z=-186.06 }, 48 | { x=-103.13, y=30.7, z=-186.13, wait=0.08 }, -- 25, jump out onto roof 49 | { x=-105.47, y=35.42, z=-211.49 }, 50 | { x=-103.32, y=35.76, z=-211.88 }, 51 | { x=-101.19, y=37.0, z=-209.27 }, 52 | { x=-101.01, y=38.26, z=-211.8, wait=0.08 }, 53 | { x=-100.51, y=40.01, z=-211.58, wait=0.08 }, -- 30, onto railing 54 | { x=-100.56, y=40.01, z=-213.45 }, -- 31, onto balcony 55 | { x=-72.41, y=38.26, z=-213.77 }, 56 | { x=-71.68, y=40.01, z=-213.41, wait=0 }, -- 33, onto railing 57 | { x=-71.41, y=40.01, z=-212.62 }, 58 | { x=-71.47, y=40.01, z=-185.29 }, 59 | { x=-81.17, y=39.96, z=-185.46 }, 60 | { x=-81.07, y=41.7, z=-181.94, wait=0.1 }, 61 | { x=-81.05, y=43.5, z=-184.65, wait=0.08 }, 62 | { x=-81.25, y=43.5, z=-184.66 }, 63 | { x=-75.84, y=43.6, z=-184.49, wait=0.2 }, 64 | { x=-72.41, y=45.31, z=-184.6, wait=0.1 }, -- 40 65 | { x=-72.48, y=46.82, z=-185.38, wait=0.08 }, -- 41, on roof 66 | { x=-85.15, y=52.28, z=-191.26 }, 67 | { x=-86.25, y=53.35, z=-193.51, wait=0.08 }, 68 | } 69 | 70 | import ("System") 71 | import("System.Numerics") 72 | GenericListType = Type.GetType("System.Collections.Generic.List`1[System.Numerics.Vector3]") 73 | 74 | function Jump() 75 | local jumpData = JumpPoints[JumpNumber] 76 | if jumpData.sprint then 77 | yield("/generalaction sprint") 78 | yield("/wait 1") 79 | end 80 | 81 | local vectorList = Activator.CreateInstance(GenericListType) 82 | vectorList:Add(Vector3(jumpData.x, jumpData.y, jumpData.z)) 83 | IPC.vnavmesh.MoveTo(vectorList, false) 84 | if jumpData.wait ~=nil then 85 | yield("/wait "..jumpData.wait) 86 | yield("/gaction jump") 87 | end 88 | repeat 89 | yield("/wait 0.1") 90 | until not IPC.vnavmesh.IsRunning() 91 | yield("/wait 0.5") 92 | JumpNumber = JumpNumber + 1 93 | end 94 | 95 | JumpNumber = Config.Get("Starting Jump Number") 96 | while JumpNumber <= #JumpPoints do 97 | Jump() 98 | end -------------------------------------------------------------------------------- /SND Legacy/Fate Farming/Companion Scripts/Atma Farming.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | 3 | ******************************************************************************** 4 | * Atma Farming * 5 | * Version 1.0.0 * 6 | ******************************************************************************** 7 | 8 | Atma farming script meant to be used with `Fate Farming.lua`. This will go down 9 | the list of atma farming zones and farm fates until you have 12 of the required 10 | atmas in your inventory, then teleport to the next zone and restart the fate 11 | farming script. 12 | 13 | Created by: pot0to (https://ko-fi.com/pot0to) 14 | 15 | -> 1.0.0 First release 16 | 17 | --#region Settings 18 | 19 | --[[ 20 | ******************************************************************************** 21 | * Settings * 22 | ******************************************************************************** 23 | ]] 24 | 25 | FateMacro = "Fate Farming" 26 | NumberToFarm = 1 -- How many of each atma to farm 27 | 28 | --#endregion Settings 29 | 30 | ------------------------------------------------------------------------------------------------------------------------------------------------------ 31 | 32 | --[[ 33 | ************************************************************** 34 | * Code: Don't touch this unless you know what you're doing * 35 | ************************************************************** 36 | ]] 37 | Atmas = 38 | { 39 | {zoneName = "Middle La Noscea", zoneId = 134, itemName = "Atma of the Ram", itemId = 7856}, 40 | {zoneName = "Lower La Noscea", zoneId = 135, itemName = "Atma of the Fish", itemId = 7859}, 41 | {zoneName = "Western La Noscea", zoneId = 138, itemName = "Atma of the Crab", itemId = 7862}, 42 | {zoneName = "Upper La Noscea", zoneId = 139, itemName = "Atma of the Water-bearer", itemId = 7853}, 43 | {zoneName = "Western Thanalan", zoneId = 140, itemName = "Atma of the Twins", itemId = 7857}, 44 | {zoneName = "Central Thanalan", zoneId = 141, itemName = "Atma of the Scales", itemId = 7861}, 45 | {zoneName = "Eastern Thanalan", zoneId = 145, itemName = "Atma of the Bull", itemId = 7855}, 46 | {zoneName = "Southern Thanalan", zoneId = 146, itemName = "Atma of the Scorpion", itemId = 7852, flying=false}, 47 | {zoneName = "Central Shroud", zoneId = 148, itemName = "Atma of the Maiden", itemId = 7851}, 48 | {zoneName = "East Shroud", zoneId = 152, itemName = "Atma of the Goat", itemId = 7854}, 49 | {zoneName = "North Shroud", zoneId = 154, itemName = "Atma of the Archer", itemId = 7860}, 50 | {zoneName = "Outer La Noscea", zoneId = 180, itemName = "Atma of the Lion", itemId = 7858, flying=false} 51 | } 52 | 53 | CharacterCondition = { 54 | casting=27, 55 | betweenAreas=45 56 | } 57 | 58 | function GetNextAtmaTable() 59 | for _, atmaTable in pairs(Atmas) do 60 | if GetItemCount(atmaTable.itemId) < NumberToFarm then 61 | return atmaTable 62 | end 63 | end 64 | end 65 | 66 | function TeleportTo(aetheryteName) 67 | yield("/tp "..aetheryteName) 68 | yield("/wait 1") -- wait for casting to begin 69 | while GetCharacterCondition(CharacterCondition.casting) do 70 | LogInfo("[FATE] Casting teleport...") 71 | yield("/wait 1") 72 | end 73 | yield("/wait 1") -- wait for that microsecond in between the cast finishing and the transition beginning 74 | while GetCharacterCondition(CharacterCondition.betweenAreas) do 75 | LogInfo("[FATE] Teleporting...") 76 | yield("/wait 1") 77 | end 78 | yield("/wait 1") 79 | end 80 | 81 | yield("/at y") 82 | NextAtmaTable = GetNextAtmaTable() 83 | while NextAtmaTable ~= nil do 84 | if not IsPlayerOccupied() and not IsMacroRunningOrQueued(FateMacro) then 85 | if GetItemCount(NextAtmaTable.itemId) >= NumberToFarm then 86 | NextAtmaTable = GetNextAtmaTable() 87 | elseif not IsInZone(NextAtmaTable.zoneId) then 88 | TeleportTo(GetAetheryteName(GetAetherytesInZone(NextAtmaTable.zoneId)[0])) 89 | else 90 | yield("/snd run "..FateMacro) 91 | end 92 | end 93 | yield("/wait 1") 94 | end -------------------------------------------------------------------------------- /SND Legacy/Gold Saucer/JumboCactpot.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | 3 | ******************************************************************************** 4 | * Jumbo Cactpot * 5 | * Version 1.0.0 * 6 | ******************************************************************************** 7 | 8 | Created by: pot0to (https://ko-fi.com/pot0to) 9 | Description: Teleports to Gold Saucer, picks up last week's cactpot prizes (if you had any), and 10 | purchases 3 new tickets using random numbers. 11 | 12 | ******************************************************************************** 13 | * Required Plugins * 14 | ******************************************************************************** 15 | 16 | 1. Lifestream 17 | 2. TextAdvance 18 | 3. Vnavmesh 19 | 20 | ******************************************************************************** 21 | * Code: Don't touch this unless you know what you're doing * 22 | ******************************************************************************** 23 | ]] 24 | 25 | function Teleport(aetheryteName) 26 | yield("/li tp "..aetheryteName) 27 | while not GetCharacterCondition(45) do 28 | yield("/wait 0.1") 29 | end 30 | while GetCharacterCondition(45) do 31 | yield("/wait 0.1") 32 | end 33 | end 34 | 35 | function Start() 36 | if LifestreamIsBusy() then 37 | return 38 | end 39 | 40 | if not IsInZone(144) then 41 | Teleport("Gold Saucer") 42 | return 43 | end 44 | 45 | yield("/target Aetheryte") 46 | 47 | if not HasTarget() or GetTargetName() ~= "aetheryte" or GetDistanceToTarget() > 7 then 48 | PathfindAndMoveTo(-4.82, 1.04, 2.21) 49 | elseif GetDistanceToTarget() <= 7 then 50 | yield("/vnav stop") 51 | yield("/li Cactpot Board") 52 | State = CharacterStates.claimPrize 53 | end 54 | end 55 | 56 | RewardClaimed = false 57 | function ClaimPrize() 58 | yield("/target Cactpot Cashier") 59 | 60 | if IsAddonVisible("LotteryWeeklyRewardList") then 61 | yield("/callback LotteryWeeklyRewardList true -1") 62 | elseif IsAddonVisible("SelectYesno") then 63 | yield("/callback SelectYesno true 0") 64 | elseif RewardClaimed and not GetCharacterCondition(32) then 65 | State = CharacterStates.purchaseNewTickets 66 | elseif not HasTarget() or GetTargetName() ~= "Cactpot Cashier" or GetDistanceToTarget() > 7 then 67 | PathfindAndMoveTo(123.25, 13.00, -19.35) 68 | elseif GetDistanceToTarget() <= 7 then 69 | yield("/vnav stop") 70 | yield("/interact") 71 | RewardClaimed = true 72 | end 73 | end 74 | 75 | TicketsPurchased = false 76 | function PurchaseNewTickets() 77 | yield("/target Jumbo Cactpot Broker") 78 | 79 | if IsAddonVisible("LotteryWeeklyRewardList") then 80 | yield("/echo You have already purchased tickets this week!") 81 | yield("/callback LotteryWeeklyRewardList true -1") 82 | State = CharacterStates.endState 83 | elseif IsAddonVisible("SelectString") then 84 | yield("/callback SelectString true 0") 85 | elseif IsAddonVisible("SelectYesno") then 86 | yield("/callback SelectYesno true 0") 87 | elseif IsAddonVisible("LotteryWeeklyInput") then 88 | yield("/wait 1") 89 | yield("/callback LotteryWeeklyInput true "..math.random(9999)) 90 | elseif TicketsPurchased and not GetCharacterCondition(32) then 91 | State = CharacterStates.endState 92 | elseif not HasTarget() or GetTargetName() ~= "Jumbo Cactpot Broker" or GetDistanceToTarget() > 7 then 93 | PathfindAndMoveTo(120.26, 13.00, -10.9) 94 | elseif GetDistanceToTarget() <= 7 then 95 | yield("/vnav stop") 96 | yield("/interact") 97 | TicketsPurchased = true 98 | end 99 | 100 | end 101 | 102 | function EndState() 103 | if IsAddonVisible("SelectString") then 104 | yield("/callback SelectString true -1") 105 | else 106 | StopFlag = true 107 | end 108 | end 109 | 110 | CharacterStates = 111 | { 112 | start = Start, 113 | claimPrize = ClaimPrize, 114 | purchaseNewTickets = PurchaseNewTickets, 115 | endState = EndState 116 | } 117 | 118 | StopFlag = false 119 | State = CharacterStates.start 120 | yield("/at y") 121 | while not StopFlag do 122 | State() 123 | yield("/wait 0.1") 124 | end -------------------------------------------------------------------------------- /SND Legacy/Fate Farming/Companion Scripts/Anima Luminous Crystal Farming.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | 3 | ******************************************************************************** 4 | * Anima Luminous Crystal Farming * 5 | * Version 1.0.1 * 6 | ******************************************************************************** 7 | 8 | Anima luminous crystal farming script meant to be used with `Fate Farming.lua`. 9 | This will go down the list of zones and farm fates until you have enough of the 10 | required crystals in your inventory, then teleport to the next zone and restart 11 | the fate farming script. 12 | 13 | Created by: pot0to (https://ko-fi.com/pot0to) 14 | 15 | -> 1.0.1 Added mounted character condition 16 | First release 17 | 18 | --#region Settings 19 | 20 | --[[ 21 | ******************************************************************************** 22 | * Settings * 23 | ******************************************************************************** 24 | ]] 25 | 26 | FateMacro = "Fate Farming" 27 | NumberToFarm = 1 -- How many of each atma to farm 28 | 29 | --#endregion Settings 30 | 31 | ------------------------------------------------------------------------------------------------------------------------------------------------------ 32 | 33 | --[[ 34 | ************************************************************** 35 | * Code: Don't touch this unless you know what you're doing * 36 | ************************************************************** 37 | ]] 38 | Atmas = 39 | { 40 | {zoneName = "Coerthas Western Highlands", zoneId = 397, itemName = "Luminous Ice Crystal", itemId = 13569}, 41 | {zoneName = "The Dravanian Forelands", zoneId = 398, itemName = "Luminous Earth Crystal", itemId = 13572}, 42 | {zoneName = "The Dravanian Hinterlands", zoneId = 399, itemName = "Luminous Water Crystal", itemId = 13574}, 43 | {zoneName = "The Churning Mists", zoneId = 400, itemName = "Luminous Lightning Crystal", itemId = 13573}, 44 | {zoneName = "Sea of Clouds", zoneId = 401, itemName = "Luminous Wind Crystal", itemId = 13570}, 45 | {zoneName = "Azys Lla", zoneId = 402, itemName = "Luminous Fire Crystal", itemId = 13571} 46 | } 47 | 48 | CharacterCondition = { 49 | mounted=4, 50 | casting=27, 51 | betweenAreas=45 52 | } 53 | 54 | function GetNextAtmaTable() 55 | for _, atmaTable in pairs(Atmas) do 56 | if GetItemCount(atmaTable.itemId) < NumberToFarm then 57 | return atmaTable 58 | end 59 | end 60 | end 61 | 62 | function TeleportTo(aetheryteName) 63 | yield("/tp "..aetheryteName) 64 | yield("/wait 1") -- wait for casting to begin 65 | while GetCharacterCondition(CharacterCondition.casting) do 66 | LogInfo("[AnimaFarming] Casting teleport...") 67 | yield("/wait 1") 68 | end 69 | yield("/wait 1") -- wait for that microsecond in between the cast finishing and the transition beginning 70 | while GetCharacterCondition(CharacterCondition.betweenAreas) do 71 | LogInfo("[AnimaFarming] Teleporting...") 72 | yield("/wait 1") 73 | end 74 | yield("/wait 1") 75 | end 76 | 77 | function GoToDravanianHinterlands() 78 | if GetCharacterCondition(CharacterCondition.betweenAreas) then 79 | return 80 | elseif IsInZone(478) then 81 | if not GetCharacterCondition(CharacterCondition.mounted) then 82 | State = CharacterState.mounting 83 | LogInfo("[AnimaFarming] State Change: Mounting") 84 | elseif not PathIsRunning() and not PathfindInProgress() then 85 | PathfindAndMoveTo(148.51, 207.0, 118.47) 86 | end 87 | else 88 | TeleportTo("Idyllshire") 89 | end 90 | end 91 | 92 | yield("/at y") 93 | NextAtmaTable = GetNextAtmaTable() 94 | while NextAtmaTable ~= nil do 95 | if not IsPlayerOccupied() and not IsMacroRunningOrQueued(FateMacro) then 96 | if GetItemCount(NextAtmaTable.itemId) >= NumberToFarm then 97 | NextAtmaTable = GetNextAtmaTable() 98 | elseif not IsInZone(NextAtmaTable.zoneId) then 99 | if NextAtmaTable.zoneId == 399 then 100 | GoToDravanianHinterlands() 101 | else 102 | TeleportTo(GetAetheryteName(GetAetherytesInZone(NextAtmaTable.zoneId)[0])) 103 | end 104 | else 105 | yield("/snd run "..FateMacro) 106 | end 107 | end 108 | yield("/wait 1") 109 | end -------------------------------------------------------------------------------- /Gold Saucer/Mini Cactpot.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | 3 | ******************************************************************************** 4 | * Mini Cactpot * 5 | * Version 2.0.0 * 6 | ******************************************************************************** 7 | 8 | Created by: pot0to (https://ko-fi.com/pot0to) 9 | Description: Teleports to Gold Saucer, runs mini cactpot. 10 | 11 | ******************************************************************************** 12 | * Required Plugins * 13 | ******************************************************************************** 14 | 15 | 1. Lifestream 16 | 3. TextAdvance 17 | 4. IPC.vnavmesh 18 | 5. Saucy 19 | 20 | ******************************************************************************** 21 | * Code: Don't touch this unless you know what you're doing * 22 | ******************************************************************************** 23 | ]] 24 | import("System.Numerics") 25 | 26 | LogPrefix = "[MiniCactpot]" 27 | 28 | CharacterCondition = 29 | { 30 | casting=27, 31 | occupiedShopkeeper = 32, 32 | betweenAreas=45 33 | } 34 | 35 | function Teleport(aetheryteName) 36 | yield("/li tp "..aetheryteName) 37 | yield("/wait 1") 38 | while Svc.Condition[CharacterCondition.casting] do 39 | yield("/wait 0.1") 40 | end 41 | yield("/wait 1") 42 | while Svc.Condition[CharacterCondition.betweenAreas] do 43 | yield("/wait 0.1") 44 | end 45 | end 46 | 47 | function Ready() 48 | if Svc.ClientState.TerritoryType ~= 144 then 49 | Teleport("Gold Saucer") 50 | else 51 | State = CharacterState.goToCashier 52 | end 53 | end 54 | 55 | function GetDistanceToPoint(vec3) 56 | local px = Svc.ClientState.LocalPlayer.Position.X 57 | local py = Svc.ClientState.LocalPlayer.Position.Y 58 | local pz = Svc.ClientState.LocalPlayer.Position.Z 59 | local distance = math.sqrt((vec3.X - px)^2 + (vec3.Y-py)^2 + (vec3.Z-pz)^2) 60 | return distance 61 | end 62 | 63 | local Npc = { name = "Mini Cactpot Broker", position=Vector3(-50, 1, 22) } 64 | local Aetheryte = Vector3(-1, 3, -1) 65 | RewardClaimed = false 66 | function GoToCashier() 67 | if GetDistanceToPoint(Aetheryte) <= 8 and IPC.vnavmesh.IsRunning() then 68 | yield("/gaction jump") 69 | yield("/wait 3") 70 | return 71 | end 72 | 73 | if GetDistanceToPoint(Npc.position) > 5 then 74 | if not IPC.vnavmesh.PathfindInProgress() and not IPC.vnavmesh.IsRunning() then 75 | IPC.vnavmesh.PathfindAndMoveTo(Npc.position, false) 76 | end 77 | return 78 | end 79 | 80 | if IPC.vnavmesh.PathfindInProgress() or IPC.vnavmesh.IsRunning() then 81 | yield("/vnav stop") 82 | end 83 | 84 | State = CharacterState.playMiniCactpot 85 | end 86 | 87 | TicketsPurchased = false 88 | function PlayMiniCactpot() 89 | -- TODO: replace with mini cactpot name 90 | 91 | if Addons.GetAddon("LotteryDaily").Ready then 92 | yield("/wait 1") 93 | elseif Addons.GetAddon("SelectIconString").Ready then 94 | yield("/callback SelectIconString true 0") 95 | elseif Addons.GetAddon("Talk").Ready then 96 | if not Addons.GetAddon("TextAdvance").Ready then 97 | yield("/click Talk Click") 98 | end 99 | elseif Addons.GetAddon("SelectYesno").Ready then 100 | yield("/callback SelectYesno true 0") 101 | elseif GetDistanceToPoint(Npc.position) > 5 then 102 | IPC.vnavmesh.PathfindAndMoveTo(Npc.x, Npc.y, Npc.z) 103 | elseif IPC.vnavmesh.IsRunning() or IPC.vnavmesh.PathfindInProgress() then 104 | yield("/vnav stop") 105 | elseif TicketsPurchased and not Svc.Condition[CharacterCondition.occupiedShopkeeper] then 106 | State = CharacterState.endState 107 | elseif Svc.Targets.Target == nil or Svc.Targets.Target.Name.TextValue ~= Npc.name then 108 | yield("/target "..Npc.name) 109 | else 110 | yield("/interact") 111 | TicketsPurchased = true 112 | end 113 | end 114 | 115 | function EndState() 116 | if Addons.GetAddon("SelectString").Ready then 117 | yield("/callback SelectString true -1") 118 | else 119 | StopFlag = true 120 | end 121 | end 122 | 123 | CharacterState = 124 | { 125 | ready = Ready, 126 | goToCashier = GoToCashier, 127 | playMiniCactpot = PlayMiniCactpot, 128 | endState = EndState 129 | } 130 | 131 | StopFlag = false 132 | State = CharacterState.ready 133 | yield("/at y") 134 | while not StopFlag do 135 | State() 136 | yield("/wait 0.1") 137 | end 138 | 139 | yield(string.format("/echo %s MiniCactpot script completed successfully..!!", LogPrefix)) 140 | Dalamud.Log(string.format("%s MiniCactpot script completed successfully..!!", LogPrefix)) -------------------------------------------------------------------------------- /SND Legacy/Dailies/PoeticsToSoil.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | ******************************************************************************** 3 | * Dump Poetics - Buy Grade 3 Thanalan Topsoil * 4 | * Version 0.2.1 * 5 | ******************************************************************************** 6 | 7 | Created by: pot0to (https://ko-fi.com/pot0to) 8 | 9 | Description: Checks if you have at least 1800 Allagan Tomestones of Poetics and 10 | dumps them on Grade 3 Thanalan Topsoil. You can later use this soil for 11 | gardening or sell it for a decent price on the marketboard. 12 | 13 | ******************************************************************************** 14 | * Required Plugins * 15 | ******************************************************************************** 16 | 1. vnavmesh 17 | 2. Teleporter 18 | 3. TextAdvance 19 | 20 | ******************************************************************************** 21 | * Code: Don't touch this unless you know what you're doing * 22 | ******************************************************************************** 23 | ]] 24 | 25 | 26 | PoeticsItemId = 28 27 | OreItemId = 13586 28 | IdyllshireTurnIn = 29 | { 30 | x=-12.3, y=211.0, z=-40.85, 31 | price = 150, 32 | oreNpc = "Hismena", 33 | turnInNpc = "Bertana" 34 | } 35 | 36 | function Teleport(aetheryteName) 37 | yield("/tp "..aetheryteName) 38 | while not GetCharacterCondition(CharacterCondition.betweenAreas) do 39 | yield("/wait 0.1") 40 | end 41 | while GetCharacterCondition(CharacterCondition.betweenAreas) do 42 | yield("/wait 0.1") 43 | end 44 | LogInfo("[Poetics Dump - Unidenfiable Ore] Finished Teleport") 45 | end 46 | 47 | function GoToIdyllshireTurnIn() 48 | if not IsInZone(478) then 49 | Teleport("Idyllshire") 50 | elseif GetDistanceToPoint(IdyllshireTurnIn.x, IdyllshireTurnIn.y, IdyllshireTurnIn.z) > 5 then 51 | if not GetCharacterCondition(CharacterCondition.mounted) then 52 | yield('/gaction "mount roulette"') 53 | yield("/wait 1") 54 | elseif not PathfindInProgress() and not PathIsRunning() then 55 | PathfindAndMoveTo(IdyllshireTurnIn.x, IdyllshireTurnIn.y, IdyllshireTurnIn.z) 56 | end 57 | else 58 | State = CharacterState.buyUnidentifiableOre 59 | end 60 | end 61 | 62 | function BuyUnidentifiableOre() 63 | local poetics = GetItemCount(PoeticsItemId) 64 | if poetics < IdyllshireTurnIn.price then 65 | if IsAddonVisible("ShopExchangeCurrency") then 66 | yield("/callback ShopExchangeCurrency true -1") 67 | else 68 | State = CharacterState.turnIn 69 | end 70 | return 71 | end 72 | 73 | GoToIdyllshireTurnIn() 74 | 75 | if GetTargetName() ~= IdyllshireTurnIn.oreNpc then 76 | yield("/target "..IdyllshireTurnIn.oreNpc) 77 | elseif IsAddonVisible("SelectIconString") then 78 | yield("/callback SelectIconString true 6") 79 | elseif IsAddonVisible("SelectYesno") then 80 | yield("/callback SelectYesno true 0") 81 | elseif IsAddonVisible("ShopExchangeCurrency") then 82 | yield("/callback ShopExchangeCurrency true 0 7 "..(poetics//IdyllshireTurnIn.price).." 0") 83 | else 84 | yield("/interact") 85 | end 86 | end 87 | 88 | function TurnIn() 89 | local ore = GetItemCount(OreItemId) 90 | if ore == 0 then 91 | if IsAddonVisible("ShopExchangeItem") then 92 | yield("/callback ShopExchangeItem true -1") 93 | else 94 | StopFlag = true 95 | end 96 | return 97 | end 98 | 99 | GoToIdyllshireTurnIn() 100 | 101 | if GetTargetName() ~= IdyllshireTurnIn.turnInNpc then 102 | yield("/target "..IdyllshireTurnIn.turnInNpc) 103 | elseif IsAddonVisible("SelectIconString") then 104 | yield("/callback SelectIconString true 5") 105 | elseif IsAddonVisible("ShopExchangeItemDialog") then 106 | yield("/callback ShopExchangeItemDialog true 0") 107 | elseif IsAddonVisible("ShopExchangeItem") then 108 | yield("/callback ShopExchangeItem true 0 1 "..ore.." 0") 109 | else 110 | yield("/interact") 111 | end 112 | end 113 | 114 | function Ready() 115 | if GetItemCount(PoeticsItemId) > 1800 or GetItemCount(OreItemId) > 0 then 116 | State = CharacterState.goToIdyllshireTurnIn 117 | else 118 | StopFlag = true 119 | end 120 | end 121 | 122 | CharacterCondition = { 123 | mounted=4, 124 | gathering=6, 125 | inCombat=26, 126 | casting=27, 127 | occupiedInEvent=31, 128 | occupiedInQuestEvent=32, 129 | occupied=33, 130 | boundByDuty=34, 131 | occupiedMateriaExtractionAndRepair=39, 132 | gathering42=42, 133 | fishing=43, 134 | betweenAreas=45, 135 | jumping48=48, 136 | jumpPlatform=61, 137 | betweenAreas51=51, 138 | boundByDuty56=56, 139 | mounting57=57, 140 | mounting64=64, 141 | beingMoved=70, 142 | flying=77 143 | } 144 | 145 | CharacterState = 146 | { 147 | ready = Ready, 148 | goToIdyllshireTurnIn = GoToIdyllshireTurnIn, 149 | buyUnidentifiableOre = BuyUnidentifiableOre, 150 | turnIn = TurnIn 151 | } 152 | 153 | yield("/at y") 154 | State = CharacterState.ready 155 | StopFlag = false 156 | while not StopFlag do 157 | State() 158 | yield("/wait 0.1") 159 | end -------------------------------------------------------------------------------- /SND Legacy/Fate Farming/README.md: -------------------------------------------------------------------------------- 1 | # Fate Farming 2 | Fate farming script with the following features: 3 | - Can purchase Bicolor Gemstone Vouchers (both old and new) when your gemstones are almost capped 4 | - Priority system for Fate selection: most progress > is bonus fate > least time left > distance 5 | - Can prioritize Forlorns when they show up during Fate 6 | - Can do all fates, including NPC collection fates 7 | - Revives upon death and gets back to fate farming 8 | - Attempts to change instances when there are no fates left in the zone 9 | - Can process your retainers and Grand Company turn ins, then get back to fate farming 10 | - Autobuys gysahl greens and grade 8 dark matter when you run out 11 | - Has companion scripts dedicated to atma farming, or you can write your own! (See [section for companion scripts](#companion-scripts)) 12 | 13 | ## New to Something Need Doing (SND) 14 | ![SND Basics](img/SNDBasics.png) 15 | 16 | ## Installing Dependency Plugins 17 | ### Required Plugins 18 | | Plugin Name | Purpose | Repo | 19 | |-------------|---------|------| 20 | | Something Need Doing [Expanded Edition] | main plugin that runs the code | https://puni.sh/api/repository/croizat | 21 | | VNavmesh | pathing and moving | https://puni.sh/api/repository/veyn | 22 | | RotationSolver Reborn OR BossMod Reborn OR Veyn's BossMod OR Wrath Combo | targeting and attacking enemies | https://raw.githubusercontent.com/FFXIV-CombatReborn/CombatRebornRepo/main/pluginmaster.json
https://raw.githubusercontent.com/FFXIV-CombatReborn/CombatRebornRepo/main/pluginmaster.json
https://puni.sh/api/repository/veyn
https://love.puni.sh/ment.json | 23 | | TextAdvance | interacting with Fate NPCs | https://github.com/NightmareXIV/MyDalamudPlugins/raw/main/pluginmaster.json | 24 | | Teleporter | teleporting to aetherytes | comes with Dalamud | 25 | | Lifestream | changing instances | https://raw.githubusercontent.com/NightmareXIV/MyDalamudPlugins/main/pluginmaster.json | 26 | 27 | ### Optional Plugins 28 | | Plugin Name | Purpose | Repo | 29 | |-------------|---------|------| 30 | | BossMod Reborn OR Veyn's BossMod | AI for dodging mechanics | https://raw.githubusercontent.com/FFXIV-CombatReborn/CombatRebornRepo/main/pluginmaster.json
https://puni.sh/api/repository/veyn | 31 | | AutoRetainer | handles retainers when they're ready, then gets back to Fate farming | https://love.puni.sh/ment.json | 32 | | Deliveroo | turns in gear to your Grand Company when your retainers come back with too much and clog your inventory | https://plugins.carvel.li/ | 33 | 34 | ## Settings 35 | ### Script Settings 36 | The script contains several settings you can mess around with to minmax gem income. This section is constantly changing, so check back whenever you update! 37 | ![Script Settings](img/ScriptSettings.png) 38 | 39 | ### RSR Settings 40 | | | | 41 | |--|--| 42 | | ![RSR Engage Settings](img/RSREngageSettings.png) | Select "All Targets that are in range for any abilities (Tanks/Autoduty)" regardless of whether you're a tank | 43 | | ![RSR Map Specific Priorities](img/RSRMapSpecificPriorities.png) | Add "Forlorn Maiden" and "The Forlorn" to Prio Targets | 44 | | ![RSR Gap Closer Distance](img/RSRGapCloserDistance.png) | Recommended for melees: gapcloser distance = 20y | 45 | 46 | ## Companion Scripts 47 | Companion scripts are meant to be used with the base `Fate Farming.lua` script 48 | and are meant to give you more control over different fate farming scenarios. 49 | 50 | Let's take the `Atma Farming.lua` script as an example. 51 | 52 | 1. Set up both `Atma Farming.lua` and `Fate Farming.lua` as macros in your your SND. 53 | 2. Make sure that the `CompanionScriptMode` setting in `Fate Farming.lua` is set to `true`. Optional: You may also with to turn off `WaitIfBonusBuff`. 54 | 3. Make sure the `FateMacro` setting in `Atma Farming.lua` matches whatever you named your fate macro 55 | 4. Hit play on `Atma Farming.lua` 56 | 57 | ## FAQ 58 | ### What's the best zone to farm fates? 59 | Depends on your world and how many people are in each zone. More people in a 60 | zone means the fate mobs have more health. But also more people in a zone means 61 | more people doing the fate, so fates go faster. Popular map options are: 62 | - Heritage Found: Low enough level that you can kill things fast, high enough 63 | level that you don't need to sync 64 | - Kozama'uka: Good aetheryte coverage and no giant wall like Heritage Found 65 | - Shaaloani: If you're ok with babysitting and are interested in the Special 66 | Fate (The SerpentLord Seethes for the capybara mount) or S ranks, though both 67 | will require manual intervention. Because of the Special Fate and S Ranks, this 68 | zone also tends to have a lot of people which can be good or bad depending on 69 | whether those people are doing fates with you or just AFK. 70 | ### What's the best class to use? 71 | Depends on what you have, but popular options are: 72 | - Whatever you have BiS for 73 | - WAR has good survivability and gap close. Great for soloing because you can 74 | pull everything 75 | - WHM holy spam stuns enemies. If you can survive the initial hits before holy 76 | goes off, it may complete fates faster than WAR 77 | - VPR lots of damage, but survivability may be an issue. Set your chocobo to 78 | healer stance 79 | - PCT also lots of damage, but fate bot may frequently move you out of landscape 80 | motif lines 81 | ### Why is my game lagging? Especially during boss fates? 82 | Do you have Pandora installed? Try turning it off completely. 83 | ### Why can't I edit the script after I paste it into SND? 84 | Try pasting to Notepad first, edit it there, then use the "Import from clipboard" 85 | button in SND to paste it in. 86 | ![Import From Clipboard](img/ImportFromClipboard.png) 87 | 88 | ## Discord 89 | https://discord.gg/punishxiv > ffxiv-snd (channel) > pot0to's fate script (thread) -------------------------------------------------------------------------------- /SND Legacy/Jump Puzzles/6 - Dawntrail/5 - Hunu'iliy (Tuliyollal Tower).lua: -------------------------------------------------------------------------------- 1 | JumpNumber = 1 -- where to start 2 | 3 | -- wait=0 for a standing jump 4 | -- wait=0.08 for a running short jump 5 | -- wait=0.1 for a running long jump 6 | -- no wait for no jump 7 | JumpPoints = { 8 | { x=270.23, y=42.43, z=-376.12 }, 9 | { x=269.36, y=43.44, z=-376.01, wait=0 }, 10 | { x=268.4, y=45.0, z=-375.98, wait=0 }, 11 | { x=267.35226, y=45, z=-377.7382 }, -- 4, beginning of jump puzzle 12 | { x=267.35, y=46.71, z=-378.15, wait=0}, 13 | { x=267.34, y=48.43, z=-381.26, wait=0.1 }, 14 | { x=267.38, y=49.95, z=-384.29, wait=0.1 }, 15 | { x=267,00, y=51.66, z=-387.12, wait=0.1 }, 16 | { x=267.16, y=51.66, z=-390.14, wait=0.08 }, 17 | { x=267.17, y=51.66, z=-390.26 }, 18 | { x=267.02, y=53.37, z=-393.00, wait=0.1 }, 19 | { x=265.71, y=54.30, z=-393.12, wait=0 }, -- 12, first ledge 20 | { x=264.78, y=54.30, z=-380.32 }, 21 | { x=264.86, y=55.50, z=-379.61, wait=0 }, 22 | { x=264.68, y=57.10, z=-382.20, wait=0.1 }, 23 | { x=264.74, y=58.80, z=-379.66, wait=0.08 }, 24 | { x=265.08, y=59.72, z=-383.13, wait=0.1 }, -- 17, wooden platform 25 | { x=265.99, y=59.73, z=-383.1 }, 26 | { x=266.22, y=59.73, z=-384.70 }, 27 | { x=267.57, y=61.00, z=-386.60, wait=0.08 }, 28 | { x=267.88, y=60.99, z=-386.36 }, 29 | { x=267.15, y=62.50, z=-388.92, wait=0.08 }, 30 | { x=266.10, y=63.85, z=-392.89, wait=0.1 }, 31 | { x=265.98, y=63.85, z=-394.98 }, 32 | { x=266.07, y=65.42, z=-397.68, wait=0.1 }, 33 | { x=264.94, y=67.20, z=-400.58, wait=0.1 }, 34 | { x=265.67, y=67.20, z=-401.16 }, 35 | { x=261.56, y=67.18, z=-401.39, wait=0.08 }, 36 | { x=261.39, y=67.18, z=-401.39 }, 37 | { x=257.85, y=68.39, z=-401.48, wait=0.1 }, 38 | { x=257.72, y=69.47, z=-399.87, wait=0.08 }, -- 31, second ledge 39 | { x=263.72, y=69.47, z=-399.47 }, 40 | { x=263.33, y=69.47, z=-388.31 }, 41 | { x=261.44, y=70.94, z=-388.12, wait=0 }, 42 | { x=262.32, y=70.94, z=-385.76 }, 43 | { x=262.78, y=72.46, z=-384.46, wait=0 }, 44 | { x=262.61, y=74.01, z=-382.58, wait=0.08 }, 45 | { x=262.75, y=75.59, z=-384.71, wait=0.08 }, 46 | { x=262.62, y=77.18, z=-382.51, wait=0.08 }, 47 | { x=262.78, y=78.77, z=-384.70, wait=0.08 }, 48 | { x=263.05, y=80.49, z=-388.04, wait=0.1 }, -- 41, wooden platform 49 | { x=263.02, y=80.49, z=-389.04 }, 50 | { x=260.92, y=82.25, z=-389.25, wait=0.08 }, 51 | { x=262.02, y=83.75, z=-386.71, wait=0.08 }, 52 | { x=260.95, y=85.25, z=-389.16, wait=0.08 }, 53 | { x=261.43, y=86.72, z=-391.51, wait=0.08 }, 54 | { x=263.18, y=88.25, z=-389.18, wait=0.08 }, 55 | { x=262.39, y=89.62, z=-392.74, wait=0.1 }, -- 48, top of pillar 56 | { x=261.82, y=89.62, z=-394.66 }, 57 | { x=261.69, y=91.17, z=-395.34, wait=0 }, 58 | { x=261.89, y=92.67, z=-393.13, wait=0.08 }, 59 | { x=262.96, y=94.17, z=-395.23, wait=0.1 }, 60 | { x=263.0, y=94.17, z=-395.06 }, 61 | { x=261.91, y=95.67, z=-393.01, wait=0.08 }, 62 | { x=263.12, y=97.17, z=-395.33, wait=0.08 }, 63 | { x=260.77, y=98.88, z=-395.47, wait=0.08 }, -- 56, ledge 64 | { x=260.61, y=98.88, z=-392.94 }, 65 | { x=260.58, y=98.88, z=-387.28, wait=0.2 }, -- 58, jump over skinny platform entirely bc wide routes are safer 66 | { x=260.73, y=100.44, z=-386.35, wait=0 }, 67 | { x=260.81, y=102.02, z=-383.72, wait=0.08 }, 68 | { x=261.38, y=103.52, z=-386.15, wait=0.08 }, 69 | { x=260.94, y=105.02, z=-383.52, wait=0.08 }, 70 | { x=261.27, y=106.52, z=-386.47, wait=0.08 }, 71 | { x=261.86, y=107.93, z=-388.47, wait=0.08 }, -- 64, wooden platform 72 | { x=261.14, y=109.52, z=-386.19, wait=0.08 }, 73 | { x=260.85, y=111.02, z=-383.81, wait=0.08 }, 74 | { x=261.29, y=112.52, z=-386.00, wait=0.08 }, 75 | { x=261.07, y=114.02, z=-383.70, wait=0.08 }, 76 | { x=261.08, y=114.67, z=-387.83, wait=0.1 }, -- 69, wooden platform 77 | { x=259.23, y=115.64, z=-385.93, wait=0.08 }, 78 | { x=258.92, y=115.64, z=-384.63 }, 79 | { x=260.62, y=116.85, z=-383.23, wait=0.08 }, 80 | { x=259.54, y=118.62, z=-381.82, wait=0.08 }, 81 | { x=261.17, y=120.39, z=-382.38, wait=0.08 }, 82 | { x=259.81, y=122.15, z=-381.66, wait=0.08 }, 83 | { x=260.68, y=123.92, z=-383.02, wait=0.08 }, 84 | { x=260.49, y=124.56, z=-386.01, wait=0.08 }, 85 | { x=260.38, y=125.4, z=-388.32, wait=0.08 }, -- 78, wooden platform 86 | { x=258.12, y=126.32, z=-386.61, wait=0.1 }, -- 79, base of 4 pillars + center column 87 | { x=258.56, y=126.32, z=-387.90 }, 88 | { x=259.77, y=127.94, z=-385.39, wait=0.08 }, 89 | { x=259.29, y=129.44, z=-387.91, wait=0.1 }, 90 | { x=259.8, y=130.94, z=-385.46, wait=0.08 }, 91 | { x=259.54, y=132.44, z=-387.91, wait=0.08 }, 92 | { x=260.08, y=133.94, z=-385.45, wait=0.08 }, 93 | { x=260.83, y=135.44, z=-387.72, wait=0.08 }, -- 86, wooden platform 94 | { x=261.39, y=136.94, z=-385.6, wait=0.08 }, 95 | { x=260.97, y=138.44, z=-387.69, wait=0.08 }, -- 88, wooden platform 96 | { x=260.20, y=139.61, z=-390.68, wait=0.08 }, -- 89, on railing 97 | { x=258.93, y=141.31, z=-389.49, wait=0 }, 98 | { x=259.04, y=143.02, z=-391.6, wait=0.08 }, 99 | { x=257.28, y=144.21, z=-390.92, wait=0.1 } 100 | } 101 | 102 | function Jump() 103 | local jumpData = JumpPoints[JumpNumber] 104 | PathMoveTo(jumpData.x, jumpData.y, jumpData.z) 105 | if jumpData.wait ~=nil then 106 | yield("/wait "..jumpData.wait) 107 | yield("/gaction jump") 108 | end 109 | repeat 110 | yield("/wait 0.1") 111 | until not PathIsRunning() 112 | yield("/wait 0.5") 113 | JumpNumber = JumpNumber + 1 114 | end 115 | 116 | while JumpNumber <= #JumpPoints do 117 | Jump() 118 | end -------------------------------------------------------------------------------- /SND Legacy/Fate Farming/Companion Scripts/Occult Demiatmas.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | 3 | ******************************************************************************** 4 | * Occult Demiatma Farming * 5 | * Version 1.0.4 * 6 | ******************************************************************************** 7 | 8 | Atma farming script meant to be used with `Fate Farming.lua`. This will go down 9 | the list of atma farming zones and farm fates until you have 12 of the required 10 | atmas in your inventory, then teleport to the next zone and restart the fate 11 | farming script. 12 | 13 | Created by: pot0to (https://ko-fi.com/pot0to) 14 | 15 | -> 1.0.4 Added more logging 16 | -> 1.0.3 Moved the wait message before the wait time, fix a looping bug 17 | Added a 10s wait if you go through all zones without a FATE, 18 | meant to prevent you from burning gil on teleports 19 | -> 1.0.1 Added ability to move to next zone if no eligible fates 20 | -> 1.0.0 First release 21 | 22 | --#region Settings 23 | 24 | --[[ 25 | ******************************************************************************** 26 | * Settings * 27 | ******************************************************************************** 28 | ]] 29 | 30 | FateMacro = "Fate Farming" 31 | NumberToFarm = 3 -- How many of each atma to farm 32 | WaitTimeBeforeLooping = 10 -- If there are no active fates in any of your areas, wait X seconds before looping through them again 33 | 34 | --#endregion Settings 35 | 36 | ------------------------------------------------------------------------------------------------------------------------------------------------------ 37 | 38 | --[[ 39 | ************************************************************** 40 | * Code: Don't touch this unless you know what you're doing * 41 | ************************************************************** 42 | ]] 43 | Atmas = 44 | { 45 | { zoneName = "Urqopacha", zoneId = 1187, itemName="Azurite Demiatma", itemId=47744 }, 46 | --{ zoneName = "Kozama'uka", zoneId = 1188, itemName="Verdigris Demiatma", itemId=47745 }, 47 | --{ zoneName = "Yak T'el", zoneId = 1189, itemName="Malachite Demiatma", itemId=47746 }, 48 | --{ zoneName = "Shaaloani", zoneId = 1190, itemName="Realgar Demiatma", itemId=47747 }, 49 | --{ zoneName = "Heritage Found", zoneId = 1191, itemName="Caput Mortuum Demiatma", itemId=47748 }, 50 | --{ zoneName = "Living Memory", zoneId = 1192, itemName="Orpiment Demiatma", itemId=47749 } 51 | } 52 | 53 | CharacterCondition = { 54 | casting=27, 55 | betweenAreas=45 56 | } 57 | 58 | FarmingZoneIndex = 1 59 | FullPass = true 60 | DidFateOnPass = false 61 | function GetNextAtmaTable() 62 | -- ffwd to next zone index, or end of list 63 | while FarmingZoneIndex <= #Atmas and GetItemCount(Atmas[FarmingZoneIndex].itemId) >= NumberToFarm do 64 | FarmingZoneIndex = FarmingZoneIndex + 1 65 | end 66 | 67 | if FarmingZoneIndex <= #Atmas then 68 | FullPass = false 69 | return Atmas[FarmingZoneIndex] 70 | elseif FullPass then 71 | LogInfo("[DemiatmaFarmer] Did fullpass, returning nil") 72 | return nil 73 | else 74 | if not DidFateOnPass then 75 | yield("/echo Went through all zones without a FATE. Waiting "..WaitTimeBeforeLooping.." seconds before going through the zones again.") 76 | yield("/wait "..WaitTimeBeforeLooping) 77 | end 78 | FarmingZoneIndex = (FarmingZoneIndex % #Atmas) + 1 79 | FullPass = true 80 | DidFateOnPass = false 81 | return GetNextAtmaTable() --second run it either finds something, or 82 | --hits the end with FullPass-true 83 | end 84 | end 85 | 86 | function TeleportTo(aetheryteName) 87 | yield("/tp "..aetheryteName) 88 | yield("/wait 1") -- wait for casting to begin 89 | while GetCharacterCondition(CharacterCondition.casting) do 90 | LogInfo("[FATE] Casting teleport...") 91 | yield("/wait 1") 92 | end 93 | yield("/wait 1") -- wait for that microsecond in between the cast finishing and the transition beginning 94 | while GetCharacterCondition(CharacterCondition.betweenAreas) do 95 | LogInfo("[FATE] Teleporting...") 96 | yield("/wait 1") 97 | end 98 | yield("/wait 1") 99 | end 100 | 101 | yield("/at y") 102 | OldBicolorGemCount = GetItemCount(26807) 103 | NextAtmaTable = GetNextAtmaTable() 104 | while NextAtmaTable ~= nil do 105 | if not IsPlayerOccupied() and not IsMacroRunningOrQueued(FateMacro) then 106 | if GetItemCount(NextAtmaTable.itemId) >= NumberToFarm then 107 | NextAtmaTable = GetNextAtmaTable() 108 | elseif not IsInZone(NextAtmaTable.zoneId) then 109 | TeleportTo(GetAetheryteName(GetAetherytesInZone(NextAtmaTable.zoneId)[0])) 110 | else 111 | yield("/snd run "..FateMacro) 112 | 113 | repeat 114 | yield("/wait 1") 115 | until not IsMacroRunningOrQueued(FateMacro) 116 | LogInfo("[DemiatmaFarmer] FateMacro has stopped") 117 | NewBicolorGemCount = GetItemCount(26807) 118 | -- yield("/echo Bicolor Count: "..NewBicolorGemCount) 119 | if NewBicolorGemCount == OldBicolorGemCount then 120 | LogInfo("[DemiatmaFarmer] FateMacro exited without doing any fates.") 121 | FarmingZoneIndex = FarmingZoneIndex + 1 122 | NextAtmaTable = GetNextAtmaTable() 123 | else 124 | LogInfo("[DemiatmaFarmer] FateMacro did a fate.") 125 | DidFateOnPass = true 126 | OldBicolorGemCount = NewBicolorGemCount 127 | end 128 | end 129 | end 130 | yield("/wait 1") 131 | end 132 | LogInfo("[DemiatmaFarmer] NextAtmaTable was nil") -------------------------------------------------------------------------------- /Gold Saucer/Jumbo Cactpot.lua: -------------------------------------------------------------------------------- 1 | --[[SND Metadata]] 2 | author: pot0to 3 | version: 2.0.1 4 | description: Teleports to Gold Saucer, picks up last week's cactpot prizes (if you had any), and purchases 3 new tickets using random numbers.\nhttps://ko-fi.com/pot0to 5 | plugin_dependencies: vnavmesh, TextAdvance, Lifestream 6 | --[[End Metadata]] 7 | --[[ 8 | 9 | ******************************************************************************** 10 | * * 11 | * Jumbo Cactpot * 12 | * * 13 | ******************************************************************************** 14 | 15 | Created by: pot0to (https://ko-fi.com/pot0to) 16 | Description: Teleports to Gold Saucer, picks up last week's cactpot prizes (if 17 | you had any), and purchases 3 new tickets using random numbers. 18 | 19 | ******************************************************************************** 20 | * Required Plugins * 21 | ******************************************************************************** 22 | 23 | 1. Lifestream 24 | 2. TextAdvance 25 | 3. Vnavmesh 26 | 27 | ******************************************************************************** 28 | * Code: Don't touch this unless you know what you're doing * 29 | ******************************************************************************** 30 | ]] 31 | 32 | import("System.Numerics") 33 | 34 | CharacterCondition = 35 | { 36 | casting=27, 37 | occupiedShopkeeper = 32, 38 | betweenAreas=45 39 | } 40 | 41 | function Teleport(aetheryteName) 42 | yield("/li tp "..aetheryteName) 43 | yield("/wait 1") 44 | while Svc.Condition[CharacterCondition.casting] do 45 | yield("/wait 0.1") 46 | end 47 | yield("/wait 1") 48 | while Svc.Condition[CharacterCondition.betweenAreas] do 49 | yield("/wait 0.1") 50 | end 51 | end 52 | 53 | function GetDistanceToPoint(vec3) 54 | local px = Svc.ClientState.LocalPlayer.Position.X 55 | local py = Svc.ClientState.LocalPlayer.Position.Y 56 | local pz = Svc.ClientState.LocalPlayer.Position.Z 57 | local distance = math.sqrt((vec3.X - px)^2 + (vec3.Y-py)^2 + (vec3.Z-pz)^2) 58 | return distance 59 | end 60 | 61 | function Start() 62 | if IPC.Lifestream.IsBusy() then 63 | return 64 | end 65 | 66 | if Svc.ClientState.TerritoryType ~= 144 then 67 | Teleport("Gold Saucer") 68 | return 69 | end 70 | 71 | yield("/target Aetheryte") 72 | 73 | if Svc.Targets.Target == nil or 74 | Svc.Targets.Target.Name.TextValue ~= "aetheryte" or 75 | GetDistanceToPoint(Svc.Targets.Target.Position) > 7 76 | then 77 | IPC.vnavmesh.PathfindAndMoveTo(Vector3(-4.82, 1.04, 2.21), false) 78 | elseif GetDistanceToPoint(Svc.Targets.Target.Position) <= 7 then 79 | yield("/echo close") 80 | yield("/vnav stop") 81 | yield("/li Cactpot Board") 82 | State = CharacterState.claimPrize 83 | end 84 | end 85 | 86 | RewardClaimed = false 87 | function ClaimPrize() 88 | yield("/target Cactpot Cashier") 89 | 90 | if Addons.GetAddon("LotteryWeeklyRewardList").Ready then 91 | yield("/callback LotteryWeeklyRewardList true -1") 92 | elseif Addons.GetAddon("SelectYesno").Ready then 93 | yield("/callback SelectYesno true 0") 94 | elseif RewardClaimed and not Svc.Condition[CharacterCondition.occupiedShopkeeper] then 95 | State = CharacterState.purchaseNewTickets 96 | elseif Svc.Targets.Target == nil or 97 | Svc.Targets.Target.Name.TextValue ~= "Cactpot Cashier" or 98 | GetDistanceToPoint(Svc.Targets.Target.Position) > 7 99 | then 100 | IPC.vnavmesh.PathfindAndMoveTo(Vector3(123.25, 13.00, -19.35), false) 101 | elseif GetDistanceToPoint(Svc.Targets.Target.Position) <= 7 then 102 | yield("/vnav stop") 103 | yield("/interact") 104 | RewardClaimed = true 105 | end 106 | end 107 | 108 | TicketsPurchased = false 109 | function PurchaseNewTickets() 110 | yield("/target Jumbo Cactpot Broker") 111 | 112 | if Addons.GetAddon("LotteryWeeklyRewardList").Ready then 113 | yield("/echo You have already purchased tickets this week!") 114 | yield("/callback LotteryWeeklyRewardList true -1") 115 | State = CharacterState.endState 116 | elseif Addons.GetAddon("SelectString").Ready then 117 | yield("/callback SelectString true 0") 118 | elseif Addons.GetAddon("SelectYesno").Ready then 119 | yield("/callback SelectYesno true 0") 120 | elseif Addons.GetAddon("LotteryWeeklyInput").Ready then 121 | yield("/wait 1") 122 | yield("/callback LotteryWeeklyInput true "..math.random(9999)) 123 | elseif TicketsPurchased and not Svc.Condition[CharacterCondition.occupiedShopkeeper] then 124 | State = CharacterState.endState 125 | elseif Svc.Targets.Target == nil or 126 | Svc.Targets.Target.Name.TextValue ~= "Jumbo Cactpot Broker" or 127 | GetDistanceToPoint(Svc.Targets.Target.Position) > 7 128 | then 129 | IPC.vnavmesh.PathfindAndMoveTo(Vector3(120.26, 13.00, -10.9), false) 130 | elseif GetDistanceToPoint(Svc.Targets.Target.Position) <= 7 then 131 | yield("/vnav stop") 132 | yield("/interact") 133 | TicketsPurchased = true 134 | end 135 | 136 | end 137 | 138 | function EndState() 139 | if Addons.GetAddon("SelectString").Ready then 140 | yield("/callback SelectString true -1") 141 | else 142 | StopFlag = true 143 | end 144 | end 145 | 146 | CharacterState = 147 | { 148 | start = Start, 149 | claimPrize = ClaimPrize, 150 | purchaseNewTickets = PurchaseNewTickets, 151 | endState = EndState 152 | } 153 | 154 | StopFlag = false 155 | State = CharacterState.start 156 | yield("/at y") 157 | while not StopFlag do 158 | State() 159 | yield("/wait 0.1") 160 | end -------------------------------------------------------------------------------- /Jump Puzzles/6 - Dawntrail/Sightseeing Log 5 - Hunu'iliy (Tuliyollal Tower).lua: -------------------------------------------------------------------------------- 1 | --[=====[ 2 | [[SND Metadata]] 3 | author: pot0to 4 | version: 2.0.0 5 | description: | 6 | Support via https://ko-fi.com/pot0to 7 | Tulliyolal Tower jump puzzle and sightseeing log: https://youtu.be/paXx-tiXkh0?t=118 8 | (Not the palace! There's no sightseeing jump puzzle at the palace!) 9 | plugin_dependencies: 10 | - vnavmesh 11 | configs: 12 | Starting Jump Number: 13 | description: Start with step 1, but if you fall due to server tick issues, 14 | you can use this to restart the jump puzzle from any step. See the 15 | "Jump Points" list 16 | default: 1 17 | [[End Metadata]] 18 | --]=====] 19 | 20 | -- wait=0 for a standing jump 21 | -- wait=0.08 for a running short jump 22 | -- wait=0.1 for a running long jump 23 | -- no wait for no jump 24 | JumpPoints = { 25 | { x=270.23, y=42.43, z=-376.12 }, 26 | { x=269.36, y=43.44, z=-376.01, wait=0 }, 27 | { x=268.4, y=45.0, z=-375.98, wait=0 }, 28 | { x=267.35226, y=45, z=-377.7382 }, -- 4, beginning of jump puzzle 29 | { x=267.35, y=46.71, z=-378.15, wait=0}, 30 | { x=267.34, y=48.43, z=-381.26, wait=0.1 }, 31 | { x=267.38, y=49.95, z=-384.29, wait=0.1 }, 32 | { x=267,00, y=51.66, z=-387.12, wait=0.1 }, 33 | { x=267.16, y=51.66, z=-390.14, wait=0.08 }, 34 | { x=267.17, y=51.66, z=-390.26 }, 35 | { x=267.02, y=53.37, z=-393.00, wait=0.1 }, 36 | { x=265.71, y=54.30, z=-393.12, wait=0 }, -- 12, first ledge 37 | { x=264.78, y=54.30, z=-380.32 }, 38 | { x=264.86, y=55.50, z=-379.61, wait=0 }, 39 | { x=264.68, y=57.10, z=-382.20, wait=0.1 }, 40 | { x=264.74, y=58.80, z=-379.66, wait=0.08 }, 41 | { x=265.08, y=59.72, z=-383.13, wait=0.1 }, -- 17, wooden platform 42 | { x=265.99, y=59.73, z=-383.1 }, 43 | { x=266.22, y=59.73, z=-384.70 }, 44 | { x=267.57, y=61.00, z=-386.60, wait=0.08 }, 45 | { x=267.88, y=60.99, z=-386.36 }, 46 | { x=267.15, y=62.50, z=-388.92, wait=0.08 }, 47 | { x=266.10, y=63.85, z=-392.89, wait=0.1 }, 48 | { x=265.98, y=63.85, z=-394.98 }, 49 | { x=266.07, y=65.42, z=-397.68, wait=0.1 }, 50 | { x=264.94, y=67.20, z=-400.58, wait=0.1 }, 51 | { x=265.67, y=67.20, z=-401.16 }, 52 | { x=261.56, y=67.18, z=-401.39, wait=0.08 }, 53 | { x=261.39, y=67.18, z=-401.39 }, 54 | { x=257.85, y=68.39, z=-401.48, wait=0.1 }, 55 | { x=257.72, y=69.47, z=-399.87, wait=0.08 }, -- 31, second ledge 56 | { x=263.72, y=69.47, z=-399.47 }, 57 | { x=263.33, y=69.47, z=-388.31 }, 58 | { x=261.44, y=70.94, z=-388.12, wait=0 }, 59 | { x=262.32, y=70.94, z=-385.76 }, 60 | { x=262.78, y=72.46, z=-384.46, wait=0 }, 61 | { x=262.61, y=74.01, z=-382.58, wait=0.08 }, 62 | { x=262.75, y=75.59, z=-384.71, wait=0.08 }, 63 | { x=262.62, y=77.18, z=-382.51, wait=0.08 }, 64 | { x=262.78, y=78.77, z=-384.70, wait=0.08 }, 65 | { x=263.05, y=80.49, z=-388.04, wait=0.1 }, -- 41, wooden platform 66 | { x=263.02, y=80.49, z=-389.04 }, 67 | { x=260.92, y=82.25, z=-389.25, wait=0.08 }, 68 | { x=262.02, y=83.75, z=-386.71, wait=0.08 }, 69 | { x=260.95, y=85.25, z=-389.16, wait=0.08 }, 70 | { x=261.43, y=86.72, z=-391.51, wait=0.08 }, 71 | { x=263.18, y=88.25, z=-389.18, wait=0.08 }, 72 | { x=262.39, y=89.62, z=-392.74, wait=0.1 }, -- 48, top of pillar 73 | { x=261.82, y=89.62, z=-394.66 }, 74 | { x=261.69, y=91.17, z=-395.34, wait=0 }, 75 | { x=261.89, y=92.67, z=-393.13, wait=0.08 }, 76 | { x=262.96, y=94.17, z=-395.23, wait=0.1 }, 77 | { x=263.0, y=94.17, z=-395.06 }, 78 | { x=261.91, y=95.67, z=-393.01, wait=0.08 }, 79 | { x=263.12, y=97.17, z=-395.33, wait=0.08 }, 80 | { x=260.77, y=98.88, z=-395.47, wait=0.08 }, -- 56, ledge 81 | { x=260.61, y=98.88, z=-392.94 }, 82 | { x=260.58, y=98.88, z=-387.28, wait=0.2 }, -- 58, jump over skinny platform entirely bc wide routes are safer 83 | { x=260.73, y=100.44, z=-386.35, wait=0 }, 84 | { x=260.81, y=102.02, z=-383.72, wait=0.08 }, 85 | { x=261.38, y=103.52, z=-386.15, wait=0.08 }, 86 | { x=260.94, y=105.02, z=-383.52, wait=0.08 }, 87 | { x=261.27, y=106.52, z=-386.47, wait=0.08 }, 88 | { x=261.86, y=107.93, z=-388.47, wait=0.08 }, -- 64, wooden platform 89 | { x=261.14, y=109.52, z=-386.19, wait=0.08 }, 90 | { x=260.85, y=111.02, z=-383.81, wait=0.08 }, 91 | { x=261.29, y=112.52, z=-386.00, wait=0.08 }, 92 | { x=261.07, y=114.02, z=-383.70, wait=0.08 }, 93 | { x=261.08, y=114.67, z=-387.83, wait=0.1 }, -- 69, wooden platform 94 | { x=259.23, y=115.64, z=-385.93, wait=0.08 }, 95 | { x=258.92, y=115.64, z=-384.63 }, 96 | { x=260.62, y=116.85, z=-383.23, wait=0.08 }, 97 | { x=259.54, y=118.62, z=-381.82, wait=0.08 }, 98 | { x=261.17, y=120.39, z=-382.38, wait=0.08 }, 99 | { x=259.81, y=122.15, z=-381.66, wait=0.08 }, 100 | { x=260.68, y=123.92, z=-383.02, wait=0.08 }, 101 | { x=260.49, y=124.56, z=-386.01, wait=0.08 }, 102 | { x=260.38, y=125.4, z=-388.32, wait=0.08 }, -- 78, wooden platform 103 | { x=258.12, y=126.32, z=-386.61, wait=0.1 }, -- 79, base of 4 pillars + center column 104 | { x=258.56, y=126.32, z=-387.90 }, 105 | { x=259.77, y=127.94, z=-385.39, wait=0.08 }, 106 | { x=259.29, y=129.44, z=-387.91, wait=0.1 }, 107 | { x=259.8, y=130.94, z=-385.46, wait=0.08 }, 108 | { x=259.54, y=132.44, z=-387.91, wait=0.08 }, 109 | { x=260.08, y=133.94, z=-385.45, wait=0.08 }, 110 | { x=260.83, y=135.44, z=-387.72, wait=0.08 }, -- 86, wooden platform 111 | { x=261.39, y=136.94, z=-385.6, wait=0.08 }, 112 | { x=260.97, y=138.44, z=-387.69, wait=0.08 }, -- 88, wooden platform 113 | { x=260.20, y=139.61, z=-390.68, wait=0.08 }, -- 89, on railing 114 | { x=258.93, y=141.31, z=-389.49, wait=0 }, 115 | { x=259.04, y=143.02, z=-391.6, wait=0.08 }, 116 | { x=257.28, y=144.21, z=-390.92, wait=0.1 } 117 | } 118 | 119 | import ("System") 120 | import("System.Numerics") 121 | GenericListType = Type.GetType("System.Collections.Generic.List`1[System.Numerics.Vector3]") 122 | 123 | function Jump() 124 | local jumpData = JumpPoints[JumpNumber] 125 | if jumpData.sprint then 126 | yield("/generalaction sprint") 127 | yield("/wait 1") 128 | end 129 | 130 | local vectorList = Activator.CreateInstance(GenericListType) 131 | vectorList:Add(Vector3(jumpData.x, jumpData.y, jumpData.z)) 132 | IPC.vnavmesh.MoveTo(vectorList, false) 133 | if jumpData.wait ~= nil then 134 | yield("/wait "..jumpData.wait) 135 | yield("/gaction jump") 136 | end 137 | repeat 138 | yield("/wait 0.1") 139 | until not IPC.vnavmesh.IsRunning() 140 | yield("/wait 0.5") 141 | JumpNumber = JumpNumber + 1 142 | end 143 | 144 | JumpNumber = Config.Get("Starting Jump Number") 145 | while JumpNumber <= #JumpPoints do 146 | Jump() 147 | end -------------------------------------------------------------------------------- /Jump Puzzles/3 - Stormblood/Sightseeing Log 26 - Shiokaze Hostelry (Kugane Tower).lua: -------------------------------------------------------------------------------- 1 | --[=====[ 2 | [[SND Metadata]] 3 | author: pot0to 4 | version: 2.0.0 5 | description: | 6 | Support via https://ko-fi.com/pot0to 7 | Kugane Tower jump puzzle and sightseeing log: https://youtu.be/paXx-tiXkh0?t=118 8 | (Not the palace! There's no sightseeing jump puzzle at the palace!) 9 | plugin_dependencies: 10 | - vnavmesh 11 | configs: 12 | Starting Jump Number: 13 | description: Start with step 1, but if you fall due to server tick issues, 14 | you can use this to restart the jump puzzle from any step. See the 15 | "Jump Points" list 16 | default: 1 17 | [[End Metadata]] 18 | --]=====] 19 | 20 | import("System") 21 | import("System.Numerics") 22 | GenericListType = Type.GetType("System.Collections.Generic.List`1[System.Numerics.Vector3]") 23 | 24 | -- wait=0 for a standing jump 25 | -- wait=0.08 for a running short jump 26 | -- wait=0.1 for a running long jump 27 | -- no wait for no jump 28 | JumpPoints = { 29 | { position=Vector3(-41.07, 15.49, -37.5), wait=0.08 }, -- 1, jump on railing 30 | { position=Vector3(-40.89, 15.52, -35.79) }, -- 2, adjust on railing 31 | { position=Vector3(-39.36, 17.2, -38.42), wait=0.05 }, -- 3, jump on peg 32 | { position=Vector3(-39.3, 17.2, -37.9) }, 33 | { position=Vector3(-36.97, 17.41, -39.1), wait=0.00 }, 34 | { position=Vector3(-36.92, 17.41, -39.15) }, 35 | { position=Vector3(-33.76, 19.21, -38.91), wait=0.08 }, 36 | { position=Vector3(-30.42, 20.91, -38.71), wait=0.08 }, 37 | { position=Vector3(-32.01, 22.85, -40.35), wait=0.1}, -- 9, green roof 38 | 39 | { position=Vector3(-28.05, 23.63, -45.98) }, 40 | { position=Vector3(-27.65, 24.18, -70.36) }, 41 | { position=Vector3(-38.29, 24.09, -80.26) }, 42 | { position=Vector3(-41.47, 25.55, -78.20) }, 43 | { position=Vector3(-43.11, 26.60, -78.66), wait=0.08 }, -- 14, edge of balcony 44 | { position=Vector3(-44.11, 28.10, -78.84), wait=0.08 }, -- 15, railing 45 | { position=Vector3(-50.62, 26.60, -79.85) }, 46 | { position=Vector3(-52.48, 28.30, -81.71), wait=0.00 }, -- 17, post 47 | { position=Vector3(-52.18, 28.3, -81.52) }, 48 | { position=Vector3(-53.99, 30.0, -82.9), wait=0.00 }, -- 19, peg 49 | { position=Vector3(-54.31, 31.76, -80.30), wait=0.08 }, -- 20, roof 50 | 51 | { position=Vector3(-45.89, 40.81, -70.41) }, 52 | { position=Vector3(-46.56, 42.11, -70.26), wait=0.00 }, -- 22, peg 1 53 | { position=Vector3(-46.41, 42.11, -70.47) }, 54 | { position=Vector3(-49.59, 43.81, -70.29), wait=0.08 }, -- 24, peg 2 55 | { position=Vector3(-49.44, 43.8, -70.45) }, 56 | { position=Vector3(-52.57, 45.31, -70.33), wait=0.05 }, -- 26, peg 3 57 | { position=Vector3(-49.62, 47.11, -70.24), wait=0.08 }, -- 27, peg 4 58 | { position=Vector3(-49.14, 47.11, -70.67) }, 59 | { position=Vector3(-46.39, 48.91, -70.69), wait=0.08 }, -- 29, 2nd to last jump before 3rd roof 60 | { position=Vector3(-46.00, 48.91, -71.08) }, 61 | { position=Vector3(-49.02, 50.44, -70.56), wait=0.08 }, -- 31, jump to roof 62 | 63 | { position=Vector3(-53.22, 52.1, -66.66) }, 64 | { position=Vector3(-53.89, 53.68, -65.98), wait=0.00 }, -- 33 65 | { position=Vector3(-55.72, 54.51, -66.72), wait=0.00 }, 66 | { position=Vector3(-55.64, 53.44, -65.25) }, 67 | { position=Vector3(-56.31, 54.82, -63.22), wait=0.08 }, 68 | { position=Vector3(-57.34, 54.78, -62.79) }, 69 | { position=Vector3(-57.14, 54.95, -58.82) }, 70 | { position=Vector3(-55.81, 56.47, -58.96) }, 71 | { position=Vector3(-54.50, 57.74, -58.44), wait=0.08 }, -- 40 jump onto wood area 72 | { position=Vector3(-54.48, 57.73, -56.56) }, 73 | { position=Vector3(-55.06, 59.53, -55.71), wait=0.00 }, -- 42, peg 1 74 | { position=Vector3(-54.74, 61.31, -58.41), wait=0.00 }, -- 43, peg 2 75 | { position=Vector3(-54.46, 62.75, -56.34), wait=0.08 }, -- 44, flat board 76 | { position=Vector3(-54.48, 62.75, -56.67) }, 77 | { position=Vector3(-55.01, 64.31, -59.55), wait=0.08 }, -- 46, jump to circle 78 | { position=Vector3(-55.05, 65.94, -62.18), wait=0.08 }, -- 47, jump above the circle 79 | { position=Vector3(-54.32, 68.48, -64.66) }, 80 | { position=Vector3(-52.49, 67.19, -65.71) }, 81 | { position=Vector3(-49.14, 68.41, -65.81), wait=0.08 }, -- 50, peg 1 82 | { position=Vector3(-46.84, 70.21, -65.81), wait=0.00 }, -- 51, peg 2 83 | { position=Vector3(-44.77, 72.01, -65.78), wait=0.00 }, -- 52, peg 3 84 | { position=Vector3(-49.23, 73.51, -65.64), wait=0.08 }, -- 53, peg 4 85 | { position=Vector3(-50.92, 75.11, -66.13), wait=0.00 }, -- 54, peg 5 86 | { position=Vector3(-47.11, 76.41, -65.88), wait=0.08 }, -- 55, peg 6 87 | { position=Vector3(-45.46, 77.25, -65.47), wait=0.00 }, -- 56, corner 88 | 89 | { position=Vector3(-41.58, 79.05, -65.55), wait=0.08 }, -- 57, peg 1 90 | { position=Vector3(-41.07, 79.05, -65.93) }, -- 58, repositioning 91 | { position=Vector3(-39.84, 80.85, -63.60), wait=0.08 }, -- 59, peg 2 92 | { position=Vector3(-41.53, 82.24, -61.86), wait=0.08 }, -- 60, right side of flag 93 | { position=Vector3(-41.54, 82.25, -56.47), wait=0.08 }, -- 61, left side of flag 94 | 95 | { position=Vector3(-40.99, 83.75, -55.39), wait=0.00 }, -- 62, peg 1 96 | { position=Vector3(-40.4, 83.75, -55.31) }, -- 63, reposition 97 | { position=Vector3(-39.12, 85.55, -51.90), wait=0.1 }, -- 64, peg 2 98 | { position=Vector3(-40.05, 87.35, -54.45), wait=0.08 }, -- 65, peg 3 99 | { position=Vector3(-40.35, 88.49, -54.42), wait=0.00 }, -- 66, jumping to ledge 100 | { position=Vector3(-39.96, 89.65, -52.00), wait=0.08 }, -- 67, peg 4 101 | { position=Vector3(-39.49, 89.65, -52.34) }, 102 | { position=Vector3(-40.81, 90.89, -51.97), wait=0.00 }, -- 69, outer Ledge 103 | { position=Vector3(-42.18, 89.16, -53.73) }, -- 70, going down to lower edge 104 | { position=Vector3(-41.64, 89.15, -65.36) }, -- 71, walk across 105 | { position=Vector3(-46.15, 89.15, -65.34) }, -- 72, turn the corner 106 | { position=Vector3(-48.28, 90.88, -66.2), wait=0.00 }, -- 73, jumping up 107 | { position=Vector3(-44.86, 90.89, -66.22) }, -- 74, position for peg 3 108 | { position=Vector3(-39.95, 91.01, -68.30), wait=0.1 }, -- 75, last peg #3 109 | --{ position=Vector3(-40.21, 91.01, -68.62) }, -- 76, positioning 110 | { position=Vector3(-40.25, 91.01, -68.85) }, 111 | --{ position=Vector3(-37.76, 92.81, -67.00), wait=0.1 } 112 | { position=Vector3(-36.94, 92.81, -67.0), wait=0.1 }, 113 | { position=Vector3(-37.46, 94.6, -65.43), wait=0.00 }, 114 | { position=Vector3(-38.51, 95.38, -65.56), wait=0.00 }, 115 | } 116 | 117 | function Jump() 118 | local jumpData = JumpPoints[JumpNumber] 119 | if jumpData.sprint then 120 | yield("/generalaction sprint") 121 | yield("/wait 1") 122 | end 123 | 124 | local vectorList = Activator.CreateInstance(GenericListType) 125 | vectorList:Add(jumpData.position) 126 | IPC.vnavmesh.MoveTo(vectorList, false) 127 | if jumpData.wait ~= nil then 128 | yield("/wait "..jumpData.wait) 129 | yield("/gaction jump") 130 | end 131 | repeat 132 | yield("/wait 0.1") 133 | until not IPC.vnavmesh.IsRunning() 134 | yield("/wait 0.5") 135 | JumpNumber = JumpNumber + 1 136 | end 137 | 138 | JumpNumber = Config.Get("Starting Jump Number") 139 | if JumpNumber == 1 then 140 | IPC.vnavmesh.PathfindAndMoveTo(Vector3(-41.66, 14.02, -34.77), false) -- Getting to jump puzzle 141 | while IPC.vnavmesh.PathfindInProgress() or IPC.vnavmesh.IsRunning() do 142 | yield("/wait 1") 143 | end 144 | end 145 | while JumpNumber <= #JumpPoints do 146 | Jump() 147 | end -------------------------------------------------------------------------------- /SND Legacy/Dailies/ProcessSubs.lua: -------------------------------------------------------------------------------- 1 | FCZone = "Goblet" 2 | ArtisanMagitekRepairListId = 14272 3 | 4 | AllResidentialZones = 5 | { 6 | { 7 | zoneName = "Mist", 8 | zoneId = 339, 9 | aetheryteName = "Limsa Lominsa", 10 | aetheryteZone = 129, 11 | entryAethernet = { x=-6, y=49, z=-112 }, 12 | destinationAethernet = "Seagaze Markets" 13 | }, 14 | { 15 | zoneName = "Lavender Beds", 16 | zoneId = 340, 17 | aetheryteName = "Gridania", 18 | aetheryteZone = 132, 19 | entryAethernet = { x=5, y=2, z=184 }, 20 | destinationAethernet = "Dappled Stalls" 21 | }, 22 | { 23 | zoneName = "Goblet", 24 | zoneId = 341, 25 | aetheryteName = "Ul'dah", 26 | aetheryteZone = 130, 27 | entryAethernet = { x=20, y=-12, z=-189 }, 28 | destinationAethernet = "Goblet Exchange" 29 | }, 30 | { 31 | zoneName = "Shirogane", 32 | zoneId = 641, 33 | aetheryteName = "Kugane", 34 | aetheryteZone = 628, 35 | entryAethernet = { x=20, y=-12, z=-189 }, 36 | destinationAethernet = "Kobai Goten", 37 | materialSupplier = { x=-37, y=20, z=49 } 38 | }, 39 | { 40 | zoneName = "Empyreum", 41 | zoneId = 979, 42 | aetheryteName = "Foundation", 43 | aetheryteZone = 418, 44 | -- entryAethernet = { x=20, y=-12, z=-189 }, 45 | destinationAethernet = "The Halberd's Head" 46 | } 47 | } 48 | 49 | CompanyWorkshopZones = { 50 | 423, 51 | 424, 52 | 425, 53 | 653, 54 | 984 55 | } 56 | function IsInCompanyWorkshop() 57 | local zoneId = GetZoneID() 58 | for _, zone in ipairs(CompanyWorkshopZones) do 59 | if zoneId == zone then 60 | return true 61 | end 62 | end 63 | return false 64 | end 65 | 66 | function GoToCompanyWorkshop() 67 | if IsInCompanyWorkshop() then 68 | State = CharacterState.turnInItems 69 | LogInfo("[WorkshopGatherer] StateChange: TurnInItems") 70 | else 71 | yield("/target \"Entrance to Additional Chambers\"") 72 | yield("/wait 0.5") 73 | if GetTargetName() == "Entrance to Additional Chambers" then 74 | FC = GetZoneID() 75 | if GetDistanceToTarget() > 3 then 76 | if not PathfindInProgress() and not PathIsRunning() then 77 | yield("/vnav movetarget") 78 | end 79 | else 80 | if PathfindInProgress() or PathIsRunning() then 81 | yield("/vnav stop") 82 | elseif PathfindInProgress() or PathIsRunning() then 83 | yield("/vnav stop") 84 | elseif IsAddonVisible("SelectString") then 85 | yield("/callback SelectString true 0") 86 | else 87 | yield("/interact") 88 | yield("/wait 1") 89 | end 90 | end 91 | else 92 | if FC == nil then 93 | yield("/li fc") 94 | repeat 95 | yield("/wait 0.1") 96 | until LifestreamIsBusy() 97 | repeat 98 | yield("/wait 1") 99 | until not LifestreamIsBusy() 100 | FC = { x=GetPlayerRawXPos(), y=GetPlayerRawYPos(), z=GetPlayerRawZPos() } 101 | else 102 | yield("/target Entrance") 103 | yield("/wait 0.5") 104 | if GetTargetName() == "Entrance" then 105 | if GetDistanceToTarget() > 3 then 106 | if not PathfindInProgress() and not PathIsRunning() then 107 | yield("/vnav movetarget") 108 | end 109 | elseif PathfindInProgress() or PathIsRunning() then 110 | yield("/vnav stop") 111 | elseif IsAddonVisible("SelectYesno") then 112 | yield("/callback SelectYesno true 0") 113 | else 114 | yield("/interact") 115 | end 116 | end 117 | end 118 | end 119 | end 120 | end 121 | 122 | function PurchaseCeruleumTanks() 123 | if IsAddonVisible("SelectYesno") then 124 | yield("/callback SelectYesno true 0") 125 | elseif IsAddonVisible("FreeCompanyCreditShop") then 126 | yield("/callback FreeCompanyCreditShop true 0 0 99") 127 | elseif IsAddonVisible("SelectIconString") then 128 | yield("/callback SelectIconString true 0") 129 | elseif GetTargetName() == "Mammet Voyager #004A" then 130 | if GetDistanceToTarget() > 4 then 131 | if not PathfindInProgress() and not PathIsRunning() then 132 | yield("/vnav movetarget") 133 | end 134 | else 135 | if PathfindInProgress() or PathIsRunning() then 136 | yield("/vnav stop") 137 | else 138 | yield("/interact") 139 | end 140 | end 141 | else 142 | yield("/target Mammet Voyager #004A") 143 | end 144 | end 145 | 146 | function CraftRepairKits() 147 | if ArtisanIsListRunning() then 148 | yield("/wait 3") 149 | return 150 | elseif GetItemCount(10386) < 900 then -- purchase Grade 6 Dark Matter from estate Junkmonger 151 | if IsInCompanyWorkshop() then 152 | if IsAddonVisible("SelectYesno") then 153 | yield("/callback SelectYesno true 0") 154 | elseif GetTargetName() ~= "Stairway to Main Hall" then 155 | yield("/target Stairway to Main Hall") 156 | elseif GetDistanceToTarget() > 4 and not PathfindInProgress() and not PathIsRunning() then 157 | yield("/vnav movetarget") 158 | elseif PathIsRunning() or PathfindInProgress() then 159 | yield("/vnav stop") 160 | else 161 | yield("/interact") 162 | end 163 | elseif GetCharacterCondition(CharacterCondition.betweenAreas) then 164 | --wait 165 | elseif IsInZone(FCZone) then 166 | if GetTargetName() ~= "Entrance" then 167 | yield("/target Entrance") 168 | elseif GetDistanceToTarget() > 7 and not PathfindInProgress() and not PathIsRunning() then 169 | yield("/vnav movetarget") 170 | elseif PathIsRunning() or PathfindInProgress() then 171 | yield("/vnav stop") 172 | else 173 | yield("/interact") 174 | end 175 | else 176 | if IsAddonVisible("SelectYesno") then 177 | yield("/callback SelectYesno true 0") 178 | elseif IsAddonVisible("SelectIconString") then 179 | yield("/callback SelectIconString true 1") 180 | elseif IsAddonVisible("Shop") then 181 | yield("/callback Shop true 0 5 99") 182 | elseif GetTargetName() ~= "Junkmonger" then 183 | yield("/target Junkmonger") 184 | elseif PathfindInProgress() or PathIsRunning() then 185 | yield("/wait 1") 186 | elseif GetDistanceToTarget() > 7 then 187 | yield("/vnav movetarget") 188 | else 189 | yield("/interact") 190 | end 191 | end 192 | else 193 | if IsAddonVisible("Shop") then 194 | yield("/callback Shop true -1") 195 | else 196 | yield("/artisan lists "..ArtisanMagitekRepairListId.." start") 197 | end 198 | end 199 | end 200 | 201 | CharacterCondition = 202 | { 203 | betweenAreas=45 204 | } 205 | 206 | yield("/ays e") 207 | for _, zone in ipairs(AllResidentialZones) do 208 | if zone.zoneName == FCZone then 209 | FCZone = zone.zoneId 210 | break 211 | end 212 | end 213 | while ARSubsWaitingToBeProcessed() do 214 | if GetCharacterCondition(CharacterCondition.betweenAreas) then 215 | yield("/wait 1") 216 | elseif GetItemCount(10373) < 24 then 217 | CraftRepairKits() 218 | elseif not IsInCompanyWorkshop() then 219 | GoToCompanyWorkshop() 220 | elseif GetItemCount(10155) < 21 then 221 | PurchaseCeruleumTanks() 222 | elseif IsInCompanyWorkshop() then 223 | yield("/target Voyage Control Panel") 224 | yield("/wait 0.5") 225 | if GetDistanceToTarget() > 3 then 226 | if not PathfindInProgress() and not PathIsRunning() then 227 | yield("/vnav movetarget") 228 | end 229 | yield("/wait 1") 230 | elseif PathfindInProgress() or PathIsRunning() then 231 | yield("/vnav stop") 232 | end 233 | yield("/interact") 234 | elseif GetCharacterCondition(CharacterCondition.betweenAreas) then 235 | yield("/wait 1") 236 | else 237 | 238 | end 239 | yield("/wait 0.1") 240 | end 241 | if IsAddonVisible("SelectString") then 242 | yield("/callback SelectString true -1") 243 | end -------------------------------------------------------------------------------- /SND Legacy/Dailies/Treasure Hunt Helper.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | 3 | ******************************************************************************** 4 | * Treasure Hunt Helper * 5 | ******************************************************************************** 6 | 7 | You must start with an open map in your inventory. This script will 8 | automatically teleport you to the correct zone, fly over, dig, kill enemies, 9 | and open the chest. It will NOT do portals for you. 10 | 11 | ******************************************************************************** 12 | * Version 1.1.2 * 13 | ******************************************************************************** 14 | 15 | Created by: pot0to (https://ko-fi.com/pot0to) 16 | -> 1.1.2 Added Lifestream or Teleporter option 17 | -> 1.1.1 Fixed some wait times related to Dravanian Hinterland tp 18 | Added ability to go to Dravanian Hinterlands via Idyllshire 19 | First release 20 | 21 | ******************************************************************************** 22 | * Required Plugins * 23 | ******************************************************************************** 24 | 25 | Plugins that are needed for it to work: 26 | 27 | -> Something Need Doing [Expanded Edition] : Main Plugin for everything to work (https://puni.sh/api/repository/croizat) 28 | -> Globetrotter : For finding the treasure map spot 29 | -> VNavmesh : For Pathing/Moving (https://puni.sh/api/repository/veyn) 30 | -> RSR : For fighting things 31 | -> Teleporter OR Lifestream : For teleporting 32 | 33 | ]] 34 | 35 | --#region Settings 36 | 37 | --[[ 38 | ******************************************************************************** 39 | * Settings * 40 | ******************************************************************************** 41 | ]] 42 | 43 | CharacterCondition = { 44 | dead=2, 45 | mounted=4, 46 | inCombat=26, 47 | casting=27, 48 | occupied31=31, 49 | occupied=33, 50 | boundByDuty34=34, 51 | betweenAreas=45, 52 | jumping48=48, 53 | betweenAreas51=51, 54 | jumping61=61, 55 | mounting57=57, 56 | mounting64=64, 57 | beingmoved70=70, 58 | beingmoved75=75, 59 | flying=77 60 | } 61 | 62 | -- #region Movement 63 | 64 | function TeleportTo(aetheryteName) 65 | if HasPlugin("Lifestream") then 66 | yield("/li tp "..aetheryteName) 67 | else 68 | yield("/tp "..aetheryteName) 69 | end 70 | yield("/wait 1") -- wait for casting to begin 71 | while GetCharacterCondition(CharacterCondition.casting) do 72 | LogInfo("[TreasureHuntHelper] Casting teleport...") 73 | yield("/wait 1") 74 | end 75 | yield("/wait 1") -- wait for that microsecond in between the cast finishing and the transition beginning 76 | while not IsPlayerAvailable() or GetCharacterCondition(CharacterCondition.betweenAreas) or GetCharacterCondition(CharacterCondition.betweenAreas51) do 77 | LogInfo("[TreasureHuntHelper] Teleporting...") 78 | yield("/wait 1") 79 | end 80 | LogInfo("[TreasureHuntHelper] Finished teleporting") 81 | yield("/wait 1") 82 | end 83 | 84 | function TeleportToFlag() 85 | local aetheryteName = GetAetheryteName(GetAetherytesInZone(GetFlagZone())[0]) 86 | TeleportTo(aetheryteName) 87 | end 88 | 89 | function GoToMapLocation() 90 | local flagZone = GetFlagZone() 91 | if not IsInZone(flagZone) then 92 | if flagZone == 399 then 93 | if not IsInZone(478) then 94 | TeleportTo("Idyllshire") 95 | else 96 | if GetTargetName() ~= "aetheryte" then 97 | yield("/target aetheryte") 98 | end 99 | if GetTargetName() ~= "aetheryte" or GetDistanceToTarget() > 7 then 100 | if not PathIsRunning() and not PathfindInProgress() then 101 | PathfindAndMoveTo(71, 211, -19) 102 | end 103 | else 104 | yield("/vnav stop") 105 | yield("/li Western Hinterlands") 106 | yield("/wait 3") 107 | while LifestreamIsBusy() do 108 | yield("/wait 1") 109 | end 110 | yield("/wait 3") 111 | while GetCharacterCondition(CharacterCondition.betweenAreas) or GetCharacterCondition(CharacterCondition.betweenAreas51) do 112 | LogInfo("[TreasureHuntHelper] Between areas...") 113 | yield("/wait 1") 114 | end 115 | yield("/wait 1") 116 | end 117 | end 118 | else 119 | TeleportToFlag() 120 | end 121 | return 122 | end 123 | 124 | if not GetCharacterCondition(CharacterCondition.mounted) then 125 | yield('/gaction "mount roulette"') 126 | yield("/wait 1") 127 | repeat 128 | yield("/wait 1") 129 | until not GetCharacterCondition(CharacterCondition.casting) 130 | yield("/wait 1") 131 | repeat 132 | yield("/wait 1") 133 | until not GetCharacterCondition(CharacterCondition.jumping48) 134 | yield("/wait 3") 135 | LogInfo("[TreasureHuntHelper] Finished mounting.") 136 | return 137 | end 138 | 139 | if not PathfindInProgress() and not PathIsRunning() then 140 | yield("/vnav flyflag") 141 | yield("/wait 10") 142 | else 143 | yield("/wait 3") 144 | end 145 | end 146 | 147 | --#endregion Movement 148 | 149 | DidMap = false 150 | function Main() 151 | if IsAddonVisible("_TextError") and GetNodeText("_TextError", 1) == "You do not possess a treasure map." and not GetCharacterCondition(CharacterCondition.boundByDuty34) then 152 | yield("/echo You do not possess a treasure map.") 153 | StopFlag = true 154 | return 155 | end 156 | 157 | if GetCharacterCondition(CharacterCondition.inCombat) and not HasTarget() then 158 | yield("/battletarget") 159 | return 160 | elseif DidMap and not GetCharacterCondition(CharacterCondition.boundByDuty34) and not GetCharacterCondition(CharacterCondition.inCombat) then -- if combat is over 161 | StopFlag = true 162 | return 163 | end 164 | 165 | yield("/wait 1") 166 | yield("/tmap") 167 | yield("/wait 1") 168 | repeat 169 | yield("/wait 1") 170 | until IsAddonVisible("AreaMap") 171 | 172 | if not IsInZone(GetFlagZone()) or GetDistanceToPoint(GetFlagXCoord(), GetPlayerRawYPos(), GetFlagYCoord()) > 15 then 173 | GoToMapLocation() 174 | return 175 | elseif PathfindInProgress() or PathIsRunning() then 176 | yield("/vnav stop") 177 | return 178 | end 179 | 180 | if GetCharacterCondition(CharacterCondition.mounted) then 181 | yield("/ac dismount") 182 | if PathfindInProgress() or PathIsRunning() then 183 | yield("/vnav stop") 184 | end 185 | yield("/wait 1") 186 | return 187 | end 188 | 189 | if not GetCharacterCondition(CharacterCondition.inCombat) and (not HasTarget() or GetTargetName() ~= "Treasure Coffer") then 190 | yield("/generalaction Dig") 191 | yield("/target Treasure Coffer") 192 | return 193 | end 194 | 195 | if GetDistanceToPoint(GetTargetRawXPos(), GetTargetRawYPos(), GetTargetRawZPos()) > 3.5 then 196 | PathfindAndMoveTo(GetTargetRawXPos(), GetTargetRawYPos(), GetTargetRawZPos()) 197 | return 198 | end 199 | 200 | if IsAddonVisible("SelectYesno") then 201 | yield("/echo see yesno") 202 | yield("/callback SelectYesno true 0") -- yes open the coffer 203 | HasOpenMap = false 204 | end 205 | 206 | if not GetCharacterCondition(CharacterCondition.inCombat) then 207 | yield("/interact") 208 | return 209 | end 210 | 211 | if GetCharacterCondition(CharacterCondition.boundByDuty34) then 212 | LogInfo("[TreasureHuntHelper] DidMap = true") 213 | DidMap = true 214 | end 215 | 216 | yield("/rotation manual") 217 | yield("/battletarget") 218 | end 219 | 220 | HasOpenMap = true 221 | StopFlag = false 222 | repeat 223 | if not (IsPlayerCasting() or 224 | GetCharacterCondition(CharacterCondition.betweenAreas) or 225 | GetCharacterCondition(CharacterCondition.jumping48) or 226 | GetCharacterCondition(CharacterCondition.betweenAreas51) or 227 | GetCharacterCondition(CharacterCondition.jumping61) or 228 | GetCharacterCondition(CharacterCondition.mounting57) or 229 | GetCharacterCondition(CharacterCondition.mounting64) or 230 | GetCharacterCondition(CharacterCondition.beingmoved70) or 231 | GetCharacterCondition(CharacterCondition.beingmoved75) or 232 | LifestreamIsBusy()) 233 | then 234 | Main() 235 | yield("/wait 1") 236 | end 237 | until StopFlag -------------------------------------------------------------------------------- /SND Legacy/Crafters and Gatherers/Firmament/FirmamentCrafting.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | 3 | ******************************************************************************** 4 | * Firmament Crafting * 5 | ******************************************************************************** 6 | 7 | Crafts the green Ishgard restoration item, turns them in for Kupo Vouchers, 8 | plays the Kupo Voucher lottery when you're capped, and gets back to crafting. 9 | Script will stop itself if you are out of materials or out of inventory space. 10 | 11 | ******************************************************************************** 12 | * Version 1.0.3 * 13 | ******************************************************************************** 14 | 15 | Created by: pot0to (https://ko-fi.com/pot0to) 16 | 17 | -> 1.0.2 Fixed the check where it tries to do one more craft in the 18 | window between finishing the last craft and when it drops 19 | in your inventory 20 | Fixed normal check when exiting crafting state, added /at y 21 | Redo order of kupo voucher 22 | First release 23 | 24 | ******************************************************************************** 25 | * Required Plugins * 26 | ******************************************************************************** 27 | 28 | Plugins that are needed for it to work: 29 | 30 | -> Something Need Doing [Expanded Edition] : Main Plugin for everything to work (https://puni.sh/api/repository/croizat) 31 | -> VNavmesh : For Pathing/Moving (https://puni.sh/api/repository/veyn) 32 | -> TextAdvance: For interacting with NPCs 33 | -> Artisan: For crafting 34 | 35 | --#region Settings 36 | 37 | --[[ 38 | ******************************************************************************** 39 | * Settings * 40 | ******************************************************************************** 41 | ]] 42 | 43 | MinInventoryFreeSlots = 5 44 | 45 | --#endregion Settings 46 | 47 | --[[ 48 | ******************************************************************************** 49 | * Code: Don't touch this unless you know what you're doing * 50 | ******************************************************************************** 51 | ]] 52 | 53 | SkybuildersCraftedItems = 54 | { 55 | { className="Carpenter", classId=8, itemId=31953, recipeId=34473 }, 56 | { className="Blacksmith", classId=9, itemId=31954, recipeId=34474 }, 57 | { className="Armorer", classId=10, itemId=31955, recipeId=34475 }, 58 | { className="Goldsmith", classId=11, itemId=31956, recipeId=34476 }, 59 | { className="Leatherworker", classId=12, itemId=31957, recipeId=34477 }, 60 | { className="Weaver", classId=13, itemId=31958, recipeId=34478 }, 61 | { className="Alchemist", classId=14, itemId=31959, recipeId=34479 }, 62 | { className="Culinarian", classId=15, itemId=31960, recipeId=34480 } 63 | } 64 | 65 | local Npcs = 66 | { 67 | turnInNpc = "Potkin", 68 | kupoVouchersNpc = "Lizbeth", 69 | x = 52.750366, y = -16, z = 168.9325 70 | } 71 | 72 | CharacterCondition = 73 | { 74 | normal = 1, 75 | craftingMode = 5, --kneel to craft 76 | occupiedInQuestEvent=32, 77 | executingCraftingSkill = 40, -- executing crafting skill 78 | preparingToCraft = 41 79 | } 80 | 81 | function OutOfMaterials() 82 | for i=0,5 do 83 | local materialCount = GetNodeText("RecipeNote", 18 + i, 8) 84 | local materialRequirement = GetNodeText("RecipeNote", 18 + i, 15) 85 | if materialCount ~= "" and materialRequirement ~= "" then 86 | if tonumber(materialCount) < tonumber(materialRequirement) then 87 | return true 88 | end 89 | end 90 | end 91 | return false 92 | end 93 | 94 | function Crafting() 95 | local slots = GetInventoryFreeSlotCount() 96 | if slots <= MinInventoryFreeSlots then 97 | yield("/echo Out of inventory slots") 98 | ArtisanSetEnduranceStatus(false) 99 | if IsAddonVisible("RecipeNote") and GetCharacterCondition(CharacterCondition.preparingToCraft) then 100 | yield("/wait 1") 101 | yield("/echo Closing crafting log 1") 102 | yield("/callback RecipeNote true -1") 103 | elseif GetCharacterCondition(CharacterCondition.normal) then 104 | yield("/echo Turning in") 105 | State = CharacterState.turnIn 106 | LogInfo("State Change: TurnIn") 107 | else 108 | yield("/wait 0.5") 109 | end 110 | elseif ArtisanGetEnduranceStatus() then 111 | -- let artisan keep crafting 112 | elseif IsAddonVisible("RecipeNote") and OutOfMaterials() then 113 | if GetItemCount(ItemId) == 0 then 114 | yield("/echo Out of materials. Stopping SND.") 115 | StopFlag = true 116 | else 117 | yield("/echo Out of materials, doing final turnin") 118 | yield("/callback RecipeNote true -1") 119 | yield("/wait 1") 120 | State = CharacterState.turnIn 121 | LogInfo("State Change: TurnIn") 122 | end 123 | elseif not ArtisanGetEnduranceStatus() and 124 | (GetCharacterCondition(CharacterCondition.preparingToCraft) or GetCharacterCondition(CharacterCondition.normal)) 125 | then 126 | yield("/echo Crafting "..math.max(0, slots - MinInventoryFreeSlots).." items") 127 | ArtisanCraftItem(RecipeId, math.max(0, slots - MinInventoryFreeSlots)) 128 | yield("/wait 5") 129 | end 130 | end 131 | 132 | function TurnIn() 133 | if IsAddonVisible("RecipeNote") then 134 | yield("/callback RecipeNote true -1") 135 | elseif GetItemCount(ItemId) == 0 then 136 | if IsAddonVisible("HWDSupply") then 137 | yield("/callback HWDSupply true -1") 138 | elseif GetInventoryFreeSlotCount() <= MinInventoryFreeSlots then 139 | yield("/echo Out of inventory space. Stopping SND") 140 | StopFlag = true 141 | else 142 | State = CharacterState.crafting 143 | LogInfo("State Change: Crafting") 144 | end 145 | elseif GetItemCount(28063) >= 9900 then 146 | yield("/echo Almost capped on Skybuilders' Scrips! Stopping SND.") 147 | StopFlag = true 148 | elseif GetDistanceToPoint(Npcs.x, Npcs.y, Npcs.z) > 5 then 149 | if not PathfindInProgress() and not PathIsRunning() then 150 | PathfindAndMoveTo(Npcs.x, Npcs.y, Npcs.z) 151 | end 152 | else 153 | if PathfindInProgress() or PathIsRunning() then 154 | yield("/vnav stop") 155 | end 156 | 157 | if not HasTarget() or GetTargetName() ~= Npcs.turnInNpc then 158 | yield("/target "..Npcs.turnInNpc) 159 | elseif not IsAddonVisible("HWDSupply") then 160 | yield("/interact") 161 | yield("/wait 1") 162 | elseif GetNodeText("HWDSupply", 16) == "10/10" then 163 | yield("/callback HWDSupply true -1") 164 | State = CharacterState.kupoVoucherLottery 165 | LogInfo("State Change: KupoVouchers") 166 | else 167 | yield("/callback HWDSupply true 1 0") 168 | yield("/wait 1") 169 | end 170 | end 171 | end 172 | 173 | Retries = 0 174 | function KupoVoucherLottery() 175 | if GetInventoryFreeSlotCount() == 0 and GetItemCount(ItemId) > 0 then 176 | if IsAddonVisible("SelectYesno") then 177 | yield("/callback SelectYesno true -1") 178 | else 179 | State = CharacterState.turnIn 180 | LogInfo("State Change: TurnIn") 181 | end 182 | elseif IsAddonVisible("SelectYesno") then 183 | yield("/callback SelectYesno true 0") 184 | elseif IsAddonVisible("HWDLottery") then 185 | Retries = 0 186 | yield("/callback HWDLottery true 0 1") 187 | yield("/wait 1") 188 | yield("/callback HWDLottery true 2") 189 | yield("/wait 1") 190 | elseif Retries >= 3 then 191 | Retries = 0 192 | State = CharacterState.crafting 193 | LogInfo("State Change: Crafting") 194 | elseif GetDistanceToPoint(Npcs.x, Npcs.y, Npcs.z) > 5 then 195 | if not PathfindInProgress() and not PathIsRunning() then 196 | PathfindAndMoveTo(Npcs.x, Npcs.y, Npcs.z) 197 | end 198 | else 199 | yield("/target Lizbeth") 200 | yield("/wait 0.5") 201 | yield("/interact") 202 | yield("/wait 1") 203 | Retries = Retries + 1 204 | end 205 | end 206 | 207 | CharacterState = 208 | { 209 | crafting = Crafting, 210 | turnIn = TurnIn, 211 | kupoVoucherLottery = KupoVoucherLottery 212 | } 213 | 214 | yield("/at y") 215 | State = CharacterState.crafting 216 | local classId = GetClassJobId() 217 | ItemId = 0 218 | RecipeId = 0 219 | for _, data in ipairs(SkybuildersCraftedItems) do 220 | if data.classId == classId then 221 | ItemId = data.itemId 222 | RecipeId = data.recipeId 223 | end 224 | end 225 | if ItemId == 0 then 226 | yield("/echo Cannot recognize current class. Stopping SND.") 227 | end 228 | 229 | StopFlag = false 230 | while not StopFlag do 231 | State() 232 | yield("/wait 0.1") 233 | end 234 | -------------------------------------------------------------------------------- /SND Legacy/Dailies/Treasure Map Gatherer.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | 3 | ******************************************************************************** 4 | * Map Gathering * 5 | ******************************************************************************** 6 | 7 | Created by: pot0to (https://ko-fi.com/pot0to) 8 | 9 | Gathers a map, relogs as the next character in the list, mails them all to your 10 | "friend", rinse and repeat. You will need to install Gather Buddy Reborn and add 11 | your desired map to the auto gather list. This plugin only kicks off the gather 12 | list and waits for the map to drop in your inventory, then stops the gathering 13 | and relogs as the next character. 14 | 15 | ******************************************************************************** 16 | * Version * 17 | * 0.1.2 * 18 | ******************************************************************************** 19 | 20 | 0.1.2 Fixed state change between character swap and ready 21 | 0.1.1 Added code to support Delivery Moogle at Radz-at-Han (/tp radz) 22 | 0.1.0 Added ability to mail 23 | 0.0.10 Moved command to close gathering menu 24 | 0.0.9 Added checks to stop pathing and close gathering menus when ready to 25 | switch characters 26 | 0.0.8 Added ability to search entire timers list for map allowances, added 27 | other maps 28 | 29 | ******************************************************************************** 30 | * Required Plugins * 31 | ******************************************************************************** 32 | 1. Vnavmesh 33 | 2. Gather Buddy Reborn - Create an autogather list with your desired map 34 | 3. Autoretainer 35 | ]] 36 | 37 | --#region Settings 38 | 39 | --[[ 40 | ******************************************************************************** 41 | * Settings * 42 | ******************************************************************************** 43 | ]] 44 | 45 | MapName = "Timeworn Gazelleskin Map" -- must match the map on your GBR list 46 | 47 | Multimode = true 48 | Characters = 49 | { 50 | { characterName="John Doe", worldName="Excalibur" }, 51 | { characterName="Jane Doe", worldName="Excalibur" } 52 | } 53 | 54 | Mail = true 55 | RecipientName = "John Doe" 56 | MailboxName = "Moogle Letter Box" -- options: Moogle Letter Box, Regal Letter Box, Delivery Moogle 57 | MailboxTeleportCommand = "/li auto" -- if you don't have a private home or fc, then "/tp radz" + Delivery Moogle will work 58 | 59 | --#endregion Settings 60 | 61 | --[[ 62 | ******************************************************************************** 63 | * Code: Don't touch this unless you know what you're doing * 64 | ******************************************************************************** 65 | ]] 66 | 67 | TimewornMapIds = { 68 | -- ARR Maps 69 | {itemId=6688, itemName="Timeworn Leather Map"}, 70 | {itemId=6689, itemName="Timeworn Goatskin Map"}, 71 | {itemId=6690, itemName="Timeworn Toadskin Map"}, 72 | {itemId=6691, itemName="Timeworn Boarskin Map"}, 73 | {itemId=6692, itemName="Timeworn Peisteskin Map"}, 74 | 75 | -- Heavensward Maps 76 | {itemId=12241, itemName="Timeworn Archaeoskin Map"}, 77 | {itemId=12242, itemName="Timeworn Wyvernskin Map"}, 78 | {itemId=12243, itemName="Timeworn Dragonskin Map"}, 79 | 80 | -- Stormblood Maps 81 | {itemId=17835, itemName="Timeworn Gaganaskin Map"}, 82 | {itemId=17836, itemName="Timeworn Gazelleskin Map"}, 83 | 84 | -- Shadowbringers Maps 85 | {itemId=26744, itemName="Timeworn Gliderskin Map"}, 86 | {itemId=26745, itemName="Timeworn Zonureskin Map"}, 87 | 88 | -- Endwalker Maps 89 | {itemId=36611, itemName="Timeworn Saigaskin Map"}, 90 | {itemId=36612, itemName="Timeworn Kumbhiraskin Map"}, 91 | {itemId=39591, itemName="Timeworn Ophiotauroskin Map"}, 92 | 93 | -- Dawntrail Maps 94 | {itemId=43556, itemName="Timeworn Loboskin Map"}, 95 | {itemId=43557, itemName="Timeworn Br'aaxskin Map"} 96 | } 97 | 98 | function GetMapInfo() 99 | for _, mapInfo in ipairs(TimewornMapIds) do 100 | if mapInfo.itemName == MapName then 101 | return mapInfo 102 | end 103 | end 104 | end 105 | 106 | function HasMapAllowance() 107 | if not IsAddonVisible("ContentsInfo") then 108 | yield("/timers") 109 | yield ("/wait 1") 110 | end 111 | 112 | for i = 1, 15 do 113 | local timerName = GetNodeText("ContentsInfo", 8, i, 5) 114 | if timerName == "Next Map Allowance" then 115 | return GetNodeText("ContentsInfo", 8, i, 4) == "Available Now" 116 | end 117 | end 118 | return false 119 | end 120 | 121 | function Gather() 122 | if LifestreamIsBusy() then 123 | return 124 | end 125 | 126 | if GetItemCount(MapInfo.itemId) > 0 then 127 | State = CharacterState.ready 128 | return 129 | end 130 | 131 | if not GBRAutoOn then 132 | yield("/gbr auto on") 133 | GBRAutoOn = true 134 | end 135 | yield("/wait 10") 136 | end 137 | 138 | function MailMap() 139 | if LifestreamIsBusy() then 140 | return 141 | end 142 | 143 | if GetItemCount(MapInfo.itemId) == 0 then 144 | if IsAddonVisible("LetterList") then 145 | yield("/callback LetterList true -1") 146 | end 147 | State = CharacterState.ready 148 | return 149 | end 150 | 151 | if IsAddonVisible("SelectYesno") then 152 | yield("/callback SelectYesno true 0") 153 | return 154 | end 155 | 156 | if IsAddonVisible("LetterEditor") then 157 | if MapAttached then 158 | --local dateString = os.date("%B %d, %Y", os.time(os.date("*t"))) 159 | yield('/callback LetterEditor true 0 0 "'..RecipientName..'" "sending you a map" 0 0') 160 | return 161 | end 162 | 163 | -- search through every inventory slot until you find the map 164 | for inventoryPage=0,4 do 165 | for inventorySlot=0,34 do 166 | if (GetItemIdInSlot(inventoryPage, inventorySlot) == MapInfo.itemId) then 167 | yield("/callback LetterEditor true 3 0 "..inventoryPage.." "..inventorySlot.." 0 0") 168 | MapAttached = true 169 | return 170 | end 171 | end 172 | end 173 | 174 | yield("/echo Could not find "..MapInfo.itemName.." in inventory.") 175 | State = CharacterState.ready 176 | return 177 | end 178 | 179 | if IsAddonVisible("LetterList") then 180 | yield("/callback LetterList true 1 0 0 0") -- click "New" 181 | return 182 | end 183 | 184 | yield("/target "..MailboxName) 185 | 186 | if HasTarget() and GetTargetName() == MailboxName then 187 | if GetDistanceToTarget() > 5 then 188 | PathfindAndMoveTo(GetTargetRawXPos(), GetTargetRawYPos(), GetTargetRawZPos(), false) 189 | 190 | repeat 191 | yield("/wait 1") 192 | until GetDistanceToTarget() <= 5 193 | yield("/vnav stop") 194 | end 195 | yield("/interact") 196 | return 197 | else 198 | yield(MailboxTeleportCommand) 199 | return 200 | end 201 | end 202 | 203 | function SwapCharacters() 204 | if GBRAutoOn then 205 | yield("/gbr auto off") 206 | GBRAutoOn = false 207 | end 208 | yield("/ays multi d") 209 | yield("/ays disable") 210 | for i=1, #Characters do 211 | if Characters[i].visited == nil then 212 | Characters[i].visited = true 213 | local nextCharacterName = Characters[i].characterName.."@"..Characters[i].worldName 214 | if GetCharacterName(true) ~= nextCharacterName then 215 | yield("/ays relog "..nextCharacterName) 216 | -- yield("/wait 3") 217 | repeat 218 | yield("/wait 1") 219 | until GetCharacterName(true) == nextCharacterName 220 | -- yield("/waitaddon _ActionBar ") 221 | yield("/waitaddon _ActionBar") 222 | State = CharacterState.ready 223 | end 224 | return 225 | end 226 | end 227 | Multimode = false 228 | end 229 | 230 | function Ready() 231 | if IsAddonVisible("Gathering") then 232 | yield("/callback Gathering true -1") 233 | return 234 | end 235 | 236 | if IsPlayerOccupied() then -- wait for player to be available 237 | return 238 | end 239 | 240 | if GetItemCount(MapInfo.itemId) > 0 then 241 | if Mail and RecipientName ~= GetCharacterName(false) then 242 | MapAttached = false 243 | State = CharacterState.mailing 244 | end 245 | elseif not HasMapAllowance() then 246 | yield("/echo No map allowance left for today.") 247 | if Multimode then 248 | State = CharacterState.swapping 249 | end 250 | else 251 | State = CharacterState.gathering 252 | end 253 | end 254 | 255 | CharacterState = 256 | { 257 | ready = Ready, 258 | gathering = Gather, 259 | mailing = MailMap, 260 | swapping = SwapCharacters 261 | } 262 | 263 | yield("/at y") 264 | GBRAutoOn = false 265 | MapInfo = GetMapInfo() 266 | State = CharacterState.ready 267 | if MapInfo == nil then 268 | yield("/echo Cannot find item # for "..MapName) 269 | else 270 | repeat 271 | State() 272 | yield("/wait 1") 273 | until not Multimode and (not HasMapAllowance() or (GetItemCount(MapInfo.itemId) > 0 and not Mail)) 274 | end -------------------------------------------------------------------------------- /SND Legacy/Field Expeditions/Occult Crescent/OCH Helper.lua: -------------------------------------------------------------------------------- 1 | ShouldExtractMateria = true 2 | SelfRepair = true 3 | RepairAmount = 5 4 | ShouldAutoBuyDarkMatter = true 5 | ShouldDumpSilver = true 6 | ItemToPurchase = "Aetherspun Silver" 7 | 8 | ShopItems = 9 | { 10 | { itemName = "Aetherspun Silver", menuIndex=1, itemIndex = 5, price = 1200 }, 11 | } 12 | 13 | CharacterCondition = { 14 | dead=2, 15 | mounted=4, 16 | inCombat=26, 17 | casting=27, 18 | occupiedInEvent=31, 19 | occupiedInQuestEvent=32, 20 | occupied=33, 21 | boundByDuty34=34, 22 | occupiedMateriaExtractionAndRepair=39, 23 | betweenAreas=45, 24 | jumping48=48, 25 | jumping61=61, 26 | occupiedSummoningBell=50, 27 | betweenAreasForDuty=51, 28 | boundByDuty56=56, 29 | mounting57=57, 30 | mounting64=64, 31 | beingMoved=70, 32 | flying=77 33 | } 34 | 35 | function TurnOnOCH() 36 | if not IllegalMode then 37 | IllegalMode = true 38 | yield("/ochillegal on") 39 | end 40 | end 41 | 42 | function TurnOffOCH() 43 | if IllegalMode then 44 | IllegalMode = false 45 | yield("/ochillegal off") 46 | end 47 | if PathfindInProgress() or PathIsRunning() then 48 | yield("/vnav stop") 49 | end 50 | if LifestreamIsBusy() then 51 | yield("/li stop") 52 | end 53 | end 54 | 55 | function ExtractMateria() 56 | TurnOffOCH() 57 | 58 | if GetCharacterCondition(CharacterCondition.mounted) then 59 | yield('/ac dismount') 60 | return 61 | end 62 | 63 | if GetCharacterCondition(CharacterCondition.occupiedMateriaExtractionAndRepair) then 64 | return 65 | end 66 | 67 | if CanExtractMateria(100) and GetInventoryFreeSlotCount() > 1 then 68 | if not IsAddonVisible("Materialize") then 69 | yield("/generalaction \"Materia Extraction\"") 70 | return 71 | end 72 | 73 | LogInfo("[OCHHelper] Extracting materia...") 74 | 75 | if IsAddonVisible("MaterializeDialog") then 76 | yield("/callback MaterializeDialog true 0") 77 | else 78 | yield("/callback Materialize true 2 0") 79 | end 80 | else 81 | if IsAddonVisible("Materialize") then 82 | yield("/callback Materialize true -1") 83 | else 84 | State = CharacterState.ready 85 | LogInfo("[FATE] State Change: Ready") 86 | end 87 | end 88 | end 89 | 90 | function ReturnToBase() 91 | yield("/gaction Return") 92 | repeat 93 | yield("/wait 1") 94 | until not GetCharacterCondition(CharacterCondition.casting) 95 | repeat 96 | yield("/wait 1") 97 | until not GetCharacterCondition(CharacterCondition.betweenAreas) 98 | end 99 | 100 | DarkMatterItemId = 33916 101 | Mender = { name="Expedition Supplier", x=821.47, y=72.73, z=-669.12 } 102 | BaseAetheryte = { x=830.75, y=72.98, z=-695.98 } 103 | function Repair() 104 | TurnOffOCH() 105 | 106 | -- if occupied by repair, then just wait 107 | if GetCharacterCondition(CharacterCondition.occupiedMateriaExtractionAndRepair) then 108 | LogInfo("[OCHHelper] Repairing...") 109 | yield("/wait 1") 110 | return 111 | end 112 | 113 | if IsAddonVisible("SelectYesno") then 114 | yield("/callback SelectYesno true 0") 115 | return 116 | end 117 | 118 | if IsAddonVisible("Repair") then 119 | if not NeedsRepair(RepairAmount) then 120 | yield("/callback Repair true -1") -- if you don't need repair anymore, close the menu 121 | else 122 | yield("/callback Repair true 0") -- select repair 123 | end 124 | return 125 | end 126 | 127 | if SelfRepair then 128 | if GetItemCount(DarkMatterItemId) > 0 then 129 | if IsAddonVisible("Shop") then 130 | yield("/callback Shop true -1") 131 | return 132 | end 133 | 134 | if GetCharacterCondition(CharacterCondition.mounted) then 135 | Dismount() 136 | LogInfo("[OCHHelper] State Change: Dismounting") 137 | return 138 | end 139 | 140 | if NeedsRepair(RepairAmount) then 141 | if not IsAddonVisible("Repair") then 142 | LogInfo("[OCHHelper] Opening repair menu...") 143 | yield("/generalaction repair") 144 | end 145 | else 146 | State = CharacterState.ready 147 | LogInfo("[OCHHelper] State Change: Ready") 148 | end 149 | elseif ShouldAutoBuyDarkMatter then 150 | local baseToMender = DistanceBetween(Mender.x, Mender.y, Mender.z, BaseAetheryte.x, BaseAetheryte.y, BaseAetheryte.z) + 50 151 | local distanceToMender = GetDistanceToPoint(Mender.x, Mender.y, Mender.z) 152 | if distanceToMender > baseToMender then 153 | ReturnToBase() 154 | return 155 | elseif distanceToMender > 7 then 156 | if not (PathfindInProgress() or PathIsRunning()) then 157 | PathfindAndMoveTo(Mender.x, Mender.y, Mender.z) 158 | end 159 | else 160 | if not HasTarget() or GetTargetName() ~= Mender.name then 161 | yield("/target "..Mender.name) 162 | elseif not GetCharacterCondition(CharacterCondition.occupiedInQuestEvent) then 163 | yield("/interact") 164 | elseif IsAddonVisible("SelectIconString") then 165 | yield("/callback SelectIconString true 0") 166 | elseif IsAddonVisible("SelectYesno") then 167 | yield("/callback SelectYesno true 0") 168 | elseif IsAddonVisible("Shop") then 169 | yield("/callback Shop true 0 10 99") 170 | end 171 | end 172 | else 173 | yield("/echo Out of Dark Matter and ShouldAutoBuyDarkMatter is false. Switching to mender.") 174 | SelfRepair = false 175 | end 176 | else 177 | if NeedsRepair(RepairAmount) then 178 | local baseToMender = DistanceBetween(Mender.x, Mender.y, Mender.z, BaseAetheryte.x, BaseAetheryte.y, BaseAetheryte.z) + 50 179 | local distanceToMender = GetDistanceToPoint(Mender.x, Mender.y, Mender.z) 180 | if distanceToMender > baseToMender then 181 | ReturnToBase() 182 | return 183 | elseif distanceToMender > 7 then 184 | if not (PathfindInProgress() or PathIsRunning()) then 185 | PathfindAndMoveTo(Mender.x, Mender.y, Mender.z) 186 | end 187 | elseif IsAddonVisible("SelectIconString") then 188 | yield("/callback SelectIconString true 1") 189 | else 190 | if not HasTarget() or GetTargetName() ~= Mender.npcName then 191 | yield("/target "..Mender.npcName) 192 | elseif not GetCharacterCondition(CharacterCondition.occupiedInQuestEvent) then 193 | yield("/interact") 194 | end 195 | end 196 | else 197 | State = CharacterState.ready 198 | LogInfo("[OCHHelper] State Change: Ready") 199 | end 200 | end 201 | end 202 | 203 | PhantomVillageZoneId = 1278 204 | OccultCrescentZoneId = 1252 205 | Talked = false 206 | function ZoneIn() 207 | if GetCharacterCondition(CharacterCondition.betweenAreas) then 208 | yield("/wait 3") 209 | elseif IsInZone(PhantomVillageZoneId) then 210 | LogInfo("[OCHHelper] Already in Phantom Village") 211 | local npc = { name="Jeffroy", x=-77.958374, y=5, z=-15.396423} 212 | if GetDistanceToPoint(npc.x, npc.y, npc.z) >= 7 then 213 | PathfindAndMoveTo(npc.x, npc.y, npc.z) 214 | elseif PathfindInProgress() or PathIsRunning() then 215 | yield("/vnav stop") 216 | elseif GetTargetName() ~= npc.name then 217 | yield("/target "..npc.name) 218 | elseif IsAddonVisible("ContentsFinderConfirm") then 219 | yield("/wait 1") 220 | yield("/callback ContentsFinderConfirm true 8") 221 | yield("/wait 3") 222 | elseif IsAddonVisible("SelectString") then 223 | yield("/callback SelectString true 0") 224 | elseif not Talked then 225 | Talked = true 226 | yield("/echo interact") 227 | yield("/interact") 228 | end 229 | elseif not IsInZone(OccultCrescentZoneId) then 230 | yield("/li occult") 231 | repeat 232 | yield("/wait 1") 233 | until not LifestreamIsBusy() 234 | elseif IsInZone(OccultCrescentZoneId) then 235 | if IsPlayerAvailable() then 236 | Talked = false 237 | TurnOnOCH() 238 | yield("/rsr auto") 239 | State = CharacterState.ready 240 | LogInfo("[OCHHelper] State Change: Ready") 241 | end 242 | end 243 | end 244 | 245 | ESilverItemId = 45043 246 | EGoldItemId = 45044 247 | --Trader = { name="Expedition Trader", x=823.33, y=72.57, z=-727.81 } 248 | EsotericShop = {name="Expedition Antiquarian", x=833.83, y=72.73, z=-719.51 } 249 | function DumpSilver() 250 | local silverCount = GetItemCount(ESilverItemId) 251 | if silverCount < SilverDumpLimit then 252 | if IsAddonVisible("ShopExchangeCurrency") then 253 | yield("/callback ShopExchangeCurrency true -1") 254 | else 255 | State = CharacterState.ready 256 | LogInfo("[OCHHelper] State Change: Ready") 257 | end 258 | else 259 | TurnOffOCH() 260 | 261 | if IsAddonVisible("SelectYesno") then 262 | yield("/callback SelectYesno true 0") 263 | elseif IsAddonVisible("ShopExchangeCurrency") then 264 | local qty = silverCount//ShopItem.price 265 | LogInfo("[OCHHelper] Attempting to buy "..qty.." "..ShopItem.itemName) 266 | yield("/callback ShopExchangeCurrency true 0 "..ShopItem.itemIndex.." "..qty.. " 0") 267 | elseif IsAddonVisible("SelectIconString") then 268 | yield("/callback SelectIconString true "..ShopItem.menuIndex) 269 | else 270 | local baseToShop = DistanceBetween(EsotericShop.x, EsotericShop.y, EsotericShop.z, BaseAetheryte.x, BaseAetheryte.y, BaseAetheryte.z) + 50 271 | local distanceToShop = GetDistanceToPoint(EsotericShop.x, EsotericShop.y, EsotericShop.z) 272 | if distanceToShop > baseToShop then 273 | ReturnToBase() 274 | elseif distanceToShop > 7 then 275 | if not (PathfindInProgress() or PathIsRunning()) then 276 | PathfindAndMoveTo(EsotericShop.x, EsotericShop.y, EsotericShop.z) 277 | end 278 | else 279 | if not HasTarget() or GetTargetName() ~= EsotericShop.name then 280 | yield("/target "..EsotericShop.name) 281 | else 282 | yield("/interact") 283 | yield("/wait 0.5") 284 | end 285 | end 286 | end 287 | end 288 | end 289 | 290 | IllegalMode = false 291 | SilverDumpLimit = 9500 292 | function Ready() 293 | if not IsInZone(OccultCrescentZoneId) then 294 | State = CharacterState.zoneIn 295 | LogInfo("[OCHHelper State Change: ZoneIn]") 296 | elseif GetCharacterCondition(CharacterCondition.inCombat) then 297 | yield("/wait 1") 298 | elseif RepairAmount > 0 and NeedsRepair(RepairAmount) then 299 | State = CharacterState.repair 300 | LogInfo("[OCHHelper] State Change: Repair") 301 | elseif ShouldExtractMateria and CanExtractMateria(100) and GetInventoryFreeSlotCount() > 1 then 302 | State = CharacterState.extractMateria 303 | LogInfo("[OCHHelper] State Change: ExtractMateria") 304 | elseif ShouldDumpSilver and GetItemCount(ESilverItemId) > SilverDumpLimit then 305 | State = CharacterState.dumpSilver 306 | LogInfo("[OCHHelper] State Change: DumpSilver") 307 | elseif not IllegalMode then 308 | TurnOnOCH() 309 | end 310 | end 311 | 312 | CharacterState = { 313 | ready = Ready, 314 | zoneIn = ZoneIn, 315 | -- dead = HandleDeath, 316 | -- unexpectedCombat = HandleUnexpectedCombat, 317 | extractMateria = ExtractMateria, 318 | repair = Repair, 319 | dumpSilver = DumpSilver 320 | } 321 | 322 | for _, item in ipairs(ShopItems) do 323 | if item.itemName == ItemToPurchase then 324 | ShopItem = item 325 | end 326 | end 327 | State = CharacterState.ready 328 | while true do 329 | State() 330 | yield("/wait 0.1") 331 | end -------------------------------------------------------------------------------- /SND Legacy/Dailies/IslandSanctuary.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | ******************************************************************************** 3 | * Island Sanctuary Dailies * 4 | * Version 0.0.7 * 5 | ******************************************************************************** 6 | 7 | Created by: pot0to (https://ko-fi.com/pot0to) 8 | 9 | Description: 10 | 0. Teleports to Moraby Drydocks and enters Island Sanctuary 11 | 1. Workshop 12 | 2. Granary 13 | 3. Ranch 14 | 4. Garden 15 | 5. Exporter 16 | 17 | ******************************************************************************** 18 | * Required Plugins * 19 | ******************************************************************************** 20 | 1. Visland 21 | 2. Vnavmesh 22 | 3. Teleporter 23 | 4. TextAdvance 24 | --#region Settings 25 | 26 | ******************************************************************************** 27 | * Settings * 28 | ******************************************************************************** 29 | ]] 30 | 31 | FeedToCraft = "Island Greenfeed" 32 | Quantity = 99 33 | 34 | --[[ 35 | ******************************************************************************** 36 | * Code: Don't touch this unless you know what you're doing * 37 | ******************************************************************************** 38 | ]] 39 | 40 | FlyingUnlocked = false -- don't change this bc the pathing sucks 41 | 42 | CharacterCondition = { 43 | normal=1, 44 | mounted=4, 45 | gathering=6, 46 | casting=27, 47 | occupiedInEvent=31, 48 | occupiedInQuestEvent=32, 49 | occupied=33, 50 | boundByDutyDiadem=34, 51 | occupiedMateriaExtractionAndRepair=39, 52 | gathering42=42, 53 | fishing=43, 54 | betweenAreas=45, 55 | jumping48=48, 56 | occupiedSummoningBell=50, 57 | betweenAreasForDuty=51, 58 | boundByDuty56=56, 59 | mounting57=57, 60 | jumpPlatform=61, 61 | mounting64=64, 62 | beingMoved=70, 63 | flying=77 64 | } 65 | 66 | Locations = 67 | { 68 | moraby = { 69 | zoneId = 135, -- Lower La Noscea 70 | aetheryte = "Moraby Drydocks", 71 | ferryman = { name="Baldin", x=174, y=14, z=667 }, 72 | }, 73 | sanctuary = { 74 | zoneId = 1055, 75 | workshop = { 76 | name="Tactful Taskmaster", 77 | x=-277, y=39, z=229, 78 | addonName="MJICraftSchedule", 79 | }, 80 | granary = { 81 | name="Excitable Explorer", 82 | x=-264, y=39, z=234, 83 | addonName="MJIGatheringHouse" 84 | }, 85 | ranch = { 86 | name="Creature Comforter", 87 | x=-270, y=55, z=134, 88 | addonName="MJIAnimalManagement" 89 | }, 90 | garden = { 91 | name="Produce Producer", 92 | x=-257, y=55, z=134, 93 | addonName="MJIFarmManagement" 94 | }, 95 | furball = { 96 | name="Felicitous Furball", 97 | x=-273, y=41, z=210, 98 | waypointX=-257.56, waypointY=40.0, waypointZ=210.0 99 | }, 100 | export = { 101 | name="Enterprising Exporter", 102 | x=-267, y=41, z=207, 103 | addonName="MJIDisposeShop" 104 | }, 105 | blueCowries = { 106 | name="Horrendous Hoarder", 107 | x=-265, y=41, z=207, 108 | addonName="ShopExchangeCurrency" 109 | } 110 | } 111 | } 112 | 113 | Feed = 114 | { 115 | types = 116 | { 117 | { name="Island Sweetfeed", id=37612, recipeIndex=0, requiredMaterialsCount=0 }, 118 | { name="Island Greenfeed", id=37613, recipeIndex=1, requiredMaterialsCount=1 }, 119 | { name="Premium Island Greenfeed", id=37614, recipeIndex=2, requiredMaterialsCount=2 } 120 | }, 121 | ingredients = 122 | { 123 | { name="Island Popoto", id=25204 }, 124 | { name="Island Cabbage", id=25208 }, 125 | { name="Isleberry", id=25306 }, 126 | { name="Island Pumpkin", id=25232 }, 127 | { name="Island Onion", id=25203 }, 128 | { name="Island Tomato", id=25209 }, 129 | { name="Island Wheat", id=25357 }, 130 | { name="Island Corn", id=25352 }, 131 | { name="Island Parsnip", id=25215 }, 132 | { name="Island Radish", id=25233 } 133 | } 134 | } 135 | 136 | function TeleportTo(aetheryteName) 137 | yield("/tp "..aetheryteName) 138 | yield("/wait 1") -- wait for casting to begin 139 | while GetCharacterCondition(CharacterCondition.casting) do 140 | LogInfo("[IslandSanctuary] Casting teleport...") 141 | yield("/wait 1") 142 | end 143 | yield("/wait 1") -- wait for that microsecond in between the cast finishing and the transition beginning 144 | while GetCharacterCondition(CharacterCondition.betweenAreas) do 145 | LogInfo("[IslandSanctuary] Teleporting...") 146 | yield("/wait 1") 147 | end 148 | yield("/wait 1") 149 | end 150 | 151 | function EnterIslandSanctuary() 152 | local distanceToFerryman = GetDistanceToPoint(Locations.moraby.ferryman.x, Locations.moraby.ferryman.y, Locations.moraby.ferryman.z) 153 | 154 | if IsInZone(Locations.sanctuary.zoneId) then 155 | State = CharacterState.openWorkshop 156 | LogInfo("[IslandSanctuary] OpenWorkshop") 157 | elseif not IsInZone(Locations.moraby.zoneId) or distanceToFerryman > 30 then 158 | TeleportTo(Locations.moraby.aetheryte) 159 | elseif distanceToFerryman > 5 then 160 | if not PathfindInProgress() and not PathIsRunning() then 161 | PathfindAndMoveTo(Locations.moraby.ferryman.x, Locations.moraby.ferryman.y, Locations.moraby.ferryman.z) 162 | elseif distanceToFerryman > 13 then 163 | yield("/gaction jump") 164 | yield("/wait 1") 165 | end 166 | elseif PathfindInProgress() or PathIsRunning() then 167 | yield("/vnav stop") 168 | elseif not HasTarget() or GetTargetName() ~= Locations.moraby.ferryman.name then 169 | yield("/target "..Locations.moraby.ferryman.name) 170 | elseif not GetCharacterCondition(CharacterCondition.occupiedInQuestEvent) then 171 | yield("/interact") 172 | elseif IsAddonVisible("SelectString") then 173 | yield("/callback SelectString true 0") 174 | elseif IsAddonVisible("SelectYesno") then 175 | yield("/callback SelectYesno true 0") 176 | end 177 | end 178 | 179 | function OpenNpc(npc, nextState) 180 | if GetDistanceToPoint(npc.x, npc.y, npc.z) > 20 then 181 | if not GetCharacterCondition(CharacterCondition.mounted) then 182 | yield('/gaction "mount roulette"') 183 | yield("/wait 1") 184 | return 185 | elseif GetCharacterCondition(CharacterCondition.casting) or GetCharacterCondition(CharacterCondition.mounting57) then 186 | return 187 | end 188 | end 189 | if GetDistanceToPoint(npc.x, npc.y, npc.z) > 5 then 190 | local shouldFly = FlyingUnlocked and GetCharacterCondition(CharacterCondition.mounted) 191 | if not PathfindInProgress() and not PathIsRunning() then 192 | PathfindAndMoveTo(npc.x, npc.y, npc.z, shouldFly) 193 | end 194 | elseif PathfindInProgress() or PathIsRunning() then 195 | yield("/vnav stop") 196 | elseif not HasTarget() or GetTargetName() ~= npc.name then 197 | yield("/target ".. npc.name) 198 | elseif GetCharacterCondition(CharacterCondition.flying) then 199 | yield("/ac dismount") 200 | yield("/wait 1") 201 | elseif not GetCharacterCondition(CharacterCondition.occupiedInQuestEvent) then 202 | yield("/interact") 203 | elseif IsAddonVisible("SelectString") then 204 | yield("/callback SelectString true 0") 205 | elseif IsAddonVisible(npc.addonName) then 206 | State = nextState 207 | LogInfo("[IslandSanctuary] State Change: "..tostring(nextState)) 208 | end 209 | end 210 | 211 | function OpenAndCloseNpc(npc, nextState, logNextState) 212 | if IsAddonVisible(npc.addonName) then 213 | yield("/wait 1") -- give it a moment to process 214 | yield("/callback "..npc.addonName.." true -1") 215 | State = nextState 216 | LogInfo("[IslandSanctuary] State Change: "..logNextState) 217 | else 218 | OpenNpc(npc, State) 219 | end 220 | end 221 | 222 | function OpenWorkshop() 223 | OpenNpc(Locations.sanctuary.workshop, CharacterState.setWorkshop) 224 | end 225 | 226 | function SetWorkshopSchedule() 227 | -- copy to clickboard 228 | -- set schedule 229 | repeat 230 | yield("/callback MJICraftSchedule true -1") 231 | yield("/wait 0.5") 232 | until not IsAddonVisible("MJICraftSchedule") 233 | repeat 234 | yield("/callback SelectString true -1") 235 | yield("/wait 0.5") 236 | until not IsAddonVisible("SelectString") 237 | 238 | State = CharacterState.granary 239 | LogInfo("[IslandSanctuary] State Change: Granary") 240 | end 241 | 242 | function SetGranary() 243 | OpenAndCloseNpc(Locations.sanctuary.granary, CharacterState.ranch, "Ranch") 244 | end 245 | 246 | function CollectRanch() 247 | local feed = GetFeed() 248 | if GetItemCount(feed.id) < 10 then 249 | CraftFeed() 250 | else 251 | OpenAndCloseNpc(Locations.sanctuary.ranch, CharacterState.garden, "Garden") 252 | end 253 | end 254 | 255 | function CollectGarden() 256 | OpenAndCloseNpc(Locations.sanctuary.garden, CharacterState.talkToFurball, "GoToFurball") 257 | end 258 | 259 | PathToFurball = "H4sIAAAAAAAACu1WTY/TMBD9K5XPIYodO4lzQ2VbFbRL2S0qLOLgEreJlHiK44BWVf874yT7UeDAFbW+eN6TPfM8ebJzIDeq0SQnS+XKyuwmWwvNZK5sYbSdOJjMOrtRdU0CMrfQ7XHlR7PzkS6QmwEUJI8Ccq1Mp+o+XCm7026O+bRdON305Fo97KEyriX5lwNZQlu5CgzJD+QTyV8xIcNMsiQNyGeSCxFSiQPRPckpj8JYCkGPCMHoxRvkIiECcquKqsOEcegFwA/daONIzoL+MNvKoDRnOx2QhXHaqm9uXbnyvU8QnXJjD8gp+5vKyJdBef18388oqS3h5+MmXItytqpuX9TsE9CAXDXg9GNtbMsYvu5XjOBDp1v3Mr7T34f2wmak7xzsp2CKURky76q6nkLnj47oFjqnn88zLZWbQtMo3wxPeL1rVblnoR7NwJ4m9eSqavR1ewKvVn82A5uwaJelMg6ap6T+C5DcdHWNxumtgOZaPexRlpR+ww0U+mm1B29hg+mOwV/cEcmQpVzwviIXYcwzniaDO5IoTGQiL+44X3dkYUoFZYM7WJgyyTgf3JElIac0yy53x7m6I8G7I2JcDO7Akn4M7mAxviw0SsTFHWfsjjiVcTK4g44vO6MY8Zj/86OC4PLL8d8a4+vxFx+sRHEGCwAA" 260 | TalkedToFurball = false 261 | function TalkToFurball() 262 | local npc = Locations.sanctuary.furball 263 | if GetDistanceToPoint(npc.x, npc.y, npc.z) > 20 then 264 | if not GetCharacterCondition(CharacterCondition.mounted) then 265 | yield('/gaction "mount roulette"') 266 | yield("/wait 1") 267 | return 268 | elseif not IsVislandRouteRunning() then 269 | VislandStartRoute(PathToFurball, true) 270 | return 271 | end 272 | elseif IsVislandRouteRunning() then 273 | return 274 | end 275 | 276 | if not HasTarget() or GetTargetName() ~= npc.name then 277 | yield("/target ".. npc.name) 278 | elseif GetCharacterCondition(CharacterCondition.flying) then 279 | yield("/ac dismount") 280 | yield("/wait 1") 281 | elseif not GetCharacterCondition(CharacterCondition.occupiedInQuestEvent) then 282 | if TalkedToFurball then 283 | State = CharacterState.export 284 | LogInfo("[IslandSanctuary] State Change: Export") 285 | else 286 | yield("/interact") 287 | end 288 | elseif IsAddonVisible("SelectString") then 289 | TalkedToFurball = true 290 | yield("/callback SelectString true 2") 291 | end 292 | end 293 | 294 | function Export() 295 | OpenAndCloseNpc(Locations.sanctuary.export, CharacterState.endState, "EndState") 296 | end 297 | 298 | function End() 299 | end 300 | 301 | function GetFeed() 302 | for _, feed in ipairs(Feed.types) do 303 | if feed.name == FeedToCraft then 304 | return feed 305 | end 306 | end 307 | end 308 | 309 | function SortTopIngredients(i1, i2) 310 | return i1.quantity > i2.quantity 311 | end 312 | 313 | function GetTopIngredients(count) 314 | local ingredients = {} 315 | for i=1,#Feed.ingredients do 316 | local quantity = GetNodeText("ContextIconMenu", 2, i, 1, 6) 317 | table.insert(ingredients, { contextMenuParam=Feed.ingredients[i], quantity=quantity }) 318 | end 319 | 320 | local topIngredients = {} 321 | table.sort(ingredients, SortTopIngredients) 322 | for i=1,count do 323 | table.insert(topIngredients, ingredients[i]) 324 | end 325 | return topIngredients 326 | end 327 | 328 | function CraftFeed() 329 | if not IsAddonVisible("MJIRecipeNoteBook") then 330 | yield("/callback MJIHud true 15") 331 | elseif GetCharacterCondition(CharacterCondition.occupiedInQuestEvent) then 332 | yield("/wait 3") 333 | else 334 | yield("/wait 1") 335 | yield("/callback MJIRecipeNoteBook true 11 1") 336 | yield("/wait 1") 337 | local feed = GetFeed() 338 | yield("/callback MJIRecipeNoteBook true 12 "..feed.recipeIndex) 339 | yield("/wait 1") 340 | local topIngredients = GetTopIngredients(feed.requiredMaterialsCount) 341 | local maxCrafts = Quantity 342 | for i=0,(feed.requiredMaterialsCount-1) do 343 | local ingredient = topIngredients[i+1] 344 | 345 | yield("/callback MJIRecipeNoteBook true 20 "..i) 346 | yield("/wait 1") 347 | yield("/callback ContextIconMenu true 0 0 "..ingredient.contextMenuParam.." 0 0") 348 | yield("/wait 1") 349 | local requiredQty = GetNodeText("MJIRecipeNoteBook", 24-i, 12) 350 | local crafts = ingredient.quantity/requiredQty 351 | if crafts < maxCrafts then 352 | maxCrafts = crafts 353 | end 354 | end 355 | yield("/wait 1") 356 | yield("/callback MJIRecipeNoteBook true 14 "..maxCrafts) 357 | end 358 | end 359 | 360 | CharacterState = 361 | { 362 | enter = EnterIslandSanctuary, 363 | openWorkshop = OpenWorkshop, 364 | setWorkshop = SetWorkshopSchedule, 365 | granary = SetGranary, 366 | ranch = CollectRanch, 367 | garden = CollectGarden, 368 | talkToFurball = TalkToFurball, 369 | export = Export, 370 | endState = End 371 | } 372 | 373 | yield("/at y") 374 | State = CharacterState.enter 375 | while State ~= CharacterState.endState do 376 | if not GetCharacterCondition(CharacterCondition.betweenAreas) then 377 | State() 378 | end 379 | yield("/wait 0.1") 380 | end -------------------------------------------------------------------------------- /SND Legacy/Dailies/Allied Society Quests.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | ******************************************************************************** 3 | * Allied Society Quests * 4 | * Version 0.2.0 * 5 | ******************************************************************************** 6 | Created by: pot0to (https://ko-fi.com/pot0to) 7 | 8 | Goes around to the specified beast tribes, picks up 3 quests, does them, and 9 | moves on to the next beast tribe. 10 | 11 | ******************************************************************************** 12 | * Version * 13 | * 0.2.1 * 14 | ******************************************************************************** 15 | 16 | 0.2.1 Fixed Mamool Ja name and removed main quests from presets 17 | 0.2.0 Added Mamool Jas for patch 7.25 (credit: Leonhart) 18 | 0.1.3 Fixed "Arkasodara" tribe name 19 | Added /qst stop after finishing one set of quests 20 | Updated Namazu aetheryte to Dhoro Iloh 21 | Added ability to change classes for different Allied Socieities 22 | First working version 23 | 24 | ******************************************************************************** 25 | * Required Plugins * 26 | ******************************************************************************** 27 | 1. Vnavmesh 28 | 2. Questionable 29 | 3. TextAdvance 30 | 31 | --#region Settings 32 | ******************************************************************************** 33 | * Settings * 34 | ******************************************************************************** 35 | --]] 36 | 37 | ToDoList = { 38 | { alliedSocietyName="Mamool Ja", class="Miner" }, 39 | { alliedSocietyName="Amalj'aa", class="Summoner" } 40 | } 41 | 42 | --#endregion Settings 43 | 44 | --[[ 45 | ******************************************************************************** 46 | * Code: Don't touch this unless you know what you're doing * 47 | ******************************************************************************** 48 | ]] 49 | 50 | AlliedSocietiesTable = 51 | { 52 | amaljaa = { 53 | alliedSocietyName = "Amalj'aa", 54 | mainQuests = { first=1217, last=1221 }, 55 | dailyQuests = { first=1222, last=1251, 56 | blackList = { 57 | [1245] = true 58 | } 59 | }, 60 | x = 103.12, 61 | y = 15.05, 62 | z = -359.51, 63 | zoneId = 146, 64 | aetheryteName = "Little Ala Mhigo", 65 | expac = "A Realm Reborn" 66 | }, 67 | sylphs = 68 | { 69 | alliedSocietyName = "Sylphs", 70 | mainQuests = { first=1252, last=1256 }, 71 | dailyQuests = { first=1257, last=1286 }, 72 | x = 46.41, 73 | y = 6.07, 74 | z = 252.91, 75 | zoneId = 152, 76 | aetheryteName = "The Hawthorne Hut", 77 | expac = "A Realm Reborn" 78 | }, 79 | kobolds = 80 | { 81 | alliedSocietyName = "Kobolds", 82 | mainQuests = { first=1320, last=1324 }, 83 | dailyQuests = { first=1325, last=1373 }, 84 | x = 12.857726, 85 | y = 16.164295, 86 | z = -178.77, 87 | zoneId = 180, 88 | aetheryteName = "Camp Overlook", 89 | expac = "A Realm Reborn" 90 | }, 91 | sahagin = 92 | { 93 | alliedSocietyName = "Sahagin", 94 | mainQuests = { first=1374, last=1378 }, 95 | dailyQuests = { first=1380, last=1409 }, 96 | x = -244.53, 97 | y = -41.46, 98 | z = 52.75, 99 | zoneId = 138, 100 | aetheryteName = "Aleport", 101 | expac = "A Realm Reborn" 102 | }, 103 | ixal = 104 | { 105 | alliedSocietyName = "Ixal", 106 | mainQuests = { first=1486, last=1493 }, 107 | dailyQuests = { first=1494, last=1568 }, 108 | x = 173.21, 109 | y = -5.37, 110 | z = 81.85, 111 | zoneId = 154, 112 | aetheryteName = "Fallgourd Float", 113 | expac = "A Realm Reborn" 114 | }, 115 | vanuvanu = { 116 | alliedSocietyName = "Vanu Vanu", 117 | mainQuests = { first=2164, last=2225 }, 118 | dailyQuests = { first=2171, last=2200 }, 119 | x = -796.3722, 120 | y = -133.27, 121 | z = -404.35, 122 | zoneId = 401, 123 | aetheryteName = "Ok' Zundu", 124 | expac = "Heavensward" 125 | }, 126 | vath = { 127 | alliedSocietyName = "Vath", 128 | mainQuests = { first=2164, last=2225 }, 129 | dailyQuests = { first=2171, last=2200 }, 130 | x = 58.80, 131 | y = -48.00, 132 | z = -171.64, 133 | zoneId = 398, 134 | aetheryteName = "Tailfeather", 135 | expac = "Heavensward" 136 | }, 137 | moogles = { 138 | alliedSocietyName = "Moogles", 139 | mainQuests = { first=2320, last=2327 }, 140 | dailyQuests = { first=2290, last=2319 }, 141 | x = -335.28, 142 | y = 58.94, 143 | z = 316.30, 144 | zoneId = 400, 145 | aetheryteName = "Zenith", 146 | expac = "Heavensward" 147 | }, 148 | kojin = { 149 | alliedSocietyName = "Kojin", 150 | mainQuests = { first=2973, last=2978 }, 151 | dailyQuests = { first=2979, last=3002 }, 152 | x = 391.22, 153 | y = -119.59, 154 | z = -234.92, 155 | zoneId = 613, 156 | aetheryteName = "Tamamizu", 157 | expac = "Stormblood" 158 | }, 159 | ananta = { 160 | alliedSocietyName = "Ananta", 161 | mainQuests = { first=3036, last=3041 }, 162 | dailyQuests = { first=3043, last=3069 }, 163 | x = -26.91, 164 | y = 56.12, 165 | z = 233.53, 166 | zoneId = 612, 167 | aetheryteName = "The Peering Stones", 168 | expac = "Stormblood" 169 | }, 170 | namazu = { 171 | alliedSocietyName = "Namazu", 172 | mainQuests = { first=3096, last=3102 }, 173 | dailyQuests = { first=3103, last=3129 }, 174 | x = -777.72, 175 | y = 127.81, 176 | z = 98.76, 177 | zoneId = 622, 178 | aetheryteName = "Dhoro Iloh", 179 | expac = "Stormblood" 180 | }, 181 | pixies = { 182 | alliedSocietyName = "Pixies", 183 | mainQuests = { first=3683, last=3688 }, 184 | dailyQuests = { first=3689, last=3716 }, 185 | x = -453.69, 186 | y = 71.21, 187 | z = 573.54, 188 | zoneId = 816, 189 | aetheryteName = "Lydha Lran", 190 | expac = "Shadowbringers" 191 | }, 192 | qitari = { 193 | alliedSocietyName = "Qitari", 194 | mainQuests = { first=3794, last=3805 }, 195 | dailyQuests = { first=3806, last=3833 }, 196 | x = 786.83, 197 | y = -45.82, 198 | z = -214.51, 199 | zoneId = 817, 200 | aetheryteName = "Fanow", 201 | expac = "Shadowbringers" 202 | }, 203 | dwarves = { 204 | alliedSocietyName = "Dwarves", 205 | mainQuests = { first=3896, last=3901 }, 206 | dailyQuests = { first=3902, last=3929 }, 207 | x = -615.48, 208 | y = 65.60, 209 | z = -423.82, 210 | zoneId = 813, 211 | aetheryteName = "The Ostall Imperative", 212 | expac = "Shadowbringers" 213 | }, 214 | arkosodara = 215 | { 216 | alliedSocietyName = "Arkasodara", 217 | mainQuests = { first=4545, last=4550 }, 218 | dailyQuests = { first=4551, last=4578 }, 219 | x = -68.21, 220 | y = 39.99, 221 | z = 323.31, 222 | zoneId = 957, 223 | aetheryteName = "Yedlihmad", 224 | expac = "Endwalker" 225 | }, 226 | loporrits = 227 | { 228 | alliedSocietyName = "Loporrits", 229 | mainQuests = { first=4681, last=4686 }, 230 | dailyQuests = { first=4687, last=4714 }, 231 | x = -201.27, 232 | y = -49.15, 233 | z = -273.8, 234 | zoneId = 959, 235 | aetheryteName = "Bestways Burrow", 236 | expac = "Endwalker" 237 | }, 238 | omicrons = 239 | { 240 | alliedSocietyName = "Omicrons", 241 | mainQuests = { first=4601, last=4606 }, 242 | dailyQuests = { first=4607, last=4634 }, 243 | x=315.84, 244 | y=481.99, 245 | z=152.08, 246 | zoneId = 960, 247 | aetheryteName = "Base Omicron", 248 | expac = "Endwalker" 249 | }, 250 | pelupleu = 251 | { 252 | alliedSocietyName = "Pelupelu", 253 | mainQuests = { first=5193, last=5198 }, 254 | dailyQuests = { first=5199, last=5226 }, 255 | x=770.89954, 256 | y=12.846571, 257 | z=-261.0889, 258 | zoneId=1188, 259 | aetheryteName="Dock Poga", 260 | expac = "Dawntrail" 261 | }, 262 | mamoolja = 263 | { 264 | alliedSocietyName = "Mamool Ja", 265 | mainQuests = { first=5255, last=5260 }, 266 | dailyQuests = { first=5261, last=5288 }, 267 | x=589.3, 268 | y=-142.9, 269 | z=730.5, 270 | zoneId = 1189, 271 | aetheryteName = "Mamook", 272 | expac = "Dawntrail" 273 | } 274 | } 275 | 276 | CharacterCondition = { 277 | dead=2, 278 | mounted=4, 279 | inCombat=26, 280 | casting=27, 281 | occupiedInEvent=31, 282 | occupiedInQuestEvent=32, 283 | occupied=33, 284 | boundByDuty34=34, 285 | occupiedMateriaExtractionAndRepair=39, 286 | betweenAreas=45, 287 | jumping48=48, 288 | jumping61=61, 289 | occupiedSummoningBell=50, 290 | betweenAreasForDuty=51, 291 | boundByDuty56=56, 292 | mounting57=57, 293 | mounting64=64, 294 | beingMoved=70, 295 | flying=77 296 | } 297 | 298 | function GetAlliedSocietyTable(alliedSocietyName) 299 | for _, alliedSociety in pairs(AlliedSocietiesTable) do 300 | if alliedSociety.alliedSocietyName == alliedSocietyName then 301 | return alliedSociety 302 | end 303 | end 304 | end 305 | 306 | function GetAcceptedAlliedSocietyQuests(alliedSocietyName) 307 | local accepted = {} 308 | local allAcceptedQuests = GetAcceptedQuests() 309 | for i=0, allAcceptedQuests.Count-1 do 310 | if GetQuestAlliedSociety(allAcceptedQuests[i]):lower() == alliedSocietyName:lower() then 311 | table.insert(accepted, allAcceptedQuests[i]) 312 | end 313 | end 314 | return accepted 315 | end 316 | 317 | function CheckAllowances() 318 | if not IsAddonVisible("ContentsInfo") then 319 | yield("/timers") 320 | yield ("/wait 1") 321 | end 322 | 323 | for i = 1, 15 do 324 | local timerName = GetNodeText("ContentsInfo", 8, i, 5) 325 | if timerName == "Next Allied Society Daily Quest Allowance" then 326 | return tonumber(GetNodeText("ContentsInfo", 8, i, 4):match("%d+$")) 327 | end 328 | end 329 | return 0 330 | end 331 | 332 | if HasPlugin("Lifestream") then 333 | TeleportCommand = "/li tp" 334 | elseif HasPlugin("Teleporter") then 335 | TeleportCommand = "/tp" 336 | else 337 | yield("/error Please install either Teleporter or Lifestream") 338 | yield("/snd stop") 339 | end 340 | function TeleportTo(aetheryteName) 341 | yield(TeleportCommand.." "..aetheryteName) 342 | yield("/wait 1") -- wait for casting to begin 343 | while GetCharacterCondition(CharacterCondition.casting) do 344 | LogInfo("[FATE] Casting teleport...") 345 | yield("/wait 1") 346 | end 347 | yield("/wait 1") -- wait for that microsecond in between the cast finishing and the transition beginning 348 | while GetCharacterCondition(CharacterCondition.betweenAreas) do 349 | LogInfo("[FATE] Teleporting...") 350 | yield("/wait 1") 351 | end 352 | yield("/wait 1") 353 | end 354 | 355 | yield("/at y") 356 | for _, alliedSociety in ipairs(ToDoList) do 357 | local alliedSocietyTable = GetAlliedSocietyTable(alliedSociety.alliedSocietyName) 358 | if alliedSocietyTable ~= nil then 359 | repeat 360 | yield("/wait 1") 361 | until not IsPlayerOccupied() 362 | 363 | if not IsInZone(alliedSocietyTable.zoneId) then 364 | TeleportTo(alliedSocietyTable.aetheryteName) 365 | end 366 | 367 | if not GetCharacterCondition(CharacterCondition.mounted) then 368 | yield('/gaction "mount roulette"') 369 | end 370 | repeat 371 | yield("/wait 1") 372 | until GetCharacterCondition(CharacterCondition.mounted) 373 | PathfindAndMoveTo(alliedSocietyTable.x, alliedSocietyTable.y, alliedSocietyTable.z, true) 374 | repeat 375 | yield("/wait 1") 376 | until not PathIsRunning() and not PathfindInProgress() 377 | 378 | yield("/gs change "..alliedSociety.class) 379 | yield("/wait 3") 380 | 381 | -- pick up quests and add them to Questionable's priority list 382 | local timeout = os.time() 383 | local quests = {} 384 | for questId=alliedSocietyTable.dailyQuests.first, alliedSocietyTable.dailyQuests.last+1 do 385 | if not QuestionableIsQuestLocked(tostring(questId)) and not alliedSocietyTable.dailyQuests.blackList[questId] then 386 | table.insert(quests, questId) 387 | QuestionableClearQuestPriority() 388 | QuestionableAddQuestPriority(tostring(questId)) 389 | repeat 390 | if not QuestionableIsRunning() then 391 | yield("/qst start") 392 | elseif os.time() - timeout > 5 then 393 | yield("/echo Took more than 5 seconds to pick up the quest. Questionable may be stuck. Reloading...") 394 | yield("/qst reload") 395 | timeout = os.time() 396 | end 397 | yield("/wait 1.1") 398 | until IsQuestAccepted(questId) 399 | timeout = os.time() 400 | yield("/qst stop") 401 | end 402 | end 403 | 404 | for _, questId in ipairs(quests) do 405 | QuestionableAddQuestPriority(tostring(questId)) 406 | end 407 | 408 | repeat 409 | if not QuestionableIsRunning() then 410 | yield("/qst start") 411 | end 412 | yield("/wait 1.2") 413 | until #GetAcceptedAlliedSocietyQuests(alliedSociety.alliedSocietyName) == 0 414 | yield("/qst stop") 415 | end 416 | end 417 | -------------------------------------------------------------------------------- /SND Legacy/Weeklies/WondrousTails.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | ******************************************************************************** 3 | * Wondrous Tails Doer * 4 | * Version 0.2.3 * 5 | ******************************************************************************** 6 | 7 | Created by: pot0to (https://ko-fi.com/pot0to) 8 | 9 | Description: Picks up a Wondrous Tails journal from Khloe, then attempts each duty 10 | 11 | For dungeons: 12 | - Attempts dungeon Unsynced if duty is at least 20 levels below you 13 | - Attempts dungeon with Duty Support if duty is within 20 levels of you and Duty 14 | Support is available 15 | 16 | For EX Trials: 17 | - Attempts any duty unsynced if it is 20 levels below you and skips any that are 18 | within 20 levels 19 | - Note: Not all EX trials have BossMod support, but this script will attempt 20 | each one once anyways 21 | - Some EX trials are blacklisted due to mechanics that cannot be done solo 22 | (Byakko tank buster, Tsukuyomi meteors, etc.) 23 | 24 | Alliance Raids/PVP/Treasure Maps/Palace of the Dead 25 | - Skips them all 26 | 27 | -> 0.2.3 Changed Final Coil to do Turn 4 instead of Turn 1 28 | -> 0.2.2 Allowed unsync lvl 80 29 | -> 0.2.1 Duty names updated after patch 7.2 30 | -> 0.2.0 Fixes for ex trials 31 | Update for patch 7.1 32 | 33 | ******************************************************************************** 34 | * Required Plugins * 35 | ******************************************************************************** 36 | 1. Autoduty 37 | 2. Rotation Solver Reborn 38 | 3. BossModReborn (BMR) or Veyn's BossMod (VBM) 39 | 40 | ******************************************************************************** 41 | * Code: Don't touch this unless you know what you're doing * 42 | ******************************************************************************** 43 | ]] 44 | 45 | WonderousTailsDuties = { 46 | { -- type 0: extreme trials 47 | { instanceId=20010, dutyId=297, dutyName="The Howling Eye (Extreme)", minLevel=50 }, 48 | { instanceId=20009, dutyId=296, dutyName="The Navel (Extreme)", minLevel=50 }, 49 | { instanceId=20008, dutyId=295, dutyName="The Bowl of Embers (Extreme)", minLevel=50 }, 50 | { instanceId=20012, dutyId=364, dutyName="Thornmarch (Extreme)", minLevel=50 }, 51 | { instanceId=20018, dutyId=359, dutyName="The Whorleater (Extreme)", minLevel=50 }, 52 | { instanceId=20023, dutyId=375, dutyName="The Striking Tree (Extreme)", minLevel=50 }, 53 | { instanceId=20025, dutyId=378, dutyName="The Akh Afah Amphitheatre (Extreme)", minLevel=50 }, 54 | { instanceId=20013, dutyId=348, dutyName="The Minstrel's Ballad: Ultima's Bane", minLevel=50 }, 55 | { instanceId=20034, dutyId=447, dutyName="The Limitless Blue (Extreme)", minLevel=60 }, 56 | { instanceId=20032, dutyId=446, dutyName="Thok ast Thok (Extreme)", minLevel=60 }, 57 | { instanceId=20036, dutyId=448, dutyName="The Minstrel's Ballad: Thordan's Reign", minLevel=60 }, 58 | { instanceId=20038, dutyId=524, dutyName="Containment Bay S1T7 (Extreme)", minLevel=60 }, 59 | { instanceId=20040, dutyId=566, dutyName="The Minstrel's Ballad: Nidhogg's Rage", minLevel=60 }, 60 | { instanceId=20042, dutyId=577, dutyName="Containment Bay P1T6 (Extreme)", minLevel=60 }, 61 | { instanceId=20044, dutyId=638, dutyName="Containment Bay Z1T9 (Extreme)", minLevel=60 }, 62 | { instanceId=20049, dutyId=720, dutyName="Emanation (Extreme)", minLevel=70 }, 63 | { instanceId=20056, dutyId=779, dutyName="The Minstrel's Ballad: Tsukuyomi's Pain", minLevel=70 }, 64 | { instanceId=20058, dutyId=811, dutyName="Hells' Kier (Extreme)", minLevel=70 }, 65 | { instanceId=20054, dutyId=762, dutyName="The Great Hunt (Extreme)", minLevel=70 }, 66 | { instanceId=20061, dutyId=825, dutyName="The Wreath of Snakes (Extreme)", minLevel=70 }, 67 | { instanceId=20063, dutyId=858, dutyName="The Dancing Plague (Extreme)", minLevel=80 }, 68 | { instanceId=20065, dutyId=848, dutyName="The Crown of the Immaculate (Extreme)", minLevel=80 }, 69 | { instanceId=20067, dutyId=885, dutyName="The Minstrel's Ballad: Hades's Elegy", minLevel=80 }, 70 | { instanceId=20069, dutyId=912, dutyName="Cinder Drift (Extreme)", minLevel=80 }, 71 | { instanceId=20070, dutyId=913, dutyName="Memoria Misera (Extreme)", minLevel=80 }, 72 | { instanceId=20072, dutyId=923, dutyName="The Seat of Sacrifice (Extreme)", minLevel=80 }, 73 | { instanceId=20074, dutyId=935, dutyName="Castrum Marinum (Extreme)", minLevel=80 }, 74 | { instanceId=20076, dutyId=951, dutyName="The Cloud Deck (Extreme)", minLevel=80 }, 75 | { instanceId=20078, dutyId=996, dutyName="The Minstrel's Ballad: Hydaelyn's Call", minLevel=90 }, 76 | { instanceId=20081, dutyId=993, dutyName="The Minstrel's Ballad: Zodiark's Fall", minLevel=90 }, 77 | { instanceId=20083, dutyId=998, dutyName="The Minstrel's Ballad: Endsinger's Aria", minLevel=90 }, 78 | { instanceId=20085, dutyId=1072, dutyName="Storm's Crown (Extreme)", minLevel=90 }, 79 | { instanceId=20087, dutyId=1096, dutyName="Mount Ordeals (Extreme)", minLevel=90 }, 80 | { instanceId=20090, dutyId=1141, dutyName="The Voidcast Dais (Extreme)", minLevel=90 }, 81 | { instanceId=20092, dutyId=1169, dutyName="The Abyssal Fracture (Extreme)", minLevel=90 } 82 | }, 83 | { -- type 1: expansion cap dungeons 84 | { dutyName="Dungeons (Lv. 100)", dutyId=1266, minLevel=100 } --Underkeep 85 | }, 86 | 2, 87 | 3, 88 | { -- type 4: normal raids 89 | { dutyName="Binding Coil of Bahamut", dutyId=241, minLevel=50 }, 90 | { dutyName="Second Coil of Bahamut", dutyId=355, minLevel=50 }, 91 | { dutyName="Final Coil of Bahamut", dutyId=196, minLevel=50 }, 92 | { dutyName="Alexander: Gordias", dutyId=442, minLevel=60 }, 93 | { dutyName="Alexander: Midas", dutyId=520, minLevel=60 }, 94 | { dutyName="Alexander: The Creator", dutyId=580, minLevel=60 }, 95 | { dutyName="Omega: Deltascape", dutyId=693, minLevel=70 }, 96 | { dutyName="Omega: Sigmascape", dutyId=748, minLevel=70 }, 97 | { dutyName="Omega: Alphascape", dutyId=798, minLevel=70 }, 98 | { dutyName="Eden's Gate", dutyId=849, minLevel=80 }, 99 | { dutyName="Eden's Verse", dutyId=903, minLevel=80 }, 100 | { dutyName="Eden's Promise", dutyId=942, minLevel=80 }, 101 | -- { dutyName="AAC Light-heavyweight M1 or M2", dutyId=1225, minLevel=100 }, 102 | -- { dutyName="AAC Light-heavyweight M3 or M4", dutyId=1229, minLevel=100 } 103 | }, 104 | { -- type 5: leveling dungeons 105 | { dutyName="Leveling Dungeons (Lv. 1-49)", dutyId=172, minLevel=15 }, --The Aurum Vale 106 | { dutyName="Leveling Dungeons (Lv. 51-59/61-69/71-79)", dutyId=434, minLevel=51 }, --The Dusk Vigil 107 | { dutyName="Leveling Dungeons (Lv. 81-89/91-99)", dutyId=952, minLevel=81 }, --The Tower of Zot 108 | }, 109 | { -- type 6: expansion cap dungeons 110 | { dutyName="High-level Dungeons (Lv. 50 & 60)", dutyId=362, minLevel=50 }, --Brayflox Longstop (Hard) 111 | { dutyName="High-level Dungeons (Lv. 70 & 80)", dutyId=1146, minLevel=70 }, --Ala Mhigo 112 | { dutyName="High-level Dungeons (Lv. 90)", dutyId=973, minLevel=90 }, --The Dead Ends 113 | 114 | }, 115 | { -- type 7: ex trials 116 | { 117 | { instanceId=20008, dutyId=295, dutyName="Trials (Lv. 50-60)", minLevel=50 }, -- Bowl of Embers 118 | { instanceId=20049, dutyId=720, dutyName="Trials (Lv. 70-100)", minLevel=70 } 119 | } 120 | }, 121 | { -- type 8: alliance raids 122 | 123 | }, 124 | { -- type 9: normal raids 125 | { dutyName="Normal Raids (Lv. 50-60)", dutyId=241, minLevel=50 }, 126 | { dutyName="Normal Raids (Lv. 70-80)", dutyId=693, minLevel=70 }, 127 | }, 128 | Blacklisted= { 129 | { -- 0 130 | { instanceId=20052, dutyId=758, dutyName="The Jade Stoa (Extreme)", minLevel=70 }, -- cannot solo double tankbuster vuln 131 | { instanceId=20047, dutyId=677, dutyName="The Pool of Tribute (Extreme)", minLevel=70 }, -- cannot solo active time maneuver 132 | { instanceId=20056, dutyId=779, dutyName="The Minstrel's Ballad: Tsukuyomi's Pain", minLevel=70 } -- cannot solo meteors 133 | }, 134 | {}, -- 1 135 | {}, -- 2 136 | { -- 3 137 | { dutyName="Treasure Dungeons" } 138 | }, 139 | { -- 4 140 | { dutyName="Alliance Raids (A Realm Reborn)", dutyId=174 }, 141 | { dutyName="Alliance Raids (Heavensward)", dutyId=508 }, 142 | { dutyName="Alliance Raids (Stormblood)", dutyId=734 }, 143 | { dutyName="Alliance Raids (Shadowbringers)", dutyId=882 }, 144 | { dutyName="Alliance Raids (Endwalker)", dutyId=1054 }, 145 | { dutyName="Asphodelos= First to Fourth Circles", dutyId=1002 }, 146 | { dutyName="Abyssos= Fifth to Eighth Circles", dutyId=1081 }, 147 | { dutyName="Anabaseios= Ninth to Twelfth Circles", dutyId=1147 } 148 | } 149 | } 150 | } 151 | 152 | Khloe = { 153 | x = -19.346453, 154 | y = 210.99998, 155 | z = 0.086749226, 156 | name = "Khloe Aliapoh" 157 | } 158 | 159 | -- Region: Functions --------------------------------------------------------------------------------- 160 | 161 | function SearchWonderousTailsTable(type, data, text) 162 | if type == 0 then -- ex trials are indexed by instance# 163 | for _, duty in ipairs(WonderousTailsDuties[type+1]) do 164 | if duty.instanceId == data then 165 | return duty 166 | end 167 | end 168 | elseif type == 1 or type == 5 or type == 6 or type == 7 then -- dungeons, level range ex trials 169 | for _, duty in ipairs(WonderousTailsDuties[type+1]) do 170 | if duty.dutyName == text then 171 | return duty 172 | end 173 | end 174 | elseif type == 4 or type == 8 then -- normal raids 175 | for _, duty in ipairs(WonderousTailsDuties[type+1]) do 176 | if duty.dutyName == text then 177 | return duty 178 | end 179 | end 180 | end 181 | end 182 | 183 | -- Region: Main --------------------------------------------------------------------------------- 184 | 185 | CurrentLevel = GetLevel() 186 | 187 | -- Pick up a journal if you need one 188 | if not HasWeeklyBingoJournal() or IsWeeklyBingoExpired() or WeeklyBingoNumPlacedStickers() == 9 then 189 | if not IsInZone(478) then 190 | yield("/tp Idyllshire") 191 | yield("/wait 1") 192 | end 193 | while not (IsInZone(478) and IsPlayerAvailable()) do 194 | yield("/wait 1") 195 | end 196 | PathfindAndMoveTo(Khloe.x, Khloe.y, Khloe.z) 197 | while(GetDistanceToPoint(Khloe.x, Khloe.y, Khloe.z) > 5) do 198 | yield("/wait 1") 199 | end 200 | yield("/target "..Khloe.name) 201 | yield("/wait 1") 202 | yield("/interact") 203 | while not IsAddonVisible("SelectString") do 204 | yield("/click Talk Click") 205 | yield("/wait 1") 206 | end 207 | if IsAddonVisible("SelectString") then 208 | if not HasWeeklyBingoJournal() then 209 | yield("/callback SelectString true 0") 210 | elseif IsWeeklyBingoExpired() then 211 | yield("/callback SelectString true 1") 212 | elseif WeeklyBingoNumPlacedStickers() == 9 then 213 | yield("/callback SelectString true 0") 214 | end 215 | 216 | end 217 | while GetCharacterCondition(32) do 218 | yield("/click Talk Click") 219 | yield("/wait 1") 220 | end 221 | yield("/wait 1") 222 | end 223 | 224 | yield("/bmrai on") 225 | yield("/vbmai on") 226 | 227 | -- skip 13: Shadowbringers raids (not doable solo unsynced) 228 | -- skip 14: Endwalker raids (not doable solo unsynced) 229 | -- skip 15: PVP 230 | for i = 0, 12 do 231 | if GetWeeklyBingoTaskStatus(i) == 0 then 232 | local key = GetWeeklyBingoOrderDataKey(i) 233 | local type = GetWeeklyBingoOrderDataType(key) 234 | local data = GetWeeklyBingoOrderDataData(key) 235 | local text = GetWeeklyBingoOrderDataText(key) 236 | LogInfo("[WondrousTails] Wonderous Tails #"..(i+1).." Key: "..key) 237 | LogInfo("[WondrousTails] Wonderous Tails #"..(i+1).." Type: "..type) 238 | LogInfo("[WondrousTails] Wonderous Tails #"..(i+1).." Data: "..data) 239 | LogInfo("[WondrousTails] Wonderous Tails #"..(i+1).." Text: "..text) 240 | 241 | local duty = SearchWonderousTailsTable(type, data, text) 242 | if duty == nil then 243 | yield("/echo duty is nil") 244 | end 245 | local dutyMode = "Support" 246 | if duty ~= nil then 247 | if CurrentLevel < duty.minLevel then 248 | yield("/echo [WonderousTails] Cannot queue for "..duty.dutyName.." as level is too low.") 249 | duty.dutyId = nil 250 | elseif type == 0 then -- trials 251 | yield("/autoduty cfg Unsynced true") 252 | dutyMode = "Trial" 253 | elseif type == 4 then -- raids 254 | yield("/autoduty cfg Unsynced true") 255 | dutyMode = "Raid" 256 | elseif CurrentLevel - duty.minLevel < 20 then 257 | -- yield("/autoduty cfg dutyModeEnum 1") -- TODO: test this when it gets released 258 | -- yield("/autoduty cfg Unsynced false") 259 | dutyMode = "Support" 260 | else 261 | -- yield("/autoduty cfg dutyModeEnum 8") 262 | yield("/autoduty cfg Unsynced true") 263 | dutyMode = "Regular" 264 | end 265 | 266 | if duty.dutyId ~= nil then 267 | yield("/echo Queuing duty TerritoryId#"..duty.dutyId.." for Wonderous Tails #"..(i+1)) 268 | yield("/autoduty run "..dutyMode.." "..duty.dutyId.." 1 true") 269 | yield("/rotation auto") 270 | yield("/wait 10") 271 | while GetCharacterCondition(34) or GetCharacterCondition(51) or GetCharacterCondition(56) do -- wait for duty to be finished 272 | if GetCharacterCondition(2) and i > 4 then -- dead, not a dungeon 273 | yield("/echo Died to "..duty.dutyName..". Skipping.") 274 | repeat 275 | yield("/wait 1") 276 | until not GetCharacterCondition(2) 277 | LeaveDuty() 278 | break 279 | end 280 | yield("/wait 1") 281 | end 282 | yield("/wait 10") 283 | else 284 | if duty.dutyName ~= nil then 285 | yield("/echo Wonderous Tails Script does not support Wonderous Tails entry #"..(i+1).." "..duty.dutyName) 286 | LogInfo("[WonderousTails] Wonderous Tails Script does not support Wonderous Tails entry #"..(i+1).." "..duty.dutyName) 287 | else 288 | yield("/echo Wonderous Tails Script does not support Wonderous Tails entry #"..(i+1)) 289 | LogInfo("[WonderousTails] Wonderous Tails Script does not support Wonderous Tails entry #"..(i+1)) 290 | end 291 | end 292 | end 293 | end 294 | 295 | -- if GetWeeklyBingoTaskStatus(i) == 1 296 | -- and (not StopPlacingStickersAt7 or WeeklyBingoNumPlacedStickers() < 7) 297 | -- then 298 | -- if not IsAddonVisible("WeeklyBingo") then 299 | -- yield("/callback WeeklyBingo true 2 "..i) 300 | -- yield("/wait 1") 301 | -- end 302 | -- end 303 | end 304 | 305 | yield("/echo Completed all Wonderous Tails entries it is capable of.") -------------------------------------------------------------------------------- /SND Legacy/Dailies/DailyHunts.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | ******************************************************************************** 3 | * Daily Hunts Doer * 4 | ******************************************************************************** 5 | 6 | Created by: pot0to (https://ko-fi.com/pot0to) 7 | 8 | Description: Picks up daily hunts from each expac and attempts to do them. It 9 | will NOT do the weekly Elite hunts. 10 | 11 | THIS CANNOT BE AFK'D FOR THE FOLLOWING REASONS: 12 | 1. The mark area is very large. There is no guarantee you will land within 13 | targetable range of a mark. 14 | 2. If the mark is in a cave, this script will land you on top of the cave but 15 | will not be able to actually find the mark. 16 | 3. The center of the mark area may not be landable, ex. the script may send you 17 | to the bottom of the Sea of Clouds. If this happens, stop the script, 18 | complete the mark manually, then restart the script. 19 | 4. This script cannot do elites. If the script says the next mark to hunt is an 20 | elite, stop the script, complete the mark manually, then restart the script. 21 | 22 | ******************************************************************************** 23 | * Version 1.0.4 * 24 | ******************************************************************************** 25 | 1.0.4 Fixed NavIsReady check 26 | 1.0.2 Fixed 3-star hunt pickups 27 | Fixed n+1 hunt requirement 28 | 29 | ******************************************************************************** 30 | * Required Plugins * 31 | ******************************************************************************** 32 | 33 | 1. Hunt Buddy 34 | 2. Rotation Solver Reborn 35 | 3. BossModReborn (BMR) 36 | 37 | ******************************************************************************** 38 | * Settings * 39 | ******************************************************************************** 40 | ]] 41 | 42 | ShouldPickUpHunts = true -- Set to false if you want it to start doing the 43 | -- hunt bills you already have 44 | 45 | --[[ 46 | ******************************************************************************** 47 | * Code: Don't touch this unless you know what you're doing * 48 | ******************************************************************************** 49 | ]] 50 | 51 | 52 | HuntBoards = 53 | { 54 | { 55 | city = "Ishgard", 56 | zoneId = 418, 57 | aetheryte = "Foundation", 58 | miniAethernet = { 59 | name = "Forgotten Knight", 60 | x=45, y=24, z=0 61 | }, 62 | boardName = "Clan Hunt Board", 63 | bills = { 2001700, 2001701, 2001702 }, 64 | x=73, y=24, z=22, 65 | }, 66 | { 67 | city = "Kugane", 68 | zoneId = 628, 69 | aetheryte = "Kugane", 70 | boardName = "Clan Hunt Board", 71 | bills = { 2002113, 2002114, 2002115 }, 72 | x=-32, y=0, z=-44 73 | }, 74 | { 75 | city = "Crystarium", 76 | zoneId = 819, 77 | aetheryte = "The Crystarium", 78 | miniAethernet = { 79 | name = "Temenos Rookery", 80 | x=-108, y=-1, z=-59 81 | }, 82 | boardName = "Nuts Board", 83 | bills = { 2002628, 2002629, 2002630 }, 84 | x=-84, y=-1, z=-91 85 | }, 86 | { 87 | city = "Old Sharlayan", 88 | zoneId = 962, 89 | aetheryte = "Old Sharlayan", 90 | miniAethernet = { 91 | name = "Scholar's Harbor", 92 | x=16, y=-17, z=127 93 | }, 94 | boardName = "Guildship Hunt Board", 95 | bills = { 2003090, 2003091, 2003092 }, 96 | x=29, y=-16, z=98 97 | }, 98 | { 99 | city = "Tuliyollal", 100 | zoneId = 1185, 101 | aetheryte = "Tuliyollal", 102 | miniAethernet = { 103 | name = "Bayside Bevy Marketplace", 104 | x=-15, y=-11, z=135 105 | }, 106 | boardName = "Hunt Board", 107 | bills = { 2003510, 2003511, 2003512 }, 108 | x=25, y=-15, z=135 109 | } 110 | } 111 | 112 | -- #region Movement 113 | 114 | function TeleportTo(aetheryteName) 115 | yield("/tp "..aetheryteName) 116 | yield("/wait 1") -- wait for casting to begin 117 | while GetCharacterCondition(CharacterCondition.casting) do 118 | LogInfo("[DailyHunts] Casting teleport...") 119 | yield("/wait 1") 120 | end 121 | yield("/wait 3") -- wait for that microsecond in between the cast finishing and the transition beginning 122 | while GetCharacterCondition(CharacterCondition.betweenAreas) do 123 | LogInfo("[DailyHunts] Teleporting...") 124 | yield("/wait 1") 125 | end 126 | yield("/wait 1") 127 | LastStuckCheckTime = os.clock() 128 | LastStuckCheckPosition = {x=GetPlayerRawXPos(), y=GetPlayerRawYPos(), z=GetPlayerRawZPos()} 129 | end 130 | 131 | function GetClosestAetheryte(x, y, z, zoneId, teleportTimePenalty) 132 | local closestAetheryte = nil 133 | local closestTravelDistance = math.maxinteger 134 | local aetheryteIds = GetAetherytesInZone(zoneId) 135 | for i=0, aetheryteIds.Count-1 do 136 | local aetheryteCoords = GetAetheryteRawPos(aetheryteIds[i]) 137 | local aetheryte = 138 | { 139 | aetheryteId = aetheryteIds[i], 140 | aetheryteName = GetAetheryteName(aetheryteIds[i]), 141 | x = aetheryteCoords.Item1, 142 | z = aetheryteCoords.Item2 143 | } 144 | 145 | local distanceAetheryteToFate = DistanceBetween(aetheryte.x, y, aetheryte.z, x, y, z) 146 | local comparisonDistance = distanceAetheryteToFate + teleportTimePenalty 147 | -- LogInfo("[DailyHunts] Distance via aetheryte #"..aetheryte.aetheryteId.." adjusted for tp penalty is "..tostring(comparisonDistance)) 148 | -- LogInfo("[DailyHunts] AetheryteX: "..aetheryte.x..", AetheryteZ: "..aetheryte.z) 149 | 150 | if comparisonDistance < closestTravelDistance then 151 | -- LogInfo("[DailyHunts] Updating closest aetheryte to #"..aetheryte.aetheryteId) 152 | closestTravelDistance = comparisonDistance 153 | closestAetheryte = aetheryte 154 | end 155 | end 156 | 157 | return closestAetheryte 158 | end 159 | 160 | function RandomAdjustCoordinates(x, y, z, maxDistance) 161 | local angle = math.random() * 2 * math.pi 162 | local x_adjust = maxDistance * math.random() 163 | local z_adjust = maxDistance * math.random() 164 | 165 | local randomX = x + (x_adjust * math.cos(angle)) 166 | local randomY = y + maxDistance 167 | local randomZ = z + (z_adjust * math.sin(angle)) 168 | 169 | return randomX, randomY, randomZ 170 | end 171 | 172 | function Mount() 173 | if GetCharacterCondition(CharacterCondition.mounting57) or 174 | GetCharacterCondition(CharacterCondition.mounting64) or 175 | IsPlayerCasting() 176 | then 177 | -- wait 178 | elseif GetCharacterCondition(CharacterCondition.mounted) then 179 | State = CharacterState.goToMarker 180 | LogInfo("[DailyHunts] State Change: GoToMarker") 181 | else 182 | yield('/gaction "mount roulette"') 183 | end 184 | yield("/wait 1") 185 | end 186 | 187 | function Dismount() 188 | if GetCharacterCondition(CharacterCondition.flying) then 189 | yield('/ac dismount') 190 | 191 | local now = os.clock() 192 | if now - LastStuckCheckTime > 1 then 193 | local x = GetPlayerRawXPos() 194 | local y = GetPlayerRawYPos() 195 | local z = GetPlayerRawZPos() 196 | 197 | if GetCharacterCondition(CharacterCondition.flying) and GetDistanceToPoint(LastStuckCheckPosition.x, LastStuckCheckPosition.y, LastStuckCheckPosition.z) < 2 then 198 | LogInfo("[FATE] Unable to dismount here. Moving to another spot.") 199 | local random_x, random_y, random_z = RandomAdjustCoordinates(x, y, z, 10) 200 | local nearestPointX = QueryMeshNearestPointX(random_x, random_y, random_z, 100, 100) 201 | local nearestPointY = QueryMeshNearestPointY(random_x, random_y, random_z, 100, 100) 202 | local nearestPointZ = QueryMeshNearestPointZ(random_x, random_y, random_z, 100, 100) 203 | if nearestPointX ~= nil and nearestPointY ~= nil and nearestPointZ ~= nil then 204 | PathfindAndMoveTo(nearestPointX, nearestPointY, nearestPointZ, GetCharacterCondition(CharacterCondition.flying) and HasFlightUnlocked()) 205 | yield("/wait 1") 206 | end 207 | end 208 | 209 | LastStuckCheckTime = now 210 | LastStuckCheckPosition = {x=x, y=y, z=z} 211 | end 212 | elseif GetCharacterCondition(CharacterCondition.mounted) then 213 | yield('/ac dismount') 214 | end 215 | end 216 | -- #endregion Movement 217 | 218 | -- #region Hunt 219 | 220 | BoardNumber = 1 221 | function GoToHuntBoard() 222 | if BoardNumber > #HuntBoards then 223 | SelectNextHunt() 224 | State = CharacterState.goToMarker 225 | LogInfo("[DailyHunts] State Change: GoToMarker") 226 | return 227 | end 228 | 229 | Board = HuntBoards[BoardNumber] 230 | local skipBoard = true 231 | for _, bill in ipairs(Board.bills) do 232 | if GetItemCount(bill) == 0 then 233 | skipBoard = false 234 | end 235 | end 236 | if not LogInfo("[DailyHunts] Check SkipBoard") and skipBoard then 237 | BoardNumber = BoardNumber + 1 238 | elseif not LogInfo("[DailyHunts] Check ZoneId") and not IsInZone(Board.zoneId) then 239 | TeleportTo(Board.aetheryte) 240 | elseif not LogInfo("[DailyHunts] Check Distance to Board") and Board.miniAethernet ~= nil and GetDistanceToPoint(Board.x, Board.y, Board.z) > (DistanceBetween(Board.miniAethernet.x, Board.miniAethernet.y, Board.miniAethernet.z, Board.x, Board.y, Board.z) + 20) then 241 | LogInfo("[DailyHunts] Distance to board is: "..GetDistanceToPoint(Board.x, Board.y, Board.z)) 242 | LogInfo("[DailyHunts] Distance between board and mini aetheryte: "..DistanceBetween(Board.miniAethernet.x, Board.miniAethernet.y, Board.miniAethernet.z, Board.x, Board.y, Board.z)) 243 | yield("/target aetheryte") 244 | yield("/wait 0.5") 245 | if GetDistanceToTarget() > 7 then 246 | PathMoveTo(GetTargetRawXPos(), GetTargetRawYPos(), GetTargetRawZPos()) 247 | else 248 | if PathfindInProgress() or PathIsRunning() then 249 | yield("/vnav stop") 250 | end 251 | yield("/li "..Board.miniAethernet.name) 252 | yield("/wait 5") 253 | end 254 | elseif IsAddonVisible("TelepotTown") then 255 | yield("/callback TelepotTown true -1") 256 | elseif GetDistanceToPoint(Board.x, Board.y, Board.z) > 3 then 257 | if not PathIsRunning() and not PathfindInProgress() then 258 | PathfindAndMoveTo(Board.x, Board.y, Board.z) 259 | end 260 | else 261 | if PathIsRunning() or PathfindInProgress() then 262 | yield("/vnav stop") 263 | else 264 | BoardNumber = BoardNumber + 1 265 | State = CharacterState.pickUpHunts 266 | LogInfo("[DailyHunts] State Change: PickUpHunts") 267 | end 268 | end 269 | end 270 | 271 | HuntNumber = 0 272 | function PickUpHunts() 273 | if HuntNumber >= #Board.bills then 274 | if IsAddonVisible("Mobhunt"..BoardNumber) then 275 | yield("/callback Mobhunt"..BoardNumber.." true -1") 276 | else 277 | HuntNumber = 0 278 | State = CharacterState.goToHuntBoard 279 | LogInfo("[DailyHunts] State Change: GoToHuntBoard "..BoardNumber) 280 | end 281 | elseif GetItemCount(Board.bills[HuntNumber+1]) >= 1 then 282 | HuntNumber = HuntNumber + 1 283 | elseif IsAddonVisible("SelectYesno") and GetNodeText("SelectYesno", 15) == "Pursuing a new mark will result in the abandonment of your current one. Proceed?" then 284 | yield("/callback SelectYesno true 1") 285 | HuntNumber = HuntNumber + 1 286 | elseif IsAddonVisible("SelectString") then 287 | local callback = "/callback SelectString true "..HuntNumber 288 | LogInfo("[DailyHunts] Executing ".."/callback SelectString true "..HuntNumber) 289 | yield(callback) 290 | elseif IsAddonVisible("Mobhunt"..BoardNumber) then 291 | local callback = "/callback Mobhunt"..BoardNumber.." true 0" 292 | LogInfo("[DailyHunts] Executing "..callback) 293 | yield(callback) 294 | HuntNumber = HuntNumber + 1 295 | elseif not HasTarget() or GetTargetName() ~= Board.boardName then 296 | yield("/target "..Board.boardName) 297 | else 298 | yield("/interact") 299 | end 300 | end 301 | 302 | function ParseHuntChat() -- Pattern to match the quantity and item name 303 | local chat = GetNodeText("ChatLogPanel_3", 7, 2) 304 | LogInfo("[DailyHunts] "..chat) 305 | -- Pattern to match the quantity, item name, and location 306 | local huntingPattern = "Hunting (%d+)x ([%w%s%-'–]+) in ([%w%s%-'–]+)" 307 | local slainPattern = "Hunt mark ([%w%s%-'–]+) slain! %((%d+)/(%d+)%)" 308 | 309 | -- Find all matches and store them in a table 310 | local hunt = nil 311 | for line in chat:gmatch("[^\r\n]+") do 312 | LogInfo("[DailyHunts] Parsing Chat: "..line) 313 | for quantity, markName, location in line:gmatch(huntingPattern) do 314 | quantity = tonumber(quantity) 315 | markName = markName:lower() 316 | LogInfo("[DailyHunts] Found hunt: "..markName) 317 | 318 | hunt = {quantity = tonumber(quantity), name = markName, location = location} 319 | end 320 | if hunt ~= nil then 321 | for markName, slain, goal in line:gmatch(slainPattern) do 322 | markName = markName:lower() 323 | LogInfo("[DailyHunts] Found slain mark "..markName) 324 | if hunt.name == markName and slain == goal then 325 | LogInfo("[DailyHunts] Hunt mark complete. Setting hunt to nil") 326 | hunt = nil 327 | end 328 | end 329 | end 330 | if string.find(line, "elite") ~= nil then 331 | LogInfo("[DailyHunts] line is elite") 332 | hunt = nil 333 | end 334 | end 335 | 336 | return hunt 337 | end 338 | 339 | function SelectNextHunt() 340 | LogInfo("[DailyHunts] Selecting Next Hunt") 341 | yield("/wait 1") 342 | Hunt = nil 343 | while Hunt == nil or Hunt.name:sub(1, 5):lower() == "elite" do 344 | yield("/phb next") 345 | yield("/wait 1") 346 | Hunt = ParseHuntChat() 347 | end 348 | end 349 | 350 | function GoToDravanianHinterlands() 351 | if IsInZone(478) then 352 | if not GetCharacterCondition(CharacterCondition.mounted) then 353 | State = CharacterState.mounting 354 | LogInfo("[DailyHunts] State Change: Mounting") 355 | else 356 | PathfindAndMoveTo(148.51, 207.0, 118.47) 357 | while PathfindInProgress() or PathIsRunning() do 358 | yield("/wait 3") 359 | end 360 | while GetCharacterCondition(CharacterCondition.betweenAreas) do 361 | yield("/wait 1") 362 | end 363 | yield("/wait 1") 364 | end 365 | else 366 | TeleportTo("Idyllshire") 367 | end 368 | end 369 | 370 | function GoToMarker() 371 | local teleportTimePenalty = 50 372 | 373 | local flagZone = GetFlagZone() 374 | local x = GetFlagXCoord() 375 | local z = GetFlagYCoord() 376 | local closestAetheryte = GetClosestAetheryte(x, 0, z, flagZone, teleportTimePenalty) 377 | -- LogInfo("[DailyHunts] Closest aetheryte is "..closestAetheryte.aetheryteName) 378 | 379 | if not IsInZone(flagZone) then 380 | if flagZone == 399 then 381 | GoToDravanianHinterlands() 382 | else 383 | TeleportTo(closestAetheryte.aetheryteName) 384 | end 385 | return 386 | end 387 | 388 | local y = GetPlayerRawYPos() 389 | local directFlightDistance = GetDistanceToPoint(x, y, z) 390 | -- LogInfo("[DailyHunts] Direct flight distance is "..directFlightDistance) 391 | 392 | if closestAetheryte ~= nil and DistanceBetween(closestAetheryte.x, y, closestAetheryte.z, x, y, z) + teleportTimePenalty < directFlightDistance then 393 | TeleportTo(closestAetheryte.aetheryteName) 394 | elseif GetDistanceToPoint(x, GetPlayerRawYPos(), z) > 15 then 395 | if not GetCharacterCondition(CharacterCondition.mounted) then 396 | State = CharacterState.mounting 397 | LogInfo("[DailyHunts] State Change: Mounting") 398 | elseif not PathIsRunning() and not PathfindInProgress() then 399 | -- PathfindAndMoveTo(x, y, z, true) 400 | yield("/wait 0.5") 401 | yield("/vnav flyflag") 402 | end 403 | else 404 | if GetCharacterCondition(CharacterCondition.mounted) then 405 | Dismount() 406 | elseif PathIsRunning() or PathfindInProgress() then 407 | yield("/vnav stop") 408 | else 409 | State = CharacterState.doHunt 410 | LogInfo("[DailyHunts] State Change: DoHunt") 411 | end 412 | end 413 | end 414 | 415 | DidHunt = false 416 | CombatModsOn = false 417 | LastTargetName = nil 418 | function DoHunt() 419 | if IsPlayerCasting() then 420 | yield("/wait 1") 421 | return 422 | elseif not IsInZone(GetFlagZone()) or GetDistanceToPoint(GetFlagXCoord(), GetPlayerRawYPos(), GetFlagYCoord()) > 200 then 423 | if GetCharacterCondition(CharacterCondition.inCombat) then 424 | if not HasTarget() then 425 | yield("/battletarget") 426 | end 427 | else 428 | State = CharacterState.goToMarker 429 | LogInfo("[DailyHunts] State Change: GoToMarker") 430 | end 431 | return 432 | elseif not HasTarget() or GetTargetHP() <= 0 then 433 | SelectNextHunt() 434 | local targetingCommand = "/target "..Hunt.name 435 | LogInfo("[DailyHunts] Executing "..targetingCommand) 436 | yield(targetingCommand) 437 | yield("/wait 0.5") 438 | return 439 | end 440 | 441 | if not CombatModsOn then 442 | yield("/bmrai followtarget on") 443 | yield("/bmrai followcombat on") 444 | yield("/rotation manual") 445 | CombatModsOn = true 446 | end 447 | 448 | if GetCharacterCondition(CharacterCondition.inCombat) then 449 | DidHunt = true 450 | if PathfindInProgress() or PathIsRunning() then 451 | yield("/vnav stop") 452 | end 453 | return 454 | elseif GetDistanceToTarget() > 5 + GetTargetHitboxRadius() then 455 | if not PathfindInProgress() and not PathIsRunning() then 456 | PathfindAndMoveTo(GetTargetRawXPos(), GetTargetRawYPos(), GetTargetRawZPos()) 457 | end 458 | return 459 | end 460 | end 461 | 462 | -- #endregion Hunt 463 | 464 | CharacterState = 465 | { 466 | goToMarker = GoToMarker, 467 | mounting = Mount, 468 | doHunt = DoHunt, 469 | goToHuntBoard = GoToHuntBoard, 470 | pickUpHunts = PickUpHunts 471 | } 472 | 473 | CharacterCondition = { 474 | dead=2, 475 | mounted=4, 476 | inCombat=26, 477 | casting=27, 478 | occupiedInEvent=31, 479 | occupiedInQuestEvent=32, 480 | occupied=33, 481 | boundByDuty34=34, 482 | occupiedMateriaExtractionAndRepair=39, 483 | betweenAreas=45, 484 | jumping48=48, 485 | jumping61=61, 486 | occupiedSummoningBell=50, 487 | betweenAreasForDuty=51, 488 | boundByDuty56=56, 489 | mounting57=57, 490 | mounting64=64, 491 | beingMoved=70, 492 | flying=77 493 | } 494 | 495 | LastStuckCheckTime = os.clock() 496 | LastStuckCheckPosition = {x=GetPlayerRawXPos(), y=GetPlayerRawYPos(), z=GetPlayerRawZPos()} 497 | 498 | if ShouldPickUpHunts then 499 | State = CharacterState.goToHuntBoard 500 | else 501 | SelectNextHunt() 502 | State = CharacterState.goToMarker 503 | end 504 | while true do 505 | if NavIsReady() and not (GetCharacterCondition(CharacterCondition.betweenAreas) or 506 | GetCharacterCondition(CharacterCondition.beingMoved) or 507 | GetCharacterCondition(CharacterCondition.occupiedMateriaExtractionAndRepair) or 508 | LifestreamIsBusy()) 509 | then 510 | State() 511 | yield("/wait 0.1") 512 | else 513 | yield("/wait 1") 514 | end 515 | end --------------------------------------------------------------------------------