GearSwap V0.927 - Inventory Handling Changes

Eorzea Time
 
 
 
Language: JP EN FR DE
Version 3.1
New Items
users online
Forum » Windower » General » GearSwap v0.927 - Inventory handling changes
GearSwap v0.927 - Inventory handling changes
First Page 2
 Lakshmi.Byrth
VIP
Offline
Server: Lakshmi
Game: FFXI
user: Byrthnoth
Posts: 6137
By Lakshmi.Byrth 2017-02-26 01:58:27
Link | Quote | Reply
 
I've been playing around with GearSwap on -dev and I've made some changes that I think improve its reliability somewhat. I'd like people to help me test it before it goes live, but we get ~zero feedback from -dev users at the moment (if there are any others), so I'm posting here to ask people to try it out.

Instructions:
Click this link and then the subsequent download link.

Copy the files from the .zip into the windower/addons/GearSwap/ folder and replace the ones that are there.

Report back if you notice your equipment not swapping, ABA issues, etc.

If you need to go back, here is the current -live version of GearSwap.



What changed:
GearSwap injects equipment packets faster than the server responds to them, so it has to maintain essentially two sets of equipment:
1) The equipment that the server has reported is currently being worn. (equip packets from the server)
2) The equipment that the addon *thinks* is being worn. (equip packets it has injected)
Previously, I made some approximations to more or less merge these two structures, which worked most of the time but probably failed some of the time. In v0.927, I've made it so I keep track of the equipment most recently reported by the server for each slot (#1), but I also keep track of the most recently injected packets for each slot (~#2). For most of what GearSwap does, I superimpose #2 onto #1 and use that. I've also taken some steps to make the equip code in GearSwap a bit faster/lighter, not that anyone was really complaining about it.
[+]
 Lakshmi.Byrth
VIP
Offline
Server: Lakshmi
Game: FFXI
user: Byrthnoth
Posts: 6137
By Lakshmi.Byrth 2017-02-26 02:01:54
Link | Quote | Reply
 
Oh yeah, I also made it so the equipset command will display it's normal " Failed to equip" messages when it fails. There is no harm to it and it will let people figure out when they have impossible swaps in their files.
[+]
 Lakshmi.Byrth
VIP
Offline
Server: Lakshmi
Game: FFXI
user: Byrthnoth
Posts: 6137
By Lakshmi.Byrth 2017-02-26 07:31:15
Link | Quote | Reply
 
I'm looking to find out whether it works in a very general sense. As long as you're not noticing it fail, it's probably an improvement over the current -live version. Instanced zones like Omen are particularly suspect. It's hard for me to force a condition where packets are being dropped, but I think the current version should deal with it about as well as it can be dealt with.

It's hard to tell whether or not gearswap works, but I find there are two places where I can tell:
1) If I'm using a JA like Reverse Flourish or something that has one effect if the swap worked and another if it didn't
2) If I end up not wearing the appropriate idle gear.
 Leviathan.Comeatmebro
Offline
Server: Leviathan
Game: FFXI
user: Rairin
Posts: 6052
By Leviathan.Comeatmebro 2017-02-26 08:03:33
Link | Quote | Reply
 
Don't know if it helps at all or this is how you're already doing it, but for ashitacast I keep a table of most recent injected equip for each slot and the time it was injected. If it was less than 2 seconds ago, I use the value from the table, otherwise I use the value from the most recent confirmed packet.
 Lakshmi.Byrth
VIP
Offline
Server: Lakshmi
Game: FFXI
user: Byrthnoth
Posts: 6137
By Lakshmi.Byrth 2017-02-26 08:17:20
Link | Quote | Reply
 
That's more or less what I'm doing now. I don't have a timeout, because I didn't think the server would ever get back to me if a packet was dropped. Client -> Server communication seems to be much more reliable than server -> client, at least for me.
 Leviathan.Comeatmebro
Offline
Server: Leviathan
Game: FFXI
user: Rairin
Posts: 6052
By Leviathan.Comeatmebro 2017-02-26 10:32:28
Link | Quote | Reply
 
In my case, I use the timeout to cover cases like encumbrance or job changes. Since there's likely been no swap in 2 seconds, it immediately trusts the incoming packet.
Offline
Posts: 182
By Sammeh 2017-02-26 10:36:03
Link | Quote | Reply
 
One note, one question:

1) I installed this AM - haven't had issues yet; will do 2x omen tonight and let you know again.

2) I'm trying to track (external LUA) a gearswap for pre-cast for Bard.
Code
windower.register_event('outgoing chunk',function(id,data,modified,injected,blocked)
	if id == 0x01A then
		--local packet = packets.parse('outgoing', data)
		local packet = packets.parse('outgoing', modified)
		local self = windower.ffxi.get_player()
		local ability_used = packet.Param
		local category = packet.Category
		if res.job_abilities[ability_used] then 
			if res.job_abilities[ability_used].id == 164 and category == 9 then
				local gear = windower.ffxi.get_items()
				local body = res.items[windower.ffxi.get_items(gear.equipment.body_bag, gear.equipment.body).id]
				if body.en == "Bihu Justaucorps" or body.en == "Bihu Jstcorps +1" then 
					troubMeritGain = self.merits.troubadour * 4 
				end
				print("Adding Buff Gain",troubMeritGain,body.en)
			end
		end
	end
end)


Basically was hoping to Capture if Bihu Justaucorps was equipped when the outgoing packet for Troubadour actually went off. However windower.ffxi.get_items() doesn't seem to be updating as quick as you inject it / go to after-cast.

Any pointers?

The gist being. Bihu Justaucorps pre-cast Troubadour adds the extra 4 seconds per-Merit however is only needed when the JA goes off - not when the spell goes off. So just trying to track and lock a variable with whether or not it was equipped when the JA went off.

-Sammeh
 Lakshmi.Byrth
VIP
Offline
Server: Lakshmi
Game: FFXI
user: Byrthnoth
Posts: 6137
By Lakshmi.Byrth 2017-02-26 10:44:19
Link | Quote | Reply
 
#2 is the problem I'm describing. GearSwap can only solve that problem inside GearSwap, but you could just make it a gearswap include and use player.equipment, which should get updated.
Code
windower.raw_register_event('outgoing chunk',function(id,data,modified,injected,blocked) -- in GearSwap, raw_register event doesn't trigger memory-intensive update functions
    if id == 0x01A then
        --local packet = packets.parse('outgoing', data)
        local packet = packets.parse('outgoing', modified)
        local self = windower.ffxi.get_player()
        local ability_used = packet.Param
        local category = packet.Category
        if res.job_abilities[ability_used] then 
            if res.job_abilities[ability_used].id == 164 and category == 9 then
                gearswap.refresh_player() -- This refreshes player.equipment, which is all you need
                if player.body == "Bihu Justaucorps" or body.en == "Bihu Jstcorps +1" then 
                    troubMeritGain = self.merits.troubadour * 4 
                end
                print("Adding Buff Gain",troubMeritGain,body.en)
            end
        end
    end
end)


Leviathan.Comeatmebro said: »
In my case, I use the timeout to cover cases like encumbrance or job changes. Since there's likely been no swap in 2 seconds, it immediately trusts the incoming packet.

This is a good idea and I'll likely have to do it before it goes live. I don't think it'll make a huge difference for people who are testing the -dev version right now, but I can see how it's an improvement.
Offline
Posts: 182
By Sammeh 2017-02-26 12:22:09
Link | Quote | Reply
 
Lakshmi.Byrth said: »
#2 is the problem I'm describing. GearSwap can only solve that problem inside GearSwap, but you could just make it a gearswap include and use player.equipment, which should get updated.
Unfortunately this didn't work.

Precast is indeed swapping in the gear. However I can't get it to print as such:
Code
windower.raw_register_event('outgoing chunk',function(id,data,modified,injected,blocked) 
    if id == 0x01A then
        local packet = packets.parse('outgoing', data)
        local self = windower.ffxi.get_player()
        local ability_used = packet.Param
        local category = packet.Category
        if res.job_abilities[ability_used] then 
            if res.job_abilities[ability_used].id == 164 and category == 9 then
				troubMeritGain = 0
                gearswap.refresh_player() -- This refreshes player.equipment, which is all you need
                if player.equipment.body == "Bihu Justaucorps" or player.equipment.body == "Bihu Jstcorps +1" then 
                    troubMeritGain = self.merits.troubadour * 4 
                end
                print("Adding Buff Gain",troubMeritGain,player.equipment.body)
            end
        end
    end
end)



Always printing my idle piece. With that said - I think I'm just going to work around it. I'll follow up more in bard forums - I don't want to derail your OP - sorry to hijack thread.
Offline
Posts: 182
By Sammeh 2017-02-26 12:44:34
Link | Quote | Reply
 
Well..

Nevermind - was able to track it via the incoming 0x28.
Code
if packet['Category'] == 6 and packet.Actor == self.id then
			local gear = windower.ffxi.get_items()
			local body = res.items[windower.ffxi.get_items(gear.equipment.body_bag, gear.equipment.body).id]
			print(body.en)
		end
		
 Asura.Hopefulki
Offline
Server: Asura
Game: FFXI
user: hopefulki
Posts: 21
By Asura.Hopefulki 2017-02-26 14:07:04
Link | Quote | Reply
 
Using the new GS, my bard gearswap no longer swaps midcast weapons or ranged. It also does not recognize the dummy song variable and does not swap in daur.

My GS uses mote's as a base with added variables for duration, accuracy for buffs and debuffs. It also incorporates a lullaby timer I found on these forums (forgot who posted it, but thanks!)

On my phone, but reported this on github and can post Lua later if desired
Offline
Posts: 182
By Sammeh 2017-02-26 15:07:26
Link | Quote | Reply
 
Asura.Hopefulki said: »
Using the new GS, my bard gearswap no longer swaps midcast weapons or ranged. It also does not recognize the dummy song variable and does not swap in daur.

My GS uses mote's as a base with added variables for duration, accuracy for buffs and debuffs. It also incorporates a lullaby timer I found on these forums (forgot who posted it, but thanks!)

On my phone, but reported this on github and can post Lua later if desired

Just went through a long debugging session while trying to customize my bard lullaby contributions. Had zero issues swapping in. Would be curious to know more.
 Asura.Hopefulki
Offline
Server: Asura
Game: FFXI
user: hopefulki
Posts: 21
By Asura.Hopefulki 2017-02-26 15:54:17
Link | Quote | Reply
 
I'll post debug logs after I get home tonight or at the latest tomorrow morning.

I can tell you that my initial debugging stated that midcast was equipping but, for example, carn was not equipping. It did not show up as gear not equipped either. Spell went off with all midcast gear but precast dagger.
 Fenrir.Divinian
Offline
Server: Fenrir
Game: FFXI
user: Divinian
Posts: 354
By Fenrir.Divinian 2017-02-26 20:41:18
Link | Quote | Reply
 
Hi Byrth. I've been using the new code since this AM and have run into no issues at all. I write my code carefully (but often redundantly), so I feel like errors people might be getting are simply just errors in their own code or possibly errors in the oft outdated code written by Motenten. I do not use Mote's luas, but have incorporated some of the code into my thf.lua for example for swapping out TH to reg. gear.

Hope this is helpful to you. Thanks for gearswap and keeping it fresh. Peace.
[+]
 Odin.Cnile
Offline
Server: Odin
Game: FFXI
user: cnile
Posts: 7
By Odin.Cnile 2017-02-27 02:36:00
Link | Quote | Reply
 
For the life of me I cannot get precast to change to midcast for this. any help, much appreciated.

Code
-- *** Credit goes to Flippant for helping me with Gearswap *** --
-- ** I Use Some of Motenten's Functions ** --

function get_sets()
	AccIndex = 1
	AccArray = {"LowACC","MidACC","HighACC"} -- 3 Levels Of Accuracy Sets For Shooting/TP/WS. First Set Is LowACC. Add More ACC Sets If Needed Then Create Your New ACC Below. Most of These Sets Are Empty So You Need To Edit Them On Your Own. Remember To Check What The Combined Set Is For Each Sets. --
	WeaponIndex = 1
	WeaponArray = {"Annihilator","Yoichinoyumi"} -- Default Ranged Weapon Is Annihilator. Can Delete Any Weapons/Sets That You Don't Need Or Replace/Add The New Weapons That You Want To Use. --
	IdleIndex = 1
	IdleArray = {"Movement","Regen"} -- Default Idle Set Is Movement --
	Armor = 'None'
	warning = false
	AutoGunWS = "LastStand" -- Set Auto Gun WS Here --
	AutoBowWS = "Namas Arrow" -- Set Auto Bow WS Here --
	AutoMode = 'On' --Set Default Auto RA/WS ON or OFF Here --
	Attack = 'On' -- Set Default WS Attack Set ON or OFF Here --
	Enmity = 'OFF' -- Set Default Enmity Set ON or OFF Here --
	ammo_warning_limit = 10 -- Set Ammo Limit Check Here --
	Samurai_Roll = 'ON' -- Set Default SAM Roll ON or OFF Here --
	target_distance = 25 -- Set Default Distance Here --
	select_default_macro_book() -- Change Default Macro Book At The End --

	sc_map = {SC1="LastStand", SC2="Coronach", SC3="Ranged"} -- 3 Additional Binds. Can Change Whatever JA/WS/Spells You Like Here. Remember Not To Use Spaces. --

	sets.Idle = {}
	-- Idle/Town Sets --
	sets.Idle.Regen = {}
	sets.Idle.Regen.Annihilator = set_combine(sets.Idle.Regen,{
			main="Oneiros Knife",
			sub="Moogle Guard +1",
			range="Annihilator",
			ammo="Achiyal. Bullet"})
	sets.Idle.Regen.Annihilator.NIN = set_combine(sets.Idle.Regen,{
			main="Hurlbat",
			sub="Courser's Pugio",
			range="Annihilator",
			ammo="Achiyal. Bullet"})

	sets.Idle.Movement = set_combine(sets.Idle.Regen,{})
	sets.Idle.Movement.Annihilator = set_combine(sets.Idle.Movement,{
			range="Annihilator",
			ammo="Achiyal. Bullet"})
	sets.Idle.Movement.Yoichinoyumi = set_combine(sets.Idle.Movement,{
			range="Yoichinoyumi",
			ammo="Achiyal. Arrow"})
	sets.Idle.Movement.Annihilator.NIN = set_combine(sets.Idle.Movement,{
			main="Hurlbat",
			sub="Courser's Pugio",
			range="Annihilator",
			ammo="Achiyal. Bullet"})

	-- Preshot --
	sets.Preshot = {
			head="Amini Gapette +1",
			body="Amini Caban +1",
			hands="Carmine Fin. Ga.",
			back="Lutian Cape",
			waist="Impulse Belt",
			legs="Adhemar Kecks",
			feet="Adhemar gamashes",
			left_ring="Rajas Ring",
			right_ring="Petrov Ring",
			left_ear="Enervating Earring",
			right_ear="Volley earring",
			neck="Ocachi gorget",}

	-- Barrage Base Set. This Set Takes Priority Over Other Pieces. --
	Barrage = {
			hands="Orion Bracers +1",
			legs="Desultor Tassets"}

	-- Shooting Base Set --
	sets.Midshot = {}

	-- Annihilator(Decoy Down) Sets --
	sets.Midshot.Annihilator = {
			range="Annihilator",
			ammo="Eminent bullet"}
	sets.Midshot.Annihilator.MidACC = set_combine(sets.Midshot.Annihilator,{})
	sets.Midshot.Annihilator.HighACC = set_combine(sets.Midshot.Annihilator.MidACC,{})

	-- Annihilator(Decoy Up) Sets --
	sets.Midshot.Annihilator.Decoy = set_combine(sets.Midshot.Annihilator,{})
	sets.Midshot.Annihilator.MidACC.Decoy = set_combine(sets.Midshot.Annihilator.MidACC,{})
	sets.Midshot.Annihilator.HighACC.Decoy = set_combine(sets.Midshot.Annihilator.HighACC,{})

	-- Annihilator(Enmity) Sets --
	sets.Midshot.Annihilator.Enmity = set_combine(sets.Midshot.Annihilator,{})
	sets.Midshot.Annihilator.MidACC.Enmity = set_combine(sets.Midshot.Annihilator.MidACC,{})
	sets.Midshot.Annihilator.HighACC.Enmity = set_combine(sets.Midshot.Annihilator.HighACC,{})

	-- Annihilator(AM) Sets --
	sets.Midshot.Annihilator.AM = set_combine(sets.Midshot.Annihilator,{})
	sets.Midshot.Annihilator.MidACC.AM = set_combine(sets.Midshot.Annihilator.MidACC,{})
	sets.Midshot.Annihilator.HighACC.AM = set_combine(sets.Midshot.Annihilator.HighACC,{})

	-- Annihilator(AM: Ionis) Sets --
	sets.Midshot.Annihilator.AM.Ionis = set_combine(sets.Midshot.Annihilator,{})
	sets.Midshot.Annihilator.MidACC.AM.Ionis = set_combine(sets.Midshot.Annihilator.MidACC,{})
	sets.Midshot.Annihilator.HighACC.AM.Ionis = set_combine(sets.Midshot.Annihilator.HighACC,{})

	-- Annihilator(Decoy Down: Ionis) Sets --
	sets.Midshot.Annihilator.Ionis = set_combine(sets.Midshot.Annihilator,{})
	sets.Midshot.Annihilator.MidACC.Ionis = set_combine(sets.Midshot.Annihilator.MidACC,{})
	sets.Midshot.Annihilator.HighACC.Ionis = set_combine(sets.Midshot.Annihilator.HighACC,{})

	-- Annihilator(Decoy Up: Ionis) Sets --
	sets.Midshot.Annihilator.Decoy.Ionis = set_combine(sets.Midshot.Annihilator,{})
	sets.Midshot.Annihilator.MidACC.Decoy.Ionis = set_combine(sets.Midshot.Annihilator.MidACC,{})
	sets.Midshot.Annihilator.HighACC.Decoy.Ionis = set_combine(sets.Midshot.Annihilator.HighACC,{})

	-- Annihilator(Decoy Down: SAM Roll) Sets --
	sets.Midshot.Annihilator.STP = set_combine(sets.Midshot.Annihilator,{})
	sets.Midshot.Annihilator.MidACC.STP = set_combine(sets.Midshot.Annihilator.MidACC,{})
	sets.Midshot.Annihilator.HighACC.STP = set_combine(sets.Midshot.Annihilator.HighACC,{})

	-- Annihilator(Decoy Up: SAM Roll) Sets --
	sets.Midshot.Annihilator.Decoy.STP = set_combine(sets.Midshot.Annihilator,{})
	sets.Midshot.Annihilator.MidACC.Decoy.STP = set_combine(sets.Midshot.Annihilator.MidACC,{})
	sets.Midshot.Annihilator.HighACC.Decoy.STP = set_combine(sets.Midshot.Annihilator.HighACC,{})

	-- Annihilator(Decoy Down: Ionis + SAM Roll) Sets --
	sets.Midshot.Annihilator.Ionis.STP = set_combine(sets.Midshot.Annihilator,{})
	sets.Midshot.Annihilator.MidACC.Ionis.STP = set_combine(sets.Midshot.Annihilator.MidACC,{})
	sets.Midshot.Annihilator.HighACC.Ionis.STP = set_combine(sets.Midshot.Annihilator.HighACC,{})

	-- Annihilator(Decoy Up: Ionis + SAM Roll) Sets --
	sets.Midshot.Annihilator.Decoy.Ionis.STP = set_combine(sets.Midshot.Annihilator,{})
	sets.Midshot.Annihilator.MidACC.Decoy.Ionis.STP = set_combine(sets.Midshot.Annihilator.MidACC,{})
	sets.Midshot.Annihilator.HighACC.Decoy.Ionis.STP = set_combine(sets.Midshot.Annihilator.HighACC,{})

	-- Annihilator Barrage Sets --
	sets.Midshot.Annihilator.Barrage = set_combine(sets.Midshot.Annihilator,{},Barrage)
	sets.Midshot.Annihilator.MidACC.Barrage = set_combine(sets.Midshot.Annihilator.MidACC,{},Barrage)
	sets.Midshot.Annihilator.HighACC.Barrage = set_combine(sets.Midshot.Annihilator.HighACC,{},Barrage)

	-- Annihilator(Decoy Down) /SAM Sets --
	sets.Midshot.Annihilator.SAM = {
			range="Annihilator",
			ammo="Achiyal. Bullet"}
	sets.Midshot.Annihilator.SAM.MidACC = set_combine(sets.Midshot.Annihilator.SAM,{})
	sets.Midshot.Annihilator.SAM.HighACC = set_combine(sets.Midshot.Annihilator.SAM.MidACC,{})

	-- Annihilator(Decoy Up) /SAM Sets --
	sets.Midshot.Annihilator.SAM.Decoy = set_combine(sets.Midshot.Annihilator.SAM,{})
	sets.Midshot.Annihilator.SAM.MidACC.Decoy = set_combine(sets.Midshot.Annihilator.SAM.MidACC,{})
	sets.Midshot.Annihilator.SAM.HighACC.Decoy = set_combine(sets.Midshot.Annihilator.SAM.HighACC,{})

	-- Annihilator(Enmity) /SAM Sets --
	sets.Midshot.Annihilator.SAM.Enmity = set_combine(sets.Midshot.Annihilator.SAM,{})
	sets.Midshot.Annihilator.SAM.MidACC.Enmity = set_combine(sets.Midshot.Annihilator.SAM.MidACC,{})
	sets.Midshot.Annihilator.SAM.HighACC.Enmity = set_combine(sets.Midshot.Annihilator.SAM.HighACC,{})

	-- Annihilator(AM) /SAM Sets --
	sets.Midshot.Annihilator.SAM.AM = set_combine(sets.Midshot.Annihilator.SAM,{})
	sets.Midshot.Annihilator.SAM.MidACC.AM = set_combine(sets.Midshot.Annihilator.SAM.MidACC,{})
	sets.Midshot.Annihilator.SAM.HighACC.AM = set_combine(sets.Midshot.Annihilator.SAM.HighACC,{})

	-- Annihilator(AM: Ionis) /SAM Sets --
	sets.Midshot.Annihilator.SAM.AM.Ionis = set_combine(sets.Midshot.Annihilator.SAM,{})
	sets.Midshot.Annihilator.SAM.MidACC.AM.Ionis = set_combine(sets.Midshot.Annihilator.SAM.MidACC,{})
	sets.Midshot.Annihilator.SAM.HighACC.AM.Ionis = set_combine(sets.Midshot.Annihilator.SAM.HighACC,{})

	-- Annihilator(Decoy Down: Ionis) /SAM Sets --
	sets.Midshot.Annihilator.SAM.Ionis = set_combine(sets.Midshot.Annihilator.SAM,{})
	sets.Midshot.Annihilator.SAM.MidACC.Ionis = set_combine(sets.Midshot.Annihilator.SAM.MidACC,{})
	sets.Midshot.Annihilator.SAM.HighACC.Ionis = set_combine(sets.Midshot.Annihilator.SAM.HighACC,{})

	-- Annihilator(Decoy Up: Ionis) /SAM Sets --
	sets.Midshot.Annihilator.SAM.Decoy.Ionis = set_combine(sets.Midshot.Annihilator.SAM,{})
	sets.Midshot.Annihilator.SAM.MidACC.Decoy.Ionis = set_combine(sets.Midshot.Annihilator.SAM.MidACC,{})
	sets.Midshot.Annihilator.SAM.HighACC.Decoy.Ionis = set_combine(sets.Midshot.Annihilator.SAM.HighACC,{})

	-- Annihilator(Decoy Down: SAM Roll) /SAM Sets --
	sets.Midshot.Annihilator.SAM.STP = set_combine(sets.Midshot.Annihilator.SAM,{})
	sets.Midshot.Annihilator.SAM.MidACC.STP = set_combine(sets.Midshot.Annihilator.SAM.MidACC,{})
	sets.Midshot.Annihilator.SAM.HighACC.STP = set_combine(sets.Midshot.Annihilator.SAM.HighACC,{})

	-- Annihilator(Decoy Up: SAM Roll) /SAM Sets --
	sets.Midshot.Annihilator.SAM.Decoy.STP = set_combine(sets.Midshot.Annihilator.SAM,{})
	sets.Midshot.Annihilator.SAM.MidACC.Decoy.STP = set_combine(sets.Midshot.Annihilator.SAM.Decoy.STP,{})
	sets.Midshot.Annihilator.SAM.HighACC.Decoy.STP = set_combine(sets.Midshot.Annihilator.SAM.MidACC.Decoy.STP,{})

	-- Annihilator(Decoy Down: Ionis + SAM Roll) /SAM Sets --
	sets.Midshot.Annihilator.SAM.Ionis.STP = set_combine(sets.Midshot.Annihilator.SAM,{})
	sets.Midshot.Annihilator.SAM.MidACC.Ionis.STP = set_combine(sets.Midshot.Annihilator.SAM.MidACC,{})
	sets.Midshot.Annihilator.SAM.HighACC.Ionis.STP = set_combine(sets.Midshot.Annihilator.SAM.HighACC,{})

	-- Annihilator(Decoy Up: Ionis + SAM Roll) /SAM Sets --
	sets.Midshot.Annihilator.SAM.Decoy.Ionis.STP = set_combine(sets.Midshot.Annihilator.SAM,{})
	sets.Midshot.Annihilator.SAM.MidACC.Decoy.Ionis.STP = set_combine(sets.Midshot.Annihilator.SAM.MidACC,{})
	sets.Midshot.Annihilator.SAM.HighACC.Decoy.Ionis.STP = set_combine(sets.Midshot.Annihilator.SAM.HighACC,{})

	-- Annihilator /SAM Barrage Sets --
	sets.Midshot.Annihilator.SAM.Barrage = set_combine(sets.Midshot.Annihilator.SAM,{},Barrage)
	sets.Midshot.Annihilator.SAM.MidACC.Barrage = set_combine(sets.Midshot.Annihilator.SAM.MidACC,{},Barrage)
	sets.Midshot.Annihilator.SAM.HighACC.Barrage = set_combine(sets.Midshot.Annihilator.SAM.HighACC,{},Barrage)

	-- Annihilator(Decoy Down) /NIN Sets --
	sets.Midshot.Annihilator.NIN = {
			range="Annihilator",
			ammo="Achiyal. Bullet"}
	sets.Midshot.Annihilator.NIN.MidACC = set_combine(sets.Midshot.Annihilator.NIN,{})
	sets.Midshot.Annihilator.NIN.HighACC = set_combine(sets.Midshot.Annihilator.NIN.MidACC,{})

	-- Annihilator(Decoy Up) /NIN Sets --
	sets.Midshot.Annihilator.NIN.Decoy = set_combine(sets.Midshot.Annihilator.NIN,{})
	sets.Midshot.Annihilator.NIN.MidACC.Decoy = set_combine(sets.Midshot.Annihilator.NIN.MidACC,{})
	sets.Midshot.Annihilator.NIN.HighACC.Decoy = set_combine(sets.Midshot.Annihilator.NIN.HighACC,{})

	-- Annihilator(Enmity) /NIN Sets --
	sets.Midshot.Annihilator.NIN.Enmity = set_combine(sets.Midshot.Annihilator.NIN,{})
	sets.Midshot.Annihilator.NIN.MidACC.Enmity = set_combine(sets.Midshot.Annihilator.NIN.MidACC,{})
	sets.Midshot.Annihilator.NIN.HighACC.Enmity = set_combine(sets.Midshot.Annihilator.NIN.HighACC,{})

	-- Annihilator(AM) /NIN Sets --
	sets.Midshot.Annihilator.NIN.AM = set_combine(sets.Midshot.Annihilator.NIN,{})
	sets.Midshot.Annihilator.NIN.MidACC.AM = set_combine(sets.Midshot.Annihilator.NIN.MidACC,{})
	sets.Midshot.Annihilator.NIN.HighACC.AM = set_combine(sets.Midshot.Annihilator.NIN.HighACC,{})

	-- Annihilator(AM: Ionis) /NIN Sets --
	sets.Midshot.Annihilator.NIN.AM.Ionis = set_combine(sets.Midshot.Annihilator.NIN,{})
	sets.Midshot.Annihilator.NIN.MidACC.AM.Ionis = set_combine(sets.Midshot.Annihilator.NIN.MidACC,{})
	sets.Midshot.Annihilator.NIN.HighACC.AM.Ionis = set_combine(sets.Midshot.Annihilator.NIN.HighACC,{})

	-- Annihilator(Decoy Down: Ionis) /NIN Sets --
	sets.Midshot.Annihilator.NIN.Ionis = set_combine(sets.Midshot.Annihilator.NIN,{})
	sets.Midshot.Annihilator.NIN.MidACC.Ionis = set_combine(sets.Midshot.Annihilator.NIN.MidACC,{})
	sets.Midshot.Annihilator.NIN.HighACC.Ionis = set_combine(sets.Midshot.Annihilator.NIN.HighACC,{})

	-- Annihilator(Decoy Up: Ionis) /NIN Sets --
	sets.Midshot.Annihilator.NIN.Decoy.Ionis = set_combine(sets.Midshot.Annihilator.NIN,{})
	sets.Midshot.Annihilator.NIN.MidACC.Decoy.Ionis = set_combine(sets.Midshot.Annihilator.NIN.MidACC,{})
	sets.Midshot.Annihilator.NIN.HighACC.Decoy.Ionis = set_combine(sets.Midshot.Annihilator.NIN.HighACC,{})

	-- Annihilator(Decoy Down: SAM Roll) /NIN Sets --
	sets.Midshot.Annihilator.NIN.STP = set_combine(sets.Midshot.Annihilator.NIN,{})
	sets.Midshot.Annihilator.NIN.MidACC.STP = set_combine(sets.Midshot.Annihilator.NIN.MidACC,{})
	sets.Midshot.Annihilator.NIN.HighACC.STP = set_combine(sets.Midshot.Annihilator.NIN.HighACC,{})

	-- Annihilator(Decoy Up: SAM Roll) /NIN Sets --
	sets.Midshot.Annihilator.NIN.Decoy.STP = set_combine(sets.Midshot.Annihilator.NIN,{})
	sets.Midshot.Annihilator.NIN.MidACC.Decoy.STP = set_combine(sets.Midshot.Annihilator.NIN.MidACC,{})
	sets.Midshot.Annihilator.NIN.HighACC.Decoy.STP = set_combine(sets.Midshot.Annihilator.NIN.HighACC,{})

	-- Annihilator(Decoy Down: Ionis + SAM Roll) /NIN Sets --
	sets.Midshot.Annihilator.NIN.Ionis.STP = set_combine(sets.Midshot.Annihilator.NIN,{})
	sets.Midshot.Annihilator.NIN.MidACC.Ionis.STP = set_combine(sets.Midshot.Annihilator.NIN.MidACC,{})
	sets.Midshot.Annihilator.NIN.HighACC.Ionis.STP = set_combine(sets.Midshot.Annihilator.NIN.HighACC,{})

	-- Annihilator(Decoy Up: Ionis + SAM Roll) /NIN Sets --
	sets.Midshot.Annihilator.NIN.Decoy.Ionis.STP = set_combine(sets.Midshot.Annihilator.NIN,{})
	sets.Midshot.Annihilator.NIN.MidACC.Decoy.Ionis.STP = set_combine(sets.Midshot.Annihilator.NIN.MidACC,{})
	sets.Midshot.Annihilator.NIN.HighACC.Decoy.Ionis.STP = set_combine(sets.Midshot.Annihilator.NIN.HighACC,{})

	-- Annihilator /NIN Barrage Sets --
	sets.Midshot.Annihilator.NIN.Barrage = set_combine(sets.Midshot.Annihilator.NIN,{},Barrage)
	sets.Midshot.Annihilator.NIN.MidACC.Barrage = set_combine(sets.Midshot.Annihilator.NIN.MidACC,{},Barrage)
	sets.Midshot.Annihilator.NIN.HighACC.Barrage = set_combine(sets.Midshot.Annihilator.NIN.HighACC,{},Barrage)

	-- PDT/MDT Sets --
	sets.PDT = {}

	sets.MDT = set_combine(sets.PDT,{})

	-- Melee Sets --
	sets.Melee = {head="Adhemar Bonnet",
			body="Adhemar Jacket",
			hands="Adhemar Wristbands",
			back="Lutian Cape",
			waist="Impulse Belt",
			legs="Samnuha Tights",
			feet="Herculean Boots",
			left_ring="Epona's Ring",
			right_ring="Petrov Ring",
			left_ear="Steelflash Earring",
			right_ear="Bladeborn Earring",
			waist="Patentia Sash",
			neck="Asperity necklace",}
	sets.Melee.MidACC = set_combine(sets.Melee,{})
	sets.Melee.HighACC = set_combine(sets.Melee.MidACC,{})

	-- WS Base Set --
	sets.WS = {
			head="Pursuer's Beret",
			body="Pursuer's Doublet",
			hands="Carmine Fin. Ga.",
			back="Lutian Cape",
			waist="Impulse Belt",
			legs="Adhemar Kecks",
			feet="Meg. Jam. +1",
			left_ring="Rajas Ring",
			right_ring="Petrov Ring",
			left_ear="Enervating Earring",
			right_ear="Ishvara Earring",
			neck="Ocachi gorget",}

	-- Coronach Sets --
	sets.WS.Coronach = {
			head="Pursuer's Beret",
			body="Pursuer's Doublet",
			hands="Carmine Fin. Ga.",
			back="Lutian Cape",
			waist="Impulse Belt",
			legs="Adhemar Kecks",
			feet="Meg. Jam. +1",
			left_ring="Rajas Ring",
			right_ring="Petrov Ring",
			left_ear="Enervating Earring",
			right_ear="Ishvara Earring",
			neck="Ocachi gorget",}
	sets.WS.Coronach.MidACC = set_combine(sets.WS.Coronach,{})
	sets.WS.Coronach.HighACC = set_combine(sets.WS.Coronach.MidACC,{})

	-- Coronach(Attack) Set. This Set Takes Priority Over Other Sets. --
	sets.WS.Coronach.ATT = set_combine(sets.WS.Coronach,{})

	-- Coronach(Enmity) Sets --
	sets.WS.Coronach.Enmity = set_combine(sets.WS.Coronach,{})
	sets.WS.Coronach.MidACC.Enmity = set_combine(sets.WS.Coronach.MidACC,{})
	sets.WS.Coronach.HighACC.Enmity = set_combine(sets.WS.Coronach.HighACC,{})

	-- Coronach(AM) Sets --
	sets.WS.Coronach.AM = set_combine(sets.WS.Coronach,{})
	sets.WS.Coronach.MidACC.AM = set_combine(sets.WS.Coronach.MidACC,{})
	sets.WS.Coronach.HighACC.AM = set_combine(sets.WS.Coronach.HighACC,{})

	-- Coronach(SAM Roll) Sets --
	sets.WS.Coronach.STP = set_combine(sets.WS.Coronach,{})
	sets.WS.Coronach.MidACC.STP = set_combine(sets.WS.Coronach.MidACC,{})
	sets.WS.Coronach.HighACC.STP = set_combine(sets.WS.Coronach.HighACC,{})

	-- Last Stand Sets --
	sets.WS["Last Stand"] = {
			head="Pursuer's Beret",
			body="Pursuer's Doublet",
			hands="Carmine Fin. Ga.",
			back="Lutian Cape",
			waist="Impulse Belt",
			legs="Adhemar Kecks",
			feet="Meg. Jam. +1",
			left_ring="Rajas Ring",
			right_ring="Petrov Ring",
			left_ear="Enervating Earring",
			right_ear="Ishvara Earring",
			neck="Ocachi gorget",}
	sets.WS["Last Stand"].MidACC = set_combine(sets.WS["Last Stand"],{})
	sets.WS["Last Stand"].HighACC = set_combine(sets.WS["Last Stand"].MidACC,{})

	-- Last Stand(Attack) Set. This Set Takes Priority Over Other Sets. --
	sets.WS["Last Stand"].ATT = set_combine(sets.WS["Last Stand"],{})

	-- Last Stand(Enmity) Sets --
	sets.WS["Last Stand"].Enmity = set_combine(sets.WS["Last Stand"],{})
	sets.WS["Last Stand"].MidACC.Enmity = set_combine(sets.WS["Last Stand"].MidACC,{})
	sets.WS["Last Stand"].HighACC.Enmity = set_combine(sets.WS["Last Stand"].HighACC,{})

	-- Last Stand(AM) Sets --
	sets.WS["Last Stand"].AM = set_combine(sets.WS["Last Stand"],{})
	sets.WS["Last Stand"].MidACC.AM = set_combine(sets.WS["Last Stand"].MidACC,{})
	sets.WS["Last Stand"].HighACC.AM = set_combine(sets.WS["Last Stand"].HighACC,{})

	-- Last Stand(SAM Roll) Sets --
	sets.WS["Last Stand"].STP = set_combine(sets.WS["Last Stand"],{})
	sets.WS["Last Stand"].MidACC.STP = set_combine(sets.WS["Last Stand"].MidACC,{})
	sets.WS["Last Stand"].HighACC.STP = set_combine(sets.WS["Last Stand"].HighACC,{})

	-- Namas Arrow Sets --
	sets.WS["Namas Arrow"] = {}
	sets.WS["Namas Arrow"].MidACC = set_combine(sets.WS["Namas Arrow"],{})
	sets.WS["Namas Arrow"].HighACC = set_combine(sets.WS["Namas Arrow"].MidACC,{})

	-- Namas Arrow(Attack) Set. This Set Takes Priority Over Other Sets. --
	sets.WS["Namas Arrow"].ATT = set_combine(sets.WS["Namas Arrow"],{})

	-- Namas Arrow(Enmity) Sets --
	sets.WS["Namas Arrow"].Enmity = set_combine(sets.WS["Namas Arrow"],{})
	sets.WS["Namas Arrow"].MidACC.Enmity = set_combine(sets.WS["Namas Arrow"].MidACC,{})
	sets.WS["Namas Arrow"].HighACC.Enmity = set_combine(sets.WS["Namas Arrow"].HighACC,{})

	-- Namas Arrow(AM) Sets --
	sets.WS["Namas Arrow"].AM = set_combine(sets.WS["Namas Arrow"],{})
	sets.WS["Namas Arrow"].MidACC.AM = set_combine(sets.WS["Namas Arrow"].MidACC,{})
	sets.WS["Namas Arrow"].HighACC.AM = set_combine(sets.WS["Namas Arrow"].HighACC,{})

	-- Namas Arrow(SAM Roll) Sets --
	sets.WS["Namas Arrow"].STP = set_combine(sets.WS["Namas Arrow"],{})
	sets.WS["Namas Arrow"].MidACC.STP = set_combine(sets.WS["Namas Arrow"].MidACC,{})
	sets.WS["Namas Arrow"].HighACC.STP = set_combine(sets.WS["Namas Arrow"].HighACC,{})

	-- Jishnu's Radiance Sets --
	sets.WS["Jishnu's Radiance"] = {}
	sets.WS["Jishnu's Radiance"].MidACC = set_combine(sets.WS["Jishnu's Radiance"],{})
	sets.WS["Jishnu's Radiance"].HighACC = set_combine(sets.WS["Jishnu's Radiance"].MidACC,{})

	-- Jishnu's Radiance(Attack) Set. This Set Takes Priority Over Other Sets. --
	sets.WS["Jishnu's Radiance"].ATT = set_combine(sets.WS["Jishnu's Radiance"],{})

	-- Jishnu's Radiance(Enmity) Sets --
	sets.WS["Jishnu's Radiance"].Enmity = set_combine(sets.WS["Jishnu's Radiance"],{})
	sets.WS["Jishnu's Radiance"].MidACC.Enmity = set_combine(sets.WS["Jishnu's Radiance"].MidACC,{})
	sets.WS["Jishnu's Radiance"].HighACC.Enmity = set_combine(sets.WS["Jishnu's Radiance"].HighACC,{})

	-- Jishnu's Radiance(AM) Sets --
	sets.WS["Jishnu's Radiance"].AM = set_combine(sets.WS["Jishnu's Radiance"],{})
	sets.WS["Jishnu's Radiance"].MidACC.AM = set_combine(sets.WS["Jishnu's Radiance"].MidACC,{})
	sets.WS["Jishnu's Radiance"].HighACC.AM = set_combine(sets.WS["Jishnu's Radiance"].HighACC,{})

	-- Jishnu's Radiance(SAM Roll) Sets --
	sets.WS["Jishnu's Radiance"].STP = set_combine(sets.WS["Jishnu's Radiance"],{})
	sets.WS["Jishnu's Radiance"].MidACC.STP = set_combine(sets.WS["Jishnu's Radiance"].MidACC,{})
	sets.WS["Jishnu's Radiance"].HighACC.STP = set_combine(sets.WS["Jishnu's Radiance"].HighACC,{})

	-- Apex Arrow Sets --
	sets.WS["Apex Arrow"] = {}
	sets.WS["Apex Arrow"].MidACC = set_combine(sets.WS["Apex Arrow"],{})
	sets.WS["Apex Arrow"].HighACC = set_combine(sets.WS["Apex Arrow"].MidACC,{})

	-- Wildfire Set --
	sets.WS.Wildfire = {}

	-- JA Sets --
	sets.JA = {}
	sets.JA.Shadowbind = {
			hands="Orion Bracers +1"}

	sets.JA.Scavenge = {feet="Orion Socks +1"}
	sets.JA.Camouflage = {body="Orion Jerkin +1"}
	sets.JA.Sharpshot = {legs="Orion Braccae +1"}
	sets.JA["Bounty Shot"] = {hands="Amini Glove. +1"}
	sets.JA["Eagle Eye Shot"] = {
			legs="Arc. Braccae +1"}

	-- Waltz Set --
	sets.Waltz = {}

	sets.Precast = {}
	-- Fastcast Set --
	sets.Precast.FastCast = {}
	-- Utsusemi Precast Set --
	sets.Precast.Utsusemi = set_combine(sets.Precast.FastCast,{neck="Magoraga Beads"})

	sets.Midcast = {}
	-- Magic Haste Set --
	sets.Midcast.Haste = set_combine(sets.PDT,{})
end

function pretarget(spell,action)
	if spell.action_type == 'Magic' and buffactive.silence then -- Auto Use Echo Drops If You Are Silenced --
		cancel_spell()
		send_command('input /item "Echo Drops" <me>')
	elseif spell.english == "Berserk" and buffactive.Berserk then -- Change Berserk To Aggressor If Berserk Is On --
		cancel_spell()
		send_command('Aggressor')
	elseif spell.english == "Seigan" and buffactive.Seigan then -- Change Seigan To Third Eye If Seigan Is On --
		cancel_spell()
		send_command('ThirdEye')
	elseif spell.english == "Meditate" and player.tp > 2900 then -- Cancel Meditate If TP Is Above 2900 --
		cancel_spell()
		add_to_chat(123, spell.name .. ' Canceled: ['..player.tp..' TP]')
	elseif spell.action_type == 'Ranged Attack' then
		if spell.target.distance > 24.9 then -- Cancel Ranged Attack If You Are Out Of Range --
			cancel_spell()
			add_to_chat(123, spell.name..' Canceled: [Out of Range]')
			return
		else
			if AutoMode == 'ON' and not buffactive.amnesia then -- Auto WS/Decoy Shot/Double Shot --
				if player.tp >= 1000 then
					cancel_spell()
					autoWS()
				elseif windower.ffxi.get_ability_recasts()[52] < 1 then
					cancel_spell()
					send_command('DecoyShot')
				elseif windower.ffxi.get_ability_recasts()[126] < 1 then
					cancel_spell()
					send_command('DoubleShot')
				end
			end
		end
	elseif spell.type == 'WeaponSkill' and player.status == 'Engaged' then -- Cancel WS If You Are Out Of Range --
		if (spell.skill == 'Archery' or spell.skill == 'Marksmanship') and spell.target.distance > 16+target_distance then
			cancel_spell()
			add_to_chat(123, spell.name..' Canceled: [Out of Range]')
			return
		else
			if spell.english ~= 'Bora Axe' and spell.target.distance > target_distance then
				cancel_spell()
				add_to_chat(123, spell.name..' Canceled: [Out of Range]')
				return
			end
		end
	end
end

function precast(spell,action)
	local check_ammo
	local check_ammo_count = 1
	if spell.action_type == 'Ranged Attack' then
		check_ammo = player.equipment.ammo
		if player.equipment.ammo == 'empty' or player.inventory[check_ammo].count <= check_ammo_count then
			add_to_chat(123, spell.name..' Canceled: [Out of Ammo]')
			cancel_spell()
			return
		else
			equip(sets.Preshot)
			if player.inventory[check_ammo].count <= ammo_warning_limit and player.inventory[check_ammo].count > 1 and not warning then
				add_to_chat(8, '***** [Low Ammo Warning!] *****')
				warning = true
			elseif player.inventory[check_ammo].count > ammo_warning_limit and warning then
				warning = false
			end
		end
	elseif spell.type == "WeaponSkill" then
		if player.status ~= 'Engaged' then -- Cancel WS If You Are Not Engaged. Can Delete It If You Don't Need It --
			cancel_spell()
			add_to_chat(123,'Unable To Use WeaponSkill: [Disengaged]')
			return
		else
			equipSet = sets.WS
			if equipSet[spell.english] then
				equipSet = equipSet[spell.english]
			end
			if Attack == 'ON' then
				equipSet = equipSet["ATT"]
			end
			if equipSet[AccArray[AccIndex]] then
				equipSet = equipSet[AccArray[AccIndex]]
			end
			if equipSet["Enmity"] and Enmity == 'ON' then
				equipSet = equipSet["Enmity"]
			end
			if buffactive.Aftermath and equipSet["AM"] then
				equipSet = equipSet["AM"]
			end
			if buffactive["Samurai Roll"] and equipSet["STP"] and Samurai_Roll == 'ON' then
				equipSet = equipSet["STP"]
			end
			if player.tp > 2990 or buffactive.Sekkanoki then
				if spell.english == "Last Stand" then -- Equip Altdorf's Earring and Wilhelm's Earring When You Have 3000 TP or Sekkanoki For Last Stand --
					equipSet = set_combine(equipSet,{ear1="Altdorf's Earring",ear2="Wilhelm's Earring"})
				elseif spell.english == "Jishnu's Radiance" then -- Equip Jupiter's Pearl When You Have 3000 TP or Sekkanoki For Jishnu's Radiance --
					equipSet = set_combine(equipSet,{ear1="Jupiter's Pearl"})
				end
			end
			if buffactive['Reive Mark'] then -- Equip Ygnas's Resolve +1 During Reive --
				equipSet = set_combine(equipSet,{neck="Ygnas's Resolve +1", range="Homestead gun"})
			end
			equip(equipSet)
		end
	elseif spell.type == "JobAbility" then
		if sets.JA[spell.english] then
			equip(sets.JA[spell.english])
		end
	elseif spell.action_type == 'Magic' then
		if spell.english:startswith('Utsusemi') then
			if spell.english == 'Utsusemi: Ni' then
				if buffactive['Copy Image (3)'] then
					cancel_spell()
					add_to_chat(123, spell.name .. ' Canceled: [3 Images]')
					return
				else
					equip(sets.Precast.Utsusemi)
				end
			else
				equip(sets.Precast.Utsusemi)
			end
		else
			equip(sets.Precast.FastCast)
		end
	elseif spell.type == "Waltz" then
		equip(sets.Waltz)
	elseif spell.english == 'Spectral Jig' and buffactive.Sneak then
		cast_delay(0.2)
		send_command('cancel Sneak')
	end
end

function midcast(spell,action)
	if spell.action_type == 'Ranged Attack' then
		equipSet = sets.Midshot
		if equipSet[WeaponArray[WeaponIndex]] then
			equipSet = equipSet[WeaponArray[WeaponIndex]]
		end
		if equipSet[player.sub_job] then
			equipSet = equipSet[player.sub_job]
		end
		if equipSet[AccArray[AccIndex]] then
			equipSet = equipSet[AccArray[AccIndex]]
		end
		if buffactive.Barrage and equipSet["Barrage"] then
			equipSet = equipSet["Barrage"]
		end
		if buffactive["Decoy Shot"] and equipSet["Decoy"] then
			equipSet = equipSet["Decoy"]
		end
		if equipSet["Enmity"] and Enmity == 'ON' then
			equipSet = equipSet["Enmity"]
		end
		if buffactive.Aftermath and equipSet["AM"] then
			equipSet = equipSet["AM"]
		end
		if buffactive.Ionis and equipSet["Ionis"] then
			equipSet = equipSet["Ionis"]
		end
		if buffactive["Samurai Roll"] and equipSet["STP"] and Samurai_Roll == 'ON' then
			equipSet = equipSet["STP"]
		end
		equip(equipSet)
	elseif spell.action_type == 'Magic' then
		if spell.english:startswith('Utsusemi') then
			if spell.english == 'Utsusemi: Ichi' and (buffactive['Copy Image'] or buffactive['Copy Image (2)'] or buffactive['Copy Image (3)']) then
				send_command('@wait 1.7;cancel Copy Image*')
			end
			equip(sets.Midcast.Haste)
		elseif spell.english == 'Monomi: Ichi' then
			if buffactive['Sneak'] then
				send_command('@wait 1.7;cancel sneak')
			end
			equip(sets.Midcast.Haste)
		else
			equip(sets.Midcast.Haste)
		end
	end
end

function aftercast(spell,action)
	if spell.action_type == 'Ranged Attack' and AutoMode == 'ON' then
		autoRA()
	else
		status_change(player.status)
	end
	if spell.type == "WeaponSkill" and not spell.interrupted then
		send_command('wait 0.2;gs c TP')
	end
end

function status_change(new,old)
	check_equip_lock()
	if Armor == 'PDT' then
		equip(sets.PDT)
	elseif Armor == 'MDT' then
		equip(sets.MDT)
	elseif new == 'Engaged' then
		equipSet = sets.Melee
		if equipSet[AccArray[AccIndex]] then
			equipSet = equipSet[AccArray[AccIndex]]
		end
		equip(equipSet)
	else
		equipSet = sets.Idle
		if equipSet[IdleArray[IdleIndex]] then
			equipSet = equipSet[IdleArray[IdleIndex]]
		end
		if equipSet[WeaponArray[WeaponIndex]] then
			equipSet = equipSet[WeaponArray[WeaponIndex]]
		end
		if equipSet[player.sub_job] then
			equipSet = equipSet[player.sub_job]
		end
		if buffactive['Reive Mark'] then -- Equip Ygnas's Resolve +1 During Reive --
			equipSet = set_combine(equipSet,{neck="Ygnas's Resolve +1"})
		end
		if world.area:endswith('Adoulin') then
			equipSet = set_combine(equipSet,{body="Councilor's Garb"})
		end
		equip(equipSet)
	end
end

function buff_change(buff,gain)
	buff = string.lower(buff)
	if buff == "overkill" then -- Overkill Timer --
		if gain then
			send_command('timers create "Overkill" 60 down')
		else
			send_command('timers delete "Overkill"')
			add_to_chat(123,'Overkill: [OFF]')
		end
	elseif buff == "decoy shot" then -- Decoy Shot Timer --
		if gain then
			send_command('timers create "Decoy Shot" 180 down')
		else
			send_command('timers delete "Decoy Shot"')
			add_to_chat(123,'Decoy Shot: [OFF]')
		end
	elseif buff == "aftermath: lv.3" then -- AM3 Timer/Countdown --
		if gain then
			send_command('timers create "Aftermath: Lv.3" 180 down;wait 150;input /echo Aftermath: Lv.3 [WEARING OFF IN 30 SEC.];wait 15;input /echo Aftermath: Lv.3 [WEARING OFF IN 15 SEC.];wait 5;input /echo Aftermath: Lv.3 [WEARING OFF IN 10 SEC.]')
		else
			send_command('timers delete "Aftermath: Lv.3"')
			add_to_chat(123,'AM3: [OFF]')
		end
	elseif buff == 'weakness' then -- Weakness Timer --
		if gain then
			send_command('timers create "Weakness" 300 up')
		else
			send_command('timers delete "Weakness"')
		end
	end
	if not midaction() then
		status_change(player.status)
	end
end

-- In Game: //gs c (command), Macro: /console gs c (command), Bind: gs c (command) --
function self_command(command)
	if command == 'C1' then -- Accuracy Level Toggle --
		AccIndex = (AccIndex % #AccArray) + 1
		add_to_chat(158,'Accuracy Level: ' .. AccArray[AccIndex])
		status_change(player.status)
	elseif command == 'C17' then -- Ranged Weapon Toggle --
		WeaponIndex = (WeaponIndex % #WeaponArray) + 1
		add_to_chat(158,'Ranged Weapon: '..WeaponArray[WeaponIndex])
		status_change(player.status)
	elseif command == 'C5' then -- Auto Update Gear Toggle --
		status_change(player.status)
		add_to_chat(158,'Auto Update Gear')
	elseif command == 'C7' then -- PDT Toggle --
		if Armor == 'PDT' then
			Armor = 'None'
			add_to_chat(123,'PDT Set: [Unlocked]')
		else
			Armor = 'PDT'
			add_to_chat(158,'PDT Set: [Locked]')
		end
		status_change(player.status)
	elseif command == 'C15' then -- MDT Toggle --
		if Armor == 'MDT' then
			Armor = 'None'
			add_to_chat(123,'MDT Set: [Unlocked]')
		else
			Armor = 'MDT'
			add_to_chat(158,'MDT Set: [Locked]')
		end
		status_change(player.status)
	elseif command == 'C11' then -- SAM Roll Toggle --
		if Samurai_Roll == 'ON' then
			Samurai_Roll = 'OFF'
			add_to_chat(123,'SAM Roll: [OFF]')
		else
			Samurai_Roll = 'ON'
			add_to_chat(158,'SAM Roll: [ON]')
		end
		status_change(player.status)
	elseif command == 'C10' then -- Enmity Toggle --
		if Enmity == 'ON' then
			Enmity = 'OFF'
			add_to_chat(123,'Enmity Set: [OFF]')
		else
			Enmity = 'ON'
			add_to_chat(158,'Enmity Set: [ON]')
		end
		status_change(player.status)
	elseif command == 'C9' then -- Attack Toggle --
		if Attack == 'ON' then
			Attack = 'OFF'
			add_to_chat(123,'Attack: [OFF]')
		else
			Attack = 'ON'
			add_to_chat(158,'Attack: [ON]')
		end
		status_change(player.status)
	elseif command == 'C3' then -- Overkill Toggle --
		send_command('Overkill')
		add_to_chat(158,'Overkill: [ON]')
	elseif command == 'C8' then -- Distance Toggle --
		if player.target.distance then
			target_distance = math.floor(player.target.distance*10)/10
			add_to_chat(158,'Distance: '..target_distance)
		else
			add_to_chat(123,'No Target Selected')
		end
	elseif command == 'C6' then -- Idle Toggle --
		IdleIndex = (IdleIndex % #IdleArray) + 1
		add_to_chat(158,'Idle Set: ' .. IdleArray[IdleIndex])
		status_change(player.status)
	elseif command == 'C2' then -- Auto RA/WS Toggle --
		if AutoMode == 'ON' then
			AutoMode = 'OFF'
			add_to_chat(123,'Auto Mode: [OFF]')
		else
			AutoMode = 'ON'
			add_to_chat(158,'Auto Mode: [ON]')
		end
	elseif command == 'TP' then
		add_to_chat(158,'TP Return: ['..tostring(player.tp)..']')
	elseif command:match('^SC%d$') then
		send_command('//' .. sc_map[command])
	end
end

function check_equip_lock() -- Lock Equipment Here --
	if player.equipment.left_ring == "Warp Ring" or player.equipment.left_ring == "Capacity Ring" or player.equipment.right_ring == "Warp Ring" or player.equipment.right_ring == "Capacity Ring" then
		disable('ring1','ring2')
	elseif player.equipment.back == "Mecisto. Mantle" or player.equipment.back == "Aptitude Mantle +1" or player.equipment.back == "Aptitude Mantle" then
		disable('back')
	else
		enable('ring1','ring2','back')
	end
end

function autoRA() -- Make Auto RA Delay Adjustment Here --
	local delay = '2.2'
	if player.equipment.range == 'Annihilator' then
		if spell.type == "WeaponSkill" then
			delay = '2.25'
		else
			if buffactive["Courser's Roll"] then
				delay = '0.7'
			elseif buffactive.Overkill or buffactive[581] then -- Flurry II --
				delay = '0.5'
			else
				delay = '1.05'
			end
		end
	elseif player.equipment.range == 'Yoichinoyumi' then
		if spell.type == "WeaponSkill" then
			delay = '2.25' 
		else
			if buffactive["Courser's Roll"] then
				delay = '0.7'
			elseif buffactive.Overkill or buffactive[581] then -- Flurry II --
				delay = '0.5'
			else
				delay = '1.05'
			end
		end
	end
	send_command('@wait '..delay..'; input /ra <t>')
end

function autoWS() -- Change Ranged Weapon Here --
	if player.equipment.range == 'Annihilator' then
		send_command('input /ws "'..AutoGunWS..'" <t>')
	elseif player.equipment.range == 'Yoichinoyumi' then
		send_command('input /ws "'..AutoBowWS..'" <t>')
	end
end

function sub_job_change(newSubjob, oldSubjob)
	select_default_macro_book()
end

function set_macro_page(set,book)
	if not tonumber(set) then
		add_to_chat(123,'Error setting macro page: Set is not a valid number ('..tostring(set)..').')
		return
	end
	if set < 1 or set > 10 then
		add_to_chat(123,'Error setting macro page: Macro set ('..tostring(set)..') must be between 1 and 10.')
		return
	end
	if book then
		if not tonumber(book) then
			add_to_chat(123,'Error setting macro page: book is not a valid number ('..tostring(book)..').')
			return
		end
		if book < 1 or book > 20 then
			add_to_chat(123,'Error setting macro page: Macro book ('..tostring(book)..') must be between 1 and 20.')
			return
		end
		send_command('@input /macro book '..tostring(book)..';wait .1;input /macro set '..tostring(set))
	else
		send_command('@input /macro set '..tostring(set))
	end
end

function select_default_macro_book()
	-- Default macro set/book
	if player.sub_job == 'WAR' then
		set_macro_page(1, 11)
	elseif player.sub_job == 'DNC' then
		set_macro_page(5, 11)
	elseif player.sub_job == 'SAM' then
		set_macro_page(2, 11)
	elseif player.sub_job == 'DRG' then
		set_macro_page(3, 11)
	elseif player.sub_job == 'NIN' then
		set_macro_page(10, 11)
	else
		set_macro_page(1, 11)
	end
end
 Lakshmi.Byrth
VIP
Offline
Server: Lakshmi
Game: FFXI
user: Byrthnoth
Posts: 6137
By Lakshmi.Byrth 2017-02-27 06:08:25
Link | Quote | Reply
 
Is everyone who is having trouble using a Motenten file?
[+]
 Bismarck.Phaded
Offline
Server: Bismarck
Game: FFXI
user: Phaded
By Bismarck.Phaded 2017-02-27 06:14:24
Link | Quote | Reply
 
Tested several jobs using my own custom made luas, from Brd to Sam all are working fine. Was wondering myself if its a mote thing.
 Asura.Saevel
Offline
Server: Asura
Game: FFXI
Posts: 9701
By Asura.Saevel 2017-02-27 06:39:35
Link | Quote | Reply
 
Lakshmi.Byrth said: »
Is everyone who is having trouble using a Motenten file?

If you use a Job Ability and it's nighttime with the moon at a 83 degree angle to the back of the target and you've eaten a bag of Doritos in the last 5min then use sets.Doritos.<Monster_Angle>.<Day> otherwise check for Sunchips and daytime inclination of the Sun and which Constellation is active...

Motenten's functions are great for those who know exactly what their doing, otherwise it's just copy pasta breaking.

When I get home from work I'll put the new GS in and let you know if their breaking or not.
[+]
 Lakshmi.Byrth
VIP
Offline
Server: Lakshmi
Game: FFXI
user: Byrthnoth
Posts: 6137
By Lakshmi.Byrth 2017-02-27 08:01:59
Link | Quote | Reply
 
I'll clarify that it's almost certainly not the fault of Motenten's files, but that would give me a good place to start looking. He added some stuff to gearswap that I might not be updating properly.
Offline
Server: Asura
Game: FFXI
user: Kenseto
Posts: 107
By Asura.Kensetobyakara 2017-02-27 08:06:57
Link | Quote | Reply
 
Asura.Saevel said: »
If you use a Job Ability and it's nighttime with the moon at a 83 degree angle to the back of the target and you've eaten a bag of Doritos in the last 5min then use sets.Doritos.<Monster_Angle>.<Day> otherwise check for Sunchips and daytime inclination of the Sun and which Constellation is active...
This is exactly what I needed on a Monday morning.
 Odin.Cnile
Offline
Server: Odin
Game: FFXI
user: cnile
Posts: 7
By Odin.Cnile 2017-02-27 11:16:50
Link | Quote | Reply
 
Byrth, maybe you have a gs with the same functions that I can get? thanks.
 Asura.Vanyar
Offline
Server: Asura
Game: FFXI
Posts: 15
By Asura.Vanyar 2017-02-27 17:09:02
Link | Quote | Reply
 
Heya, been doing two Omen runs and didn't notice any issues.

But when I did some validations after the run it seemed as if it wouldn't handle my gearswap if it contains eventArgs.handled = true within the same function.
I didn't troubleshoot it yet other then checking gear changes and showswaps, but it's nothing I can't workaround either.
Code
if state.DefenseMode.value ~= 'None' and spell.type ~= 'JobAbility' then
	handle_equipping_gear(player.status)
	eventArgs.handled = true
end
 Asura.Saevel
Offline
Server: Asura
Game: FFXI
Posts: 9701
By Asura.Saevel 2017-02-28 06:27:03
Link | Quote | Reply
 
Lakshmi.Byrth said: »
I'll clarify that it's almost certainly not the fault of Motenten's files, but that would give me a good place to start looking. He added some stuff to gearswap that I might not be updating properly.

Motenten is a great programmer and I have much respect for him. His extensions to gearswap allow for some pretty insane levels of automation. It's also extremely easy for someone who has zero coding experience to trip over their own *** "borrowing" another person's lua's that happen to use motenten's functions, without knowing how to properly edit and maintain the lua.

The highlight story is there was an Idris GEO in our group who was unknowingly removing his Idris for midcast on Indi-spells. He had screwed up the lua's logic without realizing it until one day during testing it was discovered. Turns out it had been an issue for a year...
[+]
 Odin.Cnile
Offline
Server: Odin
Game: FFXI
user: cnile
Posts: 7
By Odin.Cnile 2017-03-01 00:08:08
Link | Quote | Reply
 
Has anything been resolved?
 Lakshmi.Byrth
VIP
Offline
Server: Lakshmi
Game: FFXI
user: Byrthnoth
Posts: 6137
By Lakshmi.Byrth 2017-03-02 03:21:24
Link | Quote | Reply
 
https://www.dropbox.com/s/2fkkav1hhryflep/GearSwap%20-%20Dev.zip?dl=0

Inject_outgoing seems to be slower than I thought it was. This should fix a lot of the problems people have had.


Please try it again and let me know how it went.
 Lakshmi.Byrth
VIP
Offline
Server: Lakshmi
Game: FFXI
user: Byrthnoth
Posts: 6137
By Lakshmi.Byrth 2017-03-03 08:03:20
Link | Quote | Reply
 
I've gotten one report that this fixes the problems with the last version. Has anyone else tried it?
 Asura.Hopefulki
Offline
Server: Asura
Game: FFXI
user: hopefulki
Posts: 21
By Asura.Hopefulki 2017-03-03 09:11:15
Link | Quote | Reply
 
I'll try this out later today and report back
 Lakshmi.Byrth
VIP
Offline
Server: Lakshmi
Game: FFXI
user: Byrthnoth
Posts: 6137
By Lakshmi.Byrth 2017-03-03 18:20:15
Link | Quote | Reply
 
Excellent, thanks!
First Page 2