├── .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 | 
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 | 
38 |
39 | ### RSR Settings
40 | | | |
41 | |--|--|
42 | |  | Select "All Targets that are in range for any abilities (Tanks/Autoduty)" regardless of whether you're a tank |
43 | |  | Add "Forlorn Maiden" and "The Forlorn" to Prio Targets |
44 | |  | 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 | 
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
--------------------------------------------------------------------------------