Advertisement
Guest User

Untitled

a guest
Jul 11th, 2019
727
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 78.54 KB | None | 0 0
  1. -------------------------------------------------------------------------------------------------------------------
  2. -- Much of these files have been adapted from Motenten's base files, much credit goes to him,
  3. -- I have started to rename his files so that they don't get modified whenever the Windower
  4. -- team very rarely decides to update his old files.
  5. -- Common variables and functions to be included in job scripts, for general default handling.
  6. --
  7. -- Include this file in the get_sets() function with the command:
  8. -- include('Sel-Include.lua')
  9. --
  10. -- It will then automatically run its own init_include() function.
  11. --
  12. -- IMPORTANT: This include requires supporting include files:
  13. -- Sel-Utility
  14. -- Sel-Mappings
  15. -- Sel-SelfCommands
  16. -- Sel-Globals
  17. --
  18. -- Place the include() directive at the start of a job's get_sets() function.
  19. --
  20. -- Included variables and functions are considered to be at the same scope level as
  21. -- the job script itself, and can be used as such.
  22. -------------------------------------------------------------------------------------------------------------------
  23.  
  24. -------------------------------------------------------------------------------------------------------------------
  25. -- Initialization function that defines variables to be used.
  26. -- These are accessible at the including job lua script's scope.
  27. --
  28. -- Auto-initialize after defining this function.
  29. -------------------------------------------------------------------------------------------------------------------
  30.  
  31. function init_include()
  32.     extdata = require("extdata")
  33.     res = require ("resources")
  34.    
  35.     --Snaps's Rnghelper extension for automatic ranged attacks that should be superior to my implementation.
  36.     require('Snaps-RngHelper')
  37.  
  38.     -- Used to define various types of data mappings.  These may be used in the initialization, so load it up front.
  39.     include('Sel-Mappings')
  40.    
  41.     -- Modes is the include for a mode-tracking variable class.  Used for state vars, below.
  42.     include('Modes')
  43.    
  44.     -- Adding Organizer for gear management.
  45.     include('organizer-lib.lua')
  46.    
  47.     -- Var for tracking state values
  48.     state = {}
  49.  
  50.     --My Auto-Stun/Reaction module for gearswap, must come after state is defined.
  51.     include('Sel-Stahp.lua')
  52.    
  53.     --Making Extdata/Resources dependant functions work
  54.     cp_delay = 20
  55.  
  56.     -- General melee offense/defense modes, allowing for hybrid set builds, as well as idle/resting/weaponskill.
  57.     -- This just defines the vars and sets the descriptions.  List modes with no values automatically
  58.     -- get assigned a 'Normal' default value.
  59.     state.OffenseMode         = M{['description'] = 'Offense Mode'}
  60.     state.HybridMode          = M{['description'] = 'Hybrid Mode'}
  61.     state.RangedMode          = M{['description'] = 'Ranged Mode'}
  62.     state.WeaponskillMode     = M{['description'] = 'Weaponskill Mode','Match'}
  63.     state.CastingMode         = M{['description'] = 'Casting Mode'}
  64.     state.IdleMode            = M{['description'] = 'Idle Mode'}
  65.     state.RestingMode         = M{['description'] = 'Resting Mode'}
  66.  
  67.     state.DefenseMode         = M{['description'] = 'Defense Mode', 'None', 'Physical', 'Magical', 'Resist'}
  68.     state.PhysicalDefenseMode = M{['description'] = 'Physical Defense Mode', 'PDT'}
  69.     state.MagicalDefenseMode  = M{['description'] = 'Magical Defense Mode', 'MDT'}
  70.     state.ResistDefenseMode   = M{['description'] = 'Resistance Defense Mode', 'MEVA'}
  71.    
  72.     state.Passive             = M{['description'] = 'Passive Mode','None'}
  73.     state.Kiting              = M(false, 'Kiting')
  74.     state.SelectNPCTargets    = M(false, 'Select NPC Targets')
  75.     state.Capacity            = M(false, 'Capacity Mode')
  76.     state.ReEquip             = M(false, 'ReEquip Mode')
  77.     state.AutoArts            = M(false, 'AutoArts Mode')
  78.     state.AutoTrustMode       = M(false, 'Auto Trust Mode')
  79.     state.RngHelper           = M(false, 'RngHelper')
  80.     state.AutoTankMode        = M(false, 'Auto Tank Mode')
  81.     state.AutoNukeMode        = M(false, 'Auto Nuke Mode')
  82.     state.AutoRuneMode        = M(false, 'Auto Rune Mode')
  83.     state.AutoShadowMode      = M(false, 'Auto Shadow Mode')
  84.     state.AutoWSMode          = M(false, 'Auto Weaponskill Mode')
  85.     state.AutoFoodMode        = M(false, 'Auto Food Mode')
  86.     state.AutoSubMode         = M(false, 'Auto Sublimation Mode')
  87.     state.AutoBuffMode        = M(false, 'Auto Buff Mode')
  88.     state.AutoCleanupMode     = M(false, 'Auto Cleanup Mode')
  89.     state.DisplayMode         = M(true, 'Display Mode')
  90.     state.UseCustomTimers     = M(true, 'Use Custom Timers')
  91.     state.CancelStoneskin     = M(true, 'Stoneskin Cancel Mode')
  92.     state.RelicAftermath      = M(true, 'Maintain Relic Aftermath')
  93.     state.Contradance         = M(true, 'Auto Contradance Mode')
  94.     state.ElementalWheel      = M(false, 'Elemental Wheel')
  95.     state.MaintainDefense     = M(false, 'Maintain Defense')
  96.    
  97.     state.RuneElement         = M{['description'] = 'Rune Element','Ignis','Gelus','Flabra','Tellus','Sulpor','Unda','Lux','Tenebrae'}
  98.     state.ElementalMode       = M{['description'] = 'Elemental Mode', 'Fire','Ice','Wind','Earth','Lightning','Water','Light','Dark'}
  99.     state.AutoSambaMode       = M{['description']= 'Auto Samba Mode', 'Off', 'Haste Samba', 'Aspir Samba', 'Drain Samba II'}
  100.  
  101.     state.MagicBurstMode      = M{['description'] = 'Magic Burst Mode', 'Off', 'Single', 'Lock'}
  102.     state.SkillchainMode      = M{['description'] = 'Skillchain Mode', 'Off', 'Single', 'Lock'}
  103.     state.PCTargetMode        = M{['description'] = 'PC Target Mode', 'default', 'stpt', 'stal', 'stpc'}
  104.     state.EquipStop           = M{['description'] = 'Stop Equipping Gear', 'off', 'precast', 'midcast', 'pet_midcast'}
  105.     state.CombatWeapon        = M{['description']='Combat Weapon', ['string']=''}
  106.     state.CombatForm          = M{['description']='Combat Form', ['string']=''}
  107.    
  108.     if mageJobs:contains(player.main_job) then
  109.         state.Weapons         = M{['description'] = 'Weapons','None','Weapons'}
  110.     else
  111.         state.Weapons         = M{['description'] = 'Weapons','Weapons','None'}
  112.     end
  113.    
  114.     -- Non-mode vars that are used for state tracking.
  115.     state.MaxWeaponskillDistance = 0
  116.     state.Buff = {}
  117.    
  118.     --Tracking these here because required quick actions on multiple jobs.
  119.     state.Buff['Light Arts'] = buffactive['Light Arts'] or false
  120.     state.Buff['Addendum: White'] = buffactive['Addendum: White'] or false
  121.     state.Buff['Dark Arts'] = buffactive['Dark Arts'] or false
  122.     state.Buff['Addendum: Black'] = buffactive['Addendum: Black'] or false
  123.     state.Buff['Accession'] = buffactive['Accession'] or false
  124.  
  125.     -- Classes describe a 'type' of action.  They are similar to state, but
  126.     -- may have any free-form value, or describe an entire table of mapped values.
  127.     classes = {}
  128.     -- Basic spell mappings are based on common spell series.
  129.     -- EG: 'Cure' for Cure, Cure II, Cure III, Cure IV, Cure V, or Cure VI.
  130.     classes.SpellMaps = spell_maps
  131.     -- List of spells and spell maps that don't benefit from greater skill (though
  132.     -- they may benefit from spell-specific augments, such as improved regen or refresh).
  133.     -- Spells that fall under this category will be skipped when searching for
  134.     -- spell.skill sets.
  135.     classes.NoSkillSpells = no_skill_spells_list
  136.     classes.SkipSkillCheck = false
  137.     -- Custom, job-defined class, like the generic spell mappings.
  138.     -- Takes precedence over default spell maps.
  139.     -- Is reset at the end of each spell casting cycle (ie: at the end of aftercast).
  140.     classes.JAMode = nil
  141.     classes.CustomClass = nil
  142.     -- Custom groups used for defining melee and idle sets.  Persists long-term.
  143.     classes.CustomMeleeGroups = L{}
  144.     classes.CustomRangedGroups = L{}
  145.     classes.CustomIdleGroups = L{}
  146.     classes.CustomDefenseGroups = L{}
  147.  
  148.     -- Class variables for time-based flags
  149.     classes.Daytime = false
  150.     classes.DuskToDawn = false
  151.    
  152.     -- Var for tracking misc info
  153.     info = {}
  154.     options = {}
  155.  
  156.     -- Special control flags.
  157.     mote_vars = {}
  158.     mote_vars.set_breadcrumbs = L{}
  159.     mote_vars.res_buffs = S{}
  160.     for index,struct in pairs(gearswap.res.buffs) do
  161.         mote_vars.res_buffs:add(struct.en)
  162.     end
  163.    
  164.     -- Define and default variables for global functions that can be overwritten.
  165.     useItem = false
  166.     useItemName = ''
  167.     useItemSlot = ''
  168.    
  169.     autonuke = 'Fire'
  170.     autows = ''
  171.     rangedautows = ''
  172.     autowstp = 1000
  173.     rangedautowstp = 1000
  174.     buffup = false
  175.     time_offset = -39602
  176.     framerate = 75
  177.     curecheat = false
  178.     lastincombat = player.in_combat
  179.    
  180.     time_test = false
  181.     utsusemi_cancel_delay = .5
  182.     conserveshadows = true
  183.    
  184.     -- Buff tracking that buffactive can't detect
  185.     lastshadow = "Utsusemi: San"
  186.     lasthaste = 1
  187.     lastflurry = 1
  188.    
  189.     -- Sub-tables within the sets table that we expect to exist, and are annoying to have to
  190.     -- define within each individual job file.  We can define them here to make sure we don't
  191.     -- have to check for existence.  The job file should be including this before defining
  192.     -- any sets, so any changes it makes will override these anyway.
  193.     sets.precast = {}
  194.     sets.precast.FC = {}
  195.     sets.precast.JA = {}
  196.     sets.precast.WS = {}
  197.     sets.precast.RA = {}
  198.     sets.precast.Item = {}
  199.     sets.midcast = {}
  200.     sets.midcast.RA = {}
  201.     sets.midcast.Pet = {}
  202.     sets.idle = {}
  203.     sets.resting = {}
  204.     sets.engaged = {}
  205.     sets.defense = {}
  206.     sets.buff = {}
  207.     sets.element = {}
  208.     sets.passive = {}
  209.     sets.weapons = {}
  210.  
  211.     sets.DuskIdle = {}
  212.     sets.DayIdle = {}
  213.     sets.NightIdle = {}
  214.    
  215.     gear = {}
  216.     gear.default = {}
  217.  
  218.     gear.ElementalGorget = {name=""}
  219.     gear.ElementalBelt = {name=""}
  220.     gear.ElementalObi = {name=""}
  221.     gear.ElementalCape = {name=""}
  222.     gear.ElementalRing = {name=""}
  223.     gear.FastcastStaff = {name=""}
  224.     gear.RecastStaff = {name=""}
  225.  
  226.     -- Load externally-defined information (info that we don't want to change every time this file is updated).
  227.  
  228.     -- Used to define misc utility functions that may be useful for this include or any job files.
  229.    include('Sel-Utility')
  230.  
  231.     -- Used for all self-command handling.
  232.     include('Sel-SelfCommands')
  233.     include('Sel-TreasureHunter')
  234.  
  235.     -- Include general user globals, such as custom binds or gear tables.
  236.     -- Load Sel-Globals first, followed by User-Globals, followed by <character>-Globals.
  237.     -- Any functions re-defined in the later includes will overwrite the earlier versions.
  238.     include('Sel-GlobalItems')
  239.     optional_include({'user-globals.lua'})
  240.     optional_include({player.name..'-globals.lua'})
  241.     optional_include({player.name..'-items.lua'})
  242.     optional_include({player.name..'_Crafting.lua'})
  243.  
  244.     -- New Display functions, needs to come after globals for user settings.
  245.     include('Sel-Display.lua')
  246.  
  247.  
  248.     -- Global default binds
  249.     global_on_load()
  250.  
  251.     -- Load a sidecar file for the job (if it exists) that may re-define init_gear_sets and file_unload.
  252.     load_sidecar(player.main_job)
  253.    
  254.     -- Controls for handling our autmatic functions.
  255.    
  256.     tickdelay = (framerate * 20)
  257.    
  258.     -- General var initialization and setup.
  259.     if job_setup then
  260.         job_setup()
  261.     end
  262.  
  263.     -- User-specific var initialization and setup.
  264.     if user_setup then
  265.         user_setup()
  266.     end
  267.    
  268.     if extra_user_setup then
  269.         extra_user_setup()
  270.     end
  271.  
  272.     if state.Weapons.value == 'None' then
  273.         enable('main','sub','range','ammo')
  274.     else
  275.         send_command('@wait 3;gs c weapons Default')
  276.     end
  277.    
  278.     -- Event register to make time variables track.
  279.     windower.register_event('time change', time_change)
  280.  
  281.     -- Event register to perform actions on new targets.
  282.     function target_change(new)
  283.    
  284.         if state.RngHelper.value then
  285.             send_command('gs rh clear')
  286.         end
  287.    
  288.         local target = windower.ffxi.get_mob_by_target('t')
  289.         local sub= windower.ffxi.get_mob_by_target('st')
  290.         if (target ~= nil) and (sub == nil) then
  291.             if state.AutoCleanupMode.value and math.sqrt(target.distance) < 7 then
  292.                 if target.name == "Runje Desaali" then
  293.                     for i in pairs(bayld_items) do
  294.                         if player.inventory[bayld_items[i]] then
  295.                             windower.chat.input('/item "'..bayld_items[i]..'" <t>')
  296.                             windower.chat.input:schedule(2,'/targetnpc')
  297.                             return
  298.                         end
  299.                     end
  300.                 elseif target.name == "Sturdy Pyxis" and player.inventory['Forbidden Key'] then
  301.                     windower.chat.input('/item "Forbidden Key" <t>')
  302.                 end
  303.             end
  304.         end
  305.     end
  306.     windower.register_event('target change', target_change)
  307.  
  308.     -- Event register to prevent auto-modes from spamming after zoning.
  309.     windower.register_event('zone change', function()
  310.         tickdelay = (framerate * 20)
  311.         state.AutoBuffMode:reset()
  312.         state.AutoSubMode:reset()
  313.         state.AutoTrustMode:reset()
  314.         state.AutoTankMode:reset()
  315.         state.AutoRuneMode:reset()
  316.         state.AutoFoodMode:reset()
  317.         state.AutoWSMode:reset()
  318.         state.AutoNukeMode:reset()
  319.         useItem = false
  320.         useItemName = ''
  321.         useItemSlot = ''
  322.         lastincombat = false
  323.         being_attacked = false
  324.         if state.DisplayMode.value then update_job_states() end
  325.     end)
  326.  
  327.     -- New implementation of tick.
  328.     windower.raw_register_event('prerender', function()
  329.         tickdelay = tickdelay - 1
  330.  
  331.         if not (tickdelay <= 0) then return end
  332.  
  333.         gearswap.refresh_globals(false)
  334.        
  335.         if (player ~= nil) and (player.status == 'Idle' or player.status == 'Engaged') and not (check_midaction() or moving or buffactive['Sneak'] or buffactive['Invisible'] or silent_check_disable()) then
  336.             if pre_tick then
  337.                 if pre_tick() then return end
  338.             end
  339.  
  340.             if user_job_tick then
  341.                 if user_job_tick() then return end
  342.             end
  343.  
  344.             if user_tick then
  345.                 if user_tick() then return end
  346.             end
  347.  
  348.             if job_tick then
  349.                 if job_tick() then return end
  350.             end
  351.            
  352.             if default_tick then
  353.                 if default_tick() then return end
  354.             end        
  355.  
  356.             if extra_user_job_tick then
  357.                 if extra_user_job_tick() then return end
  358.             end
  359.  
  360.             if extra_user_tick then
  361.                 if extra_user_tick() then return end
  362.             end
  363.  
  364.             tickdelay = (framerate / 4)
  365.         end
  366.        
  367.         if lastincombat == true and not player.in_combat and being_attacked then
  368.             being_attacked = false
  369.             if player.status == 'Idle' and not midaction() and not pet_midaction() then
  370.                 handle_equipping_gear(player.status)
  371.             end
  372.         end        
  373.         lastincombat = player.in_combat
  374.  
  375.         tickdelay = (framerate / 2)
  376.  
  377.     end)
  378.    
  379.     -- Load up all the gear sets.
  380.     init_gear_sets()
  381. end
  382.  
  383. -- Called when this job file is unloaded (eg: job change)
  384. -- Conditional definition so that it doesn't overwrite explicit user
  385. -- versions of this function.
  386. if not file_unload then
  387.     file_unload = function()
  388.         if user_unload then
  389.             user_unload()
  390.         end
  391.        
  392.         if job_unload then
  393.             job_unload()
  394.         end
  395.        
  396.         global_unload()
  397.     end
  398. end
  399.  
  400. -- Function to bind GearSwap binds when loading a GS script, moved to globals to seperate per character and user.
  401. function global_on_load()
  402.  
  403. end
  404.  
  405. -- Function to revert binds when unloading.
  406. function global_unload()
  407.     send_command('unbind ^f8')
  408.     send_command('unbind !f8')
  409.     send_command('unbind @f8')
  410.     send_command('unbind f9')
  411.     send_command('unbind ^f9')
  412.     send_command('unbind !f9')
  413.     send_command('unbind @f9')
  414.     send_command('unbind f10')
  415.     send_command('unbind ^f10')
  416.     send_command('unbind !f10')
  417.     send_command('unbind @f10')
  418.     send_command('unbind f11')
  419.     send_command('unbind ^f11')
  420.     send_command('unbind !f11')
  421.     send_command('unbind @f11')
  422.     send_command('unbind f12')
  423.     send_command('unbind ^f12')
  424.     send_command('unbind !f12')
  425.     send_command('unbind @f12')
  426.     send_command('unbind ^@!pause')
  427.     send_command('unbind ^pause')
  428.     send_command('unbind !pause')
  429.     send_command('unbind @pause')
  430.     send_command('unbind ^@!pause')
  431.  
  432.     send_command('unbind ^\\\\')
  433.     send_command('unbind @\\\\')
  434.     send_command('unbind !\\\\')
  435.  
  436.     send_command('unbind ^`')
  437.     send_command('unbind !`')
  438.     send_command('unbind @`')
  439.  
  440.     send_command('unbind ^backspace')
  441.     send_command('unbind !backspace')
  442.     send_command('unbind @backspace')
  443.  
  444.     send_command('unbind ^r')
  445.     send_command('unbind !r')
  446.     send_command('unbind @r')
  447.  
  448.     send_command('unbind ^y')
  449.     send_command('unbind !y')
  450.     send_command('unbind @y')
  451.  
  452.     send_command('unbind ^q')
  453.     send_command('unbind !q')
  454.     send_command('unbind @q')
  455.    
  456.     send_command('unbind ^-')
  457.     send_command('unbind !-')
  458.     send_command('unbind @-')
  459.  
  460.     send_command('unbind ^=')
  461.     send_command('unbind !=')
  462.     send_command('unbind @=')
  463.  
  464.     send_command('unbind ^delete')
  465.     send_command('unbind !delete')
  466.     send_command('unbind @delete')
  467.    
  468.     if clear_job_states then
  469.         clear_job_states()
  470.     end    
  471. end
  472.  
  473. -------------------------------------------------------------------------------------------------------------------
  474. -- Generalized functions for handling precast/midcast/aftercast for player-initiated actions.
  475. -- This depends on proper set naming.
  476. -- Global hooks can be written as user_xxx() to override functions at a global level.
  477. -- Each job can override any of these general functions using job_xxx() hooks.
  478. -------------------------------------------------------------------------------------------------------------------
  479.  
  480. ----------------------------------- -------------------------------------
  481. -- Generic function to map a set processing order to all action events.
  482. ------------------------------------------------------------------------
  483.  
  484.  
  485. -- Process actions in a specific order of events:
  486. -- Filter  - filter_xxx() functions determine whether to run any of the code for this action.
  487. -- Global  - user_xxx() functions get called first.  Define in Sel-Globals or User-Globals.
  488. -- Local   - job_xxx() functions get called next. Define in JOB.lua file.
  489. -- Default - default_xxx() functions get called next. Defined in this file.
  490. -- Cleanup - cleanup_xxx() functions always get called before exiting.
  491. --
  492. -- Parameters:
  493. -- spell - standard spell table passed in by GearSwap
  494. -- action - string defining the function mapping to use (precast, midcast, etc)
  495. function handle_actions(spell, action)
  496.     -- Init an eventArgs that allows cancelling.
  497.     local eventArgs = {handled = false, cancel = false}
  498.    
  499.     mote_vars.set_breadcrumbs:clear()
  500.  
  501.     -- Get the spell mapping, since we'll be passing it to various functions and checks.
  502.     local spellMap = get_spell_map(spell)
  503.     gearswap.refresh_globals(false)
  504.  
  505.     -- General filter checks to see whether this function should be run.
  506.     -- If eventArgs.cancel is set, cancels this function, not the spell.
  507.     if _G['user_filter_'..action] then
  508.         _G['user_filter_'..action](spell, spellMap, eventArgs)
  509.        
  510.         if eventArgs.cancel and (action == 'pretarget' or action == 'precast') then
  511.             cancel_spell()
  512.             return
  513.         end
  514.     end
  515.    
  516.     if _G['user_job_filter_'..action] and not eventArgs.cancel then
  517.         _G['user_job_filter_'..action](spell, spellMap, eventArgs)
  518.        
  519.         if eventArgs.cancel and (action == 'pretarget' or action == 'precast') then
  520.             cancel_spell()
  521.             return
  522.         end
  523.     end
  524.    
  525.     if _G['job_filter_'..action] and not eventArgs.cancel then
  526.         _G['job_filter_'..action](spell, spellMap, eventArgs)
  527.        
  528.         if eventArgs.cancel and (action == 'pretarget' or action == 'precast') then
  529.             cancel_spell()
  530.             return
  531.         end
  532.     end
  533.    
  534.     if _G['filter_'..action] and not eventArgs.cancel then
  535.         _G['filter_'..action](spell, spellMap, eventArgs)
  536.        
  537.         if eventArgs.cancel and (action == 'pretarget' or action == 'precast') then
  538.             cancel_spell()
  539.             return
  540.         end
  541.     end
  542.    
  543.     -- If filter didn't cancel it, process user and default actions.
  544.     if not eventArgs.cancel then
  545.         -- Global user handling of this action
  546.         if _G['user_'..action] then
  547.             _G['user_'..action](spell, spellMap, eventArgs)
  548.            
  549.             if eventArgs.cancel and (action == 'pretarget' or action == 'precast') then
  550.                 cancel_spell()
  551.                 return
  552.             end
  553.         end
  554.        
  555.         -- Job-specific handling of this action
  556.         if not eventArgs.cancel and not eventArgs.handled and _G['job_'..action] then
  557.             _G['job_'..action](spell, spellMap, eventArgs)
  558.            
  559.             if eventArgs.cancel and (action == 'pretarget' or action == 'precast') then
  560.                 cancel_spell()
  561.                 return
  562.             end
  563.         end
  564.        
  565.         if not eventArgs.cancel and not eventArgs.handled and _G['user_job_'..action] then
  566.             _G['user_job_'..action](spell, spellMap, eventArgs)
  567.            
  568.             if eventArgs.cancel and (action == 'pretarget' or action == 'precast') then
  569.                 cancel_spell()
  570.                 return
  571.             end
  572.         end
  573.    
  574.         -- Default handling of this action
  575.         if not eventArgs.cancel and not eventArgs.handled and _G['default_'..action] then
  576.             _G['default_'..action](spell, spellMap, eventArgs)
  577.             display_breadcrumbs(spell, spellMap, action)
  578.            
  579.             if eventArgs.cancel and (action == 'pretarget' or action == 'precast') then
  580.                 cancel_spell()
  581.                 return
  582.             end
  583.         end
  584.        
  585.         -- Global user handling of this action
  586.         if _G['extra_user_'..action] then
  587.             _G['extra_user_'..action](spell, spellMap, eventArgs)
  588.            
  589.             if eventArgs.cancel and (action == 'pretarget' or action == 'precast') then
  590.                 cancel_spell()
  591.                 return
  592.             end
  593.         end
  594.        
  595.         -- Global post-handling of this action
  596.         if not eventArgs.cancel and _G['user_post_'..action] then
  597.             _G['user_post_'..action](spell, spellMap, eventArgs)
  598.         end
  599.  
  600.        -- Job-specific post-handling of this action
  601.         if not eventArgs.cancel and _G['job_post_'..action] then
  602.             _G['job_post_'..action](spell, spellMap, eventArgs)
  603.         end
  604.        
  605.         if not eventArgs.cancel and _G['user_job_post_'..action] then
  606.             _G['user_job_post_'..action](spell, spellMap, eventArgs)
  607.         end
  608.  
  609.         if not eventArgs.cancel and _G['default_post_'..action] then
  610.             _G['default_post_'..action](spell, spellMap, eventArgs)
  611.         end
  612.        
  613.         if not eventArgs.cancel and _G['extra_user_post_'..action] then
  614.             _G['extra_user_post_'..action](spell, spellMap, eventArgs)
  615.         end
  616.        
  617.     end
  618.  
  619.     -- Cleanup once this action is done
  620.     if _G['cleanup_'..action] then
  621.         _G['cleanup_'..action](spell, spellMap, eventArgs)
  622.     end
  623. end
  624.  
  625.  
  626. --------------------------------------
  627. -- Action hooks called by GearSwap.
  628. --------------------------------------
  629.  
  630. function filtered_action(spell, eventArgs)
  631.     local eventArgs = {cancel = false}
  632.  
  633.     -- Check users action filtering
  634.     if not eventArgs.cancel and user_filtered_action then
  635.         user_filtered_action(spell, eventArgs)
  636.     end
  637.  
  638.     -- Check jobs action filtering
  639.     if not eventArgs.cancel and user_job_filtered_action then
  640.         user_job_filtered_action(spell, eventArgs)
  641.     end
  642.    
  643.     -- Check jobs action filtering
  644.     if not eventArgs.cancel and job_filtered_action then
  645.         job_filtered_action(spell, eventArgs)
  646.     end
  647.    
  648.     -- Check users action filtering
  649.     if not eventArgs.cancel and default_filtered_action then
  650.         default_filtered_action(spell, eventArgs)
  651.     end
  652.    
  653.     -- Final user for filtering and error reporting.
  654.     if not eventArgs.cancel and extra_user_filtered_action then
  655.         extra_user_filtered_action(spell, eventArgs)
  656.     end
  657.    
  658.     -- Final pass for filtering and error reporting.
  659.     if not eventArgs.cancel and extra_default_filtered_action then
  660.         extra_default_filtered_action(spell, eventArgs)
  661.     end
  662.  
  663. end
  664.  
  665. function pretarget(spell)
  666.     handle_actions(spell, 'pretarget')
  667. end
  668.  
  669. function precast(spell)
  670.     handle_actions(spell, 'precast')
  671. end
  672.  
  673. function midcast(spell)
  674.     handle_actions(spell, 'midcast')
  675. end
  676.  
  677. function aftercast(spell)
  678.  
  679.     if state.Buff[spell.english:ucfirst()] ~= nil and spell.target.type == 'SELF' then
  680.         state.Buff[spell.english:ucfirst()] = not spell.interrupted or buffactive[spell.english] or false
  681.     end
  682.     handle_actions(spell, 'aftercast')
  683. end
  684.  
  685. function pet_midcast(spell)
  686.     handle_actions(spell, 'pet_midcast')
  687. end
  688.  
  689. function pet_aftercast(spell)
  690.     handle_actions(spell, 'pet_aftercast')
  691. end
  692.  
  693. --------------------------------------
  694. -- Default code for each action.
  695. --------------------------------------
  696.  
  697. function default_filtered_action(spell, eventArgs)
  698.     if spell.english == 'Warp' then
  699.         if (item_available('Warp Ring') or player.satchel['Warp Ring']) then
  700.             useItem = true
  701.             useItemName = 'Warp Ring'
  702.             useItemSlot = 'ring2'
  703.             add_to_chat(217,"You can't cast warp, attempting to use Warp Ring instead, /heal to cancel.")
  704.         elseif (item_available('Treat Staff') or player.satchel['Treat Staff']) then
  705.             useItem = true
  706.             useItemName = 'Treat Staff'
  707.             useItemSlot = 'main'
  708.         elseif (item_available('Warp Cudgel') or player.satchel['Warp Cudgel']) then
  709.             add_to_chat(217,"You can't cast warp, attempting to use Warp Cudgel instead, /heal to cancel.")
  710.             useItem = true
  711.             useItemName = 'Warp Cudgel'
  712.             useItemSlot = 'main'
  713.             add_to_chat(217,"You can't cast warp, attempting to use Warp Cudgel instead, /heal to cancel.")
  714.         elseif (item_available('Instant Warp') or player.satchel['Instant Warp']) then
  715.             useItem = true
  716.             useItemName = 'Instant Warp'
  717.             useItemSlot = 'item'
  718.             add_to_chat(217,"You can't cast warp, attempting to use a Warp Scroll instead, /heal to cancel.")
  719.         else
  720.             add_to_chat(122,'Warp unavailable and no warp items available.')
  721.         end
  722.         cancel_spell()
  723.         eventArgs.cancel = true
  724.     elseif spell.english == 'Retrace' then
  725.         if spell.target.type == 'SELF' and (item_available('Instant Retrace') or player.satchel['Instant Retrace']) then
  726.             useItem = true
  727.             useItemName = 'Instant Retrace'
  728.             useItemSlot = 'item'
  729.             add_to_chat(217,"You can't cast Retrace, attempting to use a Retrace Scroll instead, /heal to cancel.")
  730.             cancel_spell()
  731.             eventArgs.cancel = true
  732.         end
  733.     elseif spell.english == 'Teleport-Holla' then
  734.         if (item_available('Dim. Ring (Holla)') or player.satchel['Dim. Ring (Holla)']) then
  735.             useItem = true
  736.             useItemName = 'Dim. Ring (Holla)'
  737.             useItemSlot = 'ring2'
  738.             add_to_chat(217,"You can't cast Teleport-Holla, attempting to use Dimensional Ring instead, /heal to cancel.")
  739.             cancel_spell()
  740.             eventArgs.cancel = true
  741.         end
  742.     elseif spell.english == 'Teleport-Dem' then
  743.         if (item_available('Dim. Ring (Dem)') or player.satchel['Dim. Ring (Dem)']) then
  744.             useItem = true
  745.             useItemName = 'Dim. Ring (Dem)'
  746.             useItemSlot = 'ring2'
  747.             add_to_chat(217,"You can't cast Teleport-Dem, attempting to use Dimensional Ring instead, /heal to cancel.")
  748.             cancel_spell()
  749.             eventArgs.cancel = true
  750.         end
  751.     elseif spell.english == 'Teleport-Mea' then
  752.         if (item_available('Dim. Ring (Mea)') or player.satchel['Dim. Ring (Mea)']) then
  753.             useItem = true
  754.             useItemName = 'Dim. Ring (Mea)'
  755.             useItemSlot = 'ring2'
  756.             add_to_chat(217,"You can't cast Teleport-Mea, attempting to use Dimensional Ring instead, /heal to cancel.")
  757.             cancel_spell()
  758.             eventArgs.cancel = true
  759.         end
  760.     elseif spell.english == 'Invisible' then
  761.         if player.main_job == 'DNC' or player.sub_job == 'DNC' then
  762.             windower.chat.input('/ja "Spectral Jig" <me>')
  763.             add_to_chat(217,"You can't cast Invisible, attempting to use Spectral Jig instead.")
  764.             cancel_spell()
  765.             eventArgs.cancel = true
  766.             return
  767.         elseif player.main_job == 'NIN' or player.sub_job == 'NIN' then
  768.             windower.chat.input('/ma "Tonko: Ni" <me>')
  769.             add_to_chat(217,"You can't cast Invisible, attempting to use Tonko: Ni instead.")
  770.             cancel_spell()
  771.             eventArgs.cancel = true
  772.             return
  773.         elseif item_available('Prism Powder') then
  774.             windower.chat.input('/item "Prism Powder" <me>')
  775.             add_to_chat(217,"You can't cast Invisible, attempting to use Prism Powder instead.")
  776.             cancel_spell()
  777.             eventArgs.cancel = true
  778.             return
  779.         elseif item_available('Rainbow Powder') then
  780.             windower.chat.input('/item "Rainbow Powder" <me>')
  781.             add_to_chat(217,"You can't cast Invisible, attempting to use Prism Powder instead.")
  782.             cancel_spell()
  783.             eventArgs.cancel = true
  784.             return
  785.         end
  786.     elseif spell.english == 'Sneak' then
  787.         if player.main_job == 'DNC' or player.sub_job == 'DNC' then
  788.             windower.chat.input('/ja "Spectral Jig" <me>')
  789.             add_to_chat(217,"You can't cast Sneak, attempting to use Spectral Jig instead.")
  790.             cancel_spell()
  791.             eventArgs.cancel = true
  792.             return
  793.         elseif player.main_job == 'NIN' or player.sub_job == 'NIN' then
  794.             windower.chat.input('/ma "Monomi: Ichi" <me>')
  795.             add_to_chat(217,"You can't cast Sneak, attempting to use Monomi: Ichi instead.")
  796.             cancel_spell()
  797.             eventArgs.cancel = true
  798.             return
  799.         elseif item_available('Silent Oil') then
  800.             windower.chat.input('/item "Silent Oil" <me>')
  801.             add_to_chat(217,"You can't cast Sneak, attempting to use Silent Oil instead.")
  802.             cancel_spell()
  803.             eventArgs.cancel = true
  804.             return
  805.         end
  806.     end
  807. end
  808.  
  809. function extra_default_filtered_action(spell, eventArgs)
  810.     if not can_use(spell) then
  811.         cancel_spell()
  812.         eventArgs.cancel = true
  813.         return     
  814.     end
  815. end
  816.  
  817. function default_pretarget(spell, spellMap, eventArgs)
  818.     auto_change_target(spell, spellMap)
  819. end
  820.  
  821. function default_precast(spell, spellMap, eventArgs)
  822.     cancel_conflicting_buffs(spell, spellMap, eventArgs)
  823. --    refine_waltz(spell, spellMap, eventArgs)
  824.  
  825.     if eventArgs.cancel then
  826.         cancel_spell()
  827.     else
  828.         equip(get_precast_set(spell, spellMap))
  829.     end
  830. end
  831.  
  832. function default_post_precast(spell, spellMap, eventArgs)
  833.     if not eventArgs.handled then
  834.         if spell.type == 'Waltz' then
  835.             if spell.target.type == 'SELF' and sets.Self_Waltz and not (spell.english == "Healing Waltz" or spell.english == "Divine Waltz" or spell.english == "Divine Waltz II") then
  836.                 equip(sets.Self_Waltz)
  837.             end
  838.        
  839.         elseif spell.action_type == 'Magic' then
  840.             if spellMap == 'BarElement' and sets.midcast.BarElement then
  841.                 equip(sets.midcast.BarElement)
  842.             elseif spell.english:startswith('Utsusemi') then
  843.                 if sets.precast.FC.Shadows and ((spell.english == 'Utsusemi: Ni' and player.main_job == 'NIN' and lastshadow == 'Utsusemi: San') or (spell.english == 'Utsusemi: Ichi' and lastshadow ~= 'Utsusemi: Ichi')) then
  844.                     equip(sets.precast.FC.Shadows)
  845.                 end
  846.             end
  847.            
  848.         elseif spell.type == 'JobAbility' then
  849.        
  850.             if state.TreasureMode.value ~= 'None' and spell.target.type == 'MONSTER' and not info.tagged_mobs[spell.target.id] then
  851.                 equip(sets.TreasureHunter)
  852.             end
  853.  
  854.         elseif spell.type == 'WeaponSkill' then
  855.            
  856.             if state.WeaponskillMode.value ~= 'Proc' and elemental_obi_weaponskills:contains(spell.name) and spell.element and (spell.element == world.weather_element or spell.element == world.day_element) and item_available('Hachirin-no-Obi') then
  857.                 equip({waist="Hachirin-no-Obi"})
  858.             end
  859.            
  860.             if sets.Reive and buffactive['Reive Mark'] and sets.Reive.neck == "Ygnas's Resolve +1" then
  861.                 equip(sets.Reive)
  862.             end
  863.            
  864.             if state.WeaponskillMode.value == 'Proc' and not (sets.precast.WS[spell.english] and sets.precast.WS[spell.english].Proc) and sets.precast.WS.Proc then
  865.                 equip(sets.precast.WS.Proc)
  866.             end
  867.            
  868.             if state.Capacity.value == true then
  869.                 equip(sets.Capacity)
  870.             end
  871.            
  872.             if state.TreasureMode.value ~= 'None' and not info.tagged_mobs[spell.target.id] then
  873.                 equip(sets.TreasureHunter)
  874.             end
  875.         end
  876.        
  877.         if state.DefenseMode.value ~= 'None' and (player.in_combat or being_attacked) then
  878.             if spell.action_type == 'Magic' then
  879.                 if sets.precast.FC[spell.english] and sets.precast.FC[spell.english].DT then
  880.                     equip(sets.precast.FC[spell.english].DT)
  881.                 elseif sets.precast.FC[spellMap] and sets.precast.FC[spellMap].DT then
  882.                     equip(sets.precast.FC[spellMap].DT)
  883.                 elseif sets.precast.FC[spell.skill] and sets.precast.FC[spell.skill].DT then
  884.                     equip(sets.precast.FC[spell.skill].DT)
  885.                 elseif sets.precast.FC.DT then
  886.                     equip(sets.precast.FC.DT)
  887.                 else
  888.                     handle_equipping_gear(player.status)
  889.                 end
  890.             elseif spell.type == 'WeaponSkill' then
  891.                 if state.SkillchainMode.value ~= 'Off' and sets.Skillchain then
  892.                     equip(sets.Skillchain)
  893.                 end
  894.                
  895.                 if sets.precast.WS[spell.english] and sets.precast.WS[spell.english].DT then
  896.                     equip(sets.precast.WS[spell.english].DT)
  897.                 elseif sets.precast.WS.DT then
  898.                     equip(sets.precast.WS.DT)
  899.                 else
  900.                     handle_equipping_gear(player.status)
  901.                 end
  902.             elseif spell.action_type == 'Ability' then
  903.                 if sets.precast.JA[spell.english] and sets.precast.JA[spell.english].DT then
  904.                     equip(sets.precast.JA[spell.english].DT)
  905.                 else
  906.                     handle_equipping_gear(player.status)
  907.                 end
  908.             else
  909.                 handle_equipping_gear(player.status)
  910.             end
  911.         end
  912.     end
  913. end
  914.  
  915. function default_midcast(spell, spellMap, eventArgs)
  916.     equip(get_midcast_set(spell, spellMap))
  917. end
  918.  
  919. function default_post_midcast(spell, spellMap, eventArgs)
  920.  
  921.     if not eventArgs.handled then
  922.         if not job_post_midcast and is_nuke(spell, spellMap) and state.MagicBurstMode.value ~= 'Off' and sets.MagicBurst then
  923.             equip(sets.MagicBurst)
  924.         end
  925.  
  926.         if spell.target.type == 'SELF' and spellMap then
  927.             if spellMap:contains('Cure') then
  928.                 if curecheat then
  929.                     if sets.HPCure then
  930.                         equip(sets.HPCure)
  931.                     end
  932.                     curecheat = false
  933.                 elseif sets.Self_Healing and not (state.CastingMode.value:contains('SIRD') and (player.in_combat or being_attacked)) then
  934.                     equip(sets.Self_Healing)
  935.                 elseif sets.Self_Healing and sets.Self_Healing.SIRD and state.CastingMode.value:contains('SIRD') then
  936.                     equip(sets.Self_Healing.SIRD)
  937.                 end
  938.             elseif spellMap == 'Refresh' and sets.Self_Refresh and not (state.CastingMode.value:contains('SIRD') and (player.in_combat or being_attacked)) then
  939.                 equip(sets.Self_Refresh)
  940.             end
  941.         end
  942.        
  943.         if state.Capacity.value == true then
  944.             if set.contains(spell.targets, 'Enemy') then
  945.        
  946.                 if spell.skill == 'Elemental Magic' or spell.skill == 'Blue Magic' or spell.action_type == 'Ranged Attack' then
  947.                     equip(sets.Capacity)
  948.                 end
  949.             end
  950.         end
  951.        
  952.         if sets.Reive and buffactive['Reive Mark'] and (spell.skill == 'Elemental Magic' or spellMap == 'Cure' or spellMap == 'Curaga') then
  953.             if sets.Reive.neck == "Arciela's Grace +1" then
  954.                 equip(sets.Reive)
  955.             end
  956.         end
  957.        
  958.         if state.TreasureMode.value ~= 'None' and spell.target.type == 'MONSTER' and not info.tagged_mobs[spell.target.id] then
  959.             equip(sets.TreasureHunter)
  960.         end
  961.        
  962.         if state.DefenseMode.value ~= 'None' and spell.action_type == 'Magic' and (player.in_combat or being_attacked) then
  963.             if sets.midcast[spell.english] and sets.midcast[spell.english].DT then
  964.                 equip(sets.midcast[spell.english].DT)
  965.             elseif sets.midcast[spellMap] and sets.midcast[spellMap].DT then
  966.                 equip(sets.midcast[spellMap].DT)
  967.             elseif sets.midcast[spell.skill] and sets.midcast[spell.skill].DT then
  968.                 equip(sets.midcast[spell.skill].DT)
  969.             elseif sets.midcast.FastRecast.DT then
  970.                 equip(sets.midcast.FastRecast.DT)
  971.             else
  972.                 handle_equipping_gear(player.status)
  973.             end
  974.  
  975.             if spell.target.type == 'SELF' and spellMap and spellMap:contains('Cure') and sets.Self_Healing and sets.Self_Healing.DT then
  976.                 equip(sets.Self_Healing.DT)
  977.  
  978.             end
  979.            
  980.             eventArgs.handled = true
  981.         end
  982.     end    
  983.    
  984.     if buffactive.doom then
  985.         equip(sets.buff.Doom)
  986.     end
  987. end
  988.  
  989. function default_post_pet_midcast(spell, spellMap, eventArgs)
  990.     if state.Capacity.value == true then
  991.         equip(sets.Capacity)
  992.     end
  993.  
  994.     if buffactive.doom then
  995.         equip(sets.buff.Doom)
  996.     end
  997. end
  998.  
  999. function default_aftercast(spell, spellMap, eventArgs)
  1000.    
  1001.     if spell.action_type == 'Magic' then
  1002.         tickdelay = (framerate * 2.7)
  1003.     elseif spell.action_type == 'Ability' then
  1004.         tickdelay = (framerate * .5)
  1005.     elseif spell.type == 'WeaponSkill' then
  1006.         tickdelay = (framerate * 1.9)
  1007.     elseif  spell.action_type == 'Item' then
  1008.         tickdelay = (framerate * 1.1)
  1009.     elseif spell.action_type == 'Ranged Attack' then
  1010.         tickdelay = (framerate * 1.1)
  1011.     end
  1012.    
  1013.     if not spell.interrupted then
  1014.         if state.TreasureMode.value ~= 'None' and state.DefenseMode.value == 'None' and spell.target.type == 'MONSTER' and not info.tagged_mobs[spell.target.id] then
  1015.             info.tagged_mobs[spell.target.id] = os.time()
  1016.             if player.target.id == spell.target.id and state.th_gear_is_locked then
  1017.                 unlock_TH()
  1018.             end
  1019.         end
  1020.         if is_nuke(spell, spellMap) then
  1021.             if state.MagicBurstMode.value == 'Single' then state.MagicBurstMode:reset() end
  1022.             if state.ElementalWheel.value and (spell.skill == 'Elemental Magic' or spellMap:contains('ElementalNinjutsu')) then
  1023.                 state.ElementalMode:cycle()
  1024.                 local startindex = state.ElementalMode.index
  1025.                 while S{"Light","Dark"}:contains(state.ElementalMode.value) do
  1026.                     state.ElementalMode:cycle()
  1027.                     if startindex == state.ElementalMode.index then break end
  1028.                 end
  1029.             end
  1030.             if state.DisplayMode.value then update_job_states() end
  1031.         elseif spell.type == 'WeaponSkill' and state.SkillchainMode.value == 'Single' then
  1032.             state.SkillchainMode:reset()
  1033.             if state.DisplayMode.value then update_job_states() end
  1034.         elseif spell.english:startswith('Utsusemi') then
  1035.             lastshadow = spell.english
  1036.         elseif spell.action_type == 'Item' and useItem and spell.english == useItemName then
  1037.             useItem = false
  1038.             if useItemSlot == 'item' then
  1039.                 windower.send_command('put '..useItemName..' satchel')
  1040.             elseif useItemSlot == 'set' then
  1041.                 local slots = T{}
  1042.                 for slot,item in pairs(sets[useItemName]) do
  1043.                     slots:append(slot)
  1044.                 end
  1045.                 enable(slots)
  1046.                 if player.inventory[useItemName] then
  1047.                     windower.send_command('wait 1;put '..set_to_item(useItemName)..' satchel')
  1048.                 end
  1049.             else
  1050.                 enable(useItemSlot)
  1051.                 if player.inventory[useItemName] then
  1052.                     windower.send_command('wait 1;put '..useItemName..' satchel')
  1053.                 end
  1054.             end
  1055.             useItemName = ''
  1056.             useItemSlot = ''
  1057.         end
  1058.     else
  1059.     end
  1060.  
  1061.     if not eventArgs.handled then
  1062.         handle_equipping_gear(player.status)
  1063.     end
  1064. end
  1065.  
  1066. function default_pet_midcast(spell, spellMap, eventArgs)
  1067.     equip(get_pet_midcast_set(spell, spellMap))
  1068. end
  1069.  
  1070. function default_pet_aftercast(spell, spellMap, eventArgs)
  1071.     if not midaction() then handle_equipping_gear(player.status) end
  1072. end
  1073.  
  1074. --------------------------------------
  1075. -- Filters for each action.
  1076. -- Set eventArgs.cancel to true to stop further processing.
  1077. -- May show notification messages, but should not do any processing here.
  1078. --------------------------------------
  1079.  
  1080. function filter_precast(spell, spellMap, eventArgs)
  1081.     if check_rnghelper(spell, spellMap, eventArgs) then return end
  1082.     if check_midaction(spell, spellMap, eventArgs) then return end
  1083.     if check_disable(spell, spellMap, eventArgs) then return end
  1084.     if check_doom(spell, spellMap, eventArgs) then return end
  1085.     if check_amnesia(spell, spellMap, eventArgs) then return end
  1086.     if check_abilities(spell, spellMap, eventArgs) then return end
  1087.     if check_silence(spell, spellMap, eventArgs) then return end
  1088.     if check_targets(spell, spellMap, eventArgs) then return end
  1089.     if check_recast(spell, spellMap, eventArgs) then return end
  1090.     if check_cost(spell, spellMap, eventArgs) then return end
  1091.  
  1092.     if spellMap == 'Cure' or spellMap == 'Curaga' then
  1093.         if spell.target.distance > 21 and spell.target.type == 'PLAYER' then
  1094.             cancel_spell()
  1095.             eventArgs.cancel = true
  1096.             --Delete the next line and uncomment the line after, if you'd rather it send a tell if they're too far to heal.
  1097.             add_to_chat(123,'Target out of range, too far to heal!')
  1098.             --windower.send_command('input /tell '..spell.target.name..' !!! OUT OF RANGE !!! TOO FAR TO HEAL !!!')
  1099.         end
  1100.     end
  1101. end
  1102.  
  1103. function filter_midcast(spell, spellMap, eventArgs)
  1104.     if state.EquipStop.value == 'precast' then
  1105.         eventArgs.cancel = true
  1106.         return
  1107.     end
  1108.    
  1109.     -- Default base equipment layer of fast recast, needs to come before job-midcast.
  1110.     if spell.action_type == 'Magic' and sets.midcast and sets.midcast.FastRecast then
  1111.         equip(sets.midcast.FastRecast)
  1112.     end
  1113. end
  1114.  
  1115. function filter_aftercast(spell, spellMap, eventArgs)
  1116.     if state.EquipStop.value == 'precast' or state.EquipStop.value == 'midcast' or state.EquipStop.value == 'pet_midcast' then
  1117.         eventArgs.cancel = true
  1118.     elseif spell.name == 'Unknown Interrupt' then
  1119.         eventArgs.cancel = true
  1120.     end
  1121. end
  1122.  
  1123. function filter_pet_midcast(spell, spellMap, eventArgs)
  1124.     -- If we have show_set active for precast or midcast, don't try to equip pet midcast gear.
  1125.     if state.EquipStop.value == 'precast' or state.EquipStop.value == 'midcast' then
  1126.         add_to_chat(104, 'Show Sets: Pet midcast not equipped.')
  1127.         eventArgs.cancel = true
  1128.     end
  1129. end
  1130.  
  1131. function filter_pet_aftercast(spell, spellMap, eventArgs)
  1132.     -- If show_set is flagged for precast or midcast, don't try to equip aftercast gear.
  1133.     if state.EquipStop.value == 'precast' or state.EquipStop.value == 'midcast' or state.EquipStop.value == 'pet_midcast' then
  1134.         eventArgs.cancel = true
  1135.     end
  1136. end
  1137.  
  1138. --------------------------------------
  1139. -- Cleanup code for each action.
  1140. --------------------------------------
  1141.  
  1142. function cleanup_precast(spell, spellMap, eventArgs)
  1143.     -- If show_set is flagged for precast, notify that we won't try to equip later gear.
  1144.     if state.EquipStop.value == 'precast' then
  1145.         add_to_chat(104, 'Show Sets: Stopping at precast.')
  1146.     end
  1147. end
  1148.  
  1149. function cleanup_midcast(spell, spellMap, eventArgs)
  1150.     -- If show_set is flagged for midcast, notify that we won't try to equip later gear.
  1151.     if state.EquipStop.value == 'midcast' then
  1152.         add_to_chat(104, 'Show Sets: Stopping at midcast.')
  1153.     end
  1154. end
  1155.  
  1156. function cleanup_aftercast(spell, spellMap, eventArgs)
  1157.     -- Reset custom classes after all possible precast/midcast/aftercast/job-specific usage of the value.
  1158.     -- If we're in the middle of a pet action, pet_aftercast will handle clearing it.
  1159.     if not pet_midaction() then
  1160.         reset_transitory_classes()
  1161.     end
  1162. end
  1163.  
  1164. function cleanup_pet_midcast(spell, spellMap, eventArgs)
  1165.     -- If show_set is flagged for pet midcast, notify that we won't try to equip later gear.
  1166.     if state.EquipStop.value == 'pet_midcast' then
  1167.         add_to_chat(104, 'Show Sets: Stopping at pet midcast.')
  1168.     end
  1169. end
  1170.  
  1171. function cleanup_pet_aftercast(spell, spellMap, eventArgs)
  1172.     -- Reset custom classes after all possible precast/midcast/aftercast/job-specific usage of the value.
  1173.     reset_transitory_classes()
  1174. end
  1175.  
  1176. function pre_tick()
  1177.     if check_trust() then return true end
  1178.     if check_rune() then return true end
  1179.     return false
  1180. end
  1181.  
  1182. function default_tick()
  1183.     if check_shadows() then return true end
  1184.     if check_use_item() then return true end
  1185.     if check_sub() then return true end
  1186.     if check_food() then return true end
  1187.     if check_ws() then return true end
  1188.     if check_samba() then return true end
  1189.     if check_cpring_buff() then return true end
  1190.     if check_cleanup() then return true end
  1191.     if check_nuke() then return true end
  1192.     return false
  1193. end
  1194.  
  1195. -- Clears the values from classes that only exist til the action is complete.
  1196. function reset_transitory_classes()
  1197.     classes.CustomClass = nil
  1198.     classes.JAMode = nil
  1199. end
  1200.  
  1201.  
  1202.  
  1203. -------------------------------------------------------------------------------------------------------------------
  1204. -- High-level functions for selecting and equipping gear sets.
  1205. -------------------------------------------------------------------------------------------------------------------
  1206.  
  1207. -- Central point to call to equip gear based on status.
  1208. -- Status - Player status that we're using to define what gear to equip.
  1209. function handle_equipping_gear(playerStatus, petStatus)
  1210.     -- init a new eventArgs
  1211.     local eventArgs = {handled = false}
  1212.    
  1213.     -- Allow jobs to override this code
  1214.     if job_handle_equipping_gear then
  1215.         job_handle_equipping_gear(playerStatus, eventArgs)
  1216.     end
  1217.  
  1218.     if state.ReEquip.value and state.Weapons.value ~= 'None' then
  1219.         if player.equipment.main == 'empty' and player.equipment.sub == 'empty' then
  1220.             local commandArgs = {}
  1221.             handle_weapons(commandArgs)
  1222.         end
  1223.     end
  1224.  
  1225.     if player.equipment.ammo == 'empty' and sets.weapons[state.Weapons.value] and sets.weapons[state.Weapons.value].ammo then
  1226.         enable('ammo')
  1227.         equip({ammo=sets.weapons[state.Weapons.value].ammo})
  1228.         disable('ammo')
  1229.     end
  1230.    
  1231.     -- Equip default gear if job didn't handle it.
  1232.     if not eventArgs.handled then
  1233.         equip_gear_by_status(playerStatus, petStatus)
  1234.     end
  1235. end
  1236.  
  1237.  
  1238. -- Function to wrap logic for equipping gear on aftercast, status change, or user update.
  1239. -- @param status : The current or new player status that determines what sort of gear to equip.
  1240. function equip_gear_by_status(playerStatus, petStatus)
  1241.     if _global.debug_mode then add_to_chat(123,'Debug: Equip gear for status ['..tostring(status)..'], HP='..tostring(player.hp)) end
  1242.  
  1243.     playerStatus = playerStatus or player.status or 'Idle'
  1244.     -- If status not defined, treat as idle.
  1245.     -- Be sure to check for positive HP to make sure they're not dead.
  1246.     if (playerStatus == 'Idle' or playerStatus == '') and player.hp > 0 then
  1247.         equip(get_idle_set(petStatus))
  1248.     elseif playerStatus == 'Engaged' then
  1249.         if player.target and player.target.model_size and player.target.distance < (3.2 + player.target.model_size) then
  1250.             equip(get_melee_set(petStatus))
  1251.         else
  1252.             equip(get_idle_set(petStatus))
  1253.         end
  1254.     elseif playerStatus == 'Resting' then
  1255.         equip(get_resting_set(petStatus))
  1256.     end
  1257. end
  1258.  
  1259.  
  1260. -------------------------------------------------------------------------------------------------------------------
  1261. -- Functions for constructing default gear sets based on status.
  1262. -------------------------------------------------------------------------------------------------------------------
  1263.  
  1264. -- Returns the appropriate idle set based on current state values and location.
  1265. -- Set construction order (all of which are optional):
  1266. --   sets.idle[idleScope][state.IdleMode][Pet[Engaged]][CustomIdleGroups]
  1267. --
  1268. -- Params:
  1269. -- petStatus - Optional explicit definition of pet status.
  1270. function get_idle_set(petStatus)
  1271.     local idleSet = sets.idle
  1272.    
  1273.     if not idleSet then
  1274.         return {}
  1275.     end
  1276.    
  1277.     mote_vars.set_breadcrumbs:append('sets')
  1278.     mote_vars.set_breadcrumbs:append('idle')
  1279.    
  1280.     local idleScope
  1281.  
  1282.     if buffactive.weakness then
  1283.         idleScope = 'Weak'
  1284.     else
  1285.         idleScope = 'Field'
  1286.     end
  1287.  
  1288.     if idleSet[idleScope] then
  1289.         idleSet = idleSet[idleScope]
  1290.         mote_vars.set_breadcrumbs:append(idleScope)
  1291.     end
  1292.  
  1293.     if not (player.in_combat or being_attacked) and (state.IdleMode.current:contains('DT') or state.IdleMode.current:contains('Tank')) then
  1294.     elseif idleSet[state.IdleMode.current] then
  1295.         idleSet = idleSet[state.IdleMode.current]
  1296.         mote_vars.set_breadcrumbs:append(state.IdleMode.current)
  1297.     end
  1298.  
  1299.     if (pet.isvalid or state.Buff.Pet) and idleSet.Pet then
  1300.         idleSet = idleSet.Pet
  1301.         petStatus = petStatus or pet.status
  1302.         mote_vars.set_breadcrumbs:append('Pet')
  1303.  
  1304.         if petStatus == 'Engaged' and idleSet.Engaged then
  1305.             idleSet = idleSet.Engaged
  1306.             mote_vars.set_breadcrumbs:append('Engaged')
  1307.         end
  1308.     end
  1309.  
  1310.     for _,group in ipairs(classes.CustomIdleGroups) do
  1311.         if idleSet[group] then
  1312.             idleSet = idleSet[group]
  1313.             mote_vars.set_breadcrumbs:append(group)
  1314.         end
  1315.     end
  1316.  
  1317.     --Apply time based gear.
  1318.     if (state.IdleMode.value == 'Normal' or state.IdleMode.value == 'Sphere') and not pet.isvalid then
  1319.         if classes.DuskToDawn then
  1320.             if sets.DuskIdle then idleSet = set_combine(idleSet, sets.DuskIdle) end
  1321.         end
  1322.        
  1323.         if classes.Daytime then
  1324.             if sets.DayIdle then idleSet = set_combine(idleSet, sets.DayIdle) end
  1325.         else
  1326.             if sets.NightIdle then idleSet = set_combine(idleSet, sets.NightIdle) end
  1327.         end
  1328.     end
  1329.  
  1330.     if areas.Assault:contains(world.area) and sets.Assault then
  1331.         idleSet = set_combine(idleSet, sets.Assault)
  1332.     end
  1333.    
  1334.     if sets.Reive and buffactive['Reive Mark'] then
  1335.         idleSet = set_combine(idleSet, sets.Reive)
  1336.     end
  1337.  
  1338.     if user_customize_idle_set then
  1339.         idleSet = user_customize_idle_set(idleSet)
  1340.     end
  1341.    
  1342.     if job_customize_idle_set then
  1343.         idleSet = job_customize_idle_set(idleSet)
  1344.     end
  1345.    
  1346.     if user_job_customize_idle_set then
  1347.         idleSet = user_job_customize_idle_set(idleSet)
  1348.     end
  1349.  
  1350.     if areas.Cities:contains(world.area) then
  1351.         if sets.idle.Town then
  1352.             idleSet = set_combine(idleSet, sets.Kiting, sets.idle.Town)
  1353.         elseif sets.Town then
  1354.             idleSet = set_combine(idleSet, sets.Kiting, sets.Town)
  1355.         else
  1356.             idleSet = set_combine(idleSet, sets.Kiting)
  1357.         end
  1358.  
  1359.         if (world.area:contains('Adoulin') or world.area == "Celennia Memorial Library") and item_available("Councilor's Garb") then
  1360.             idleSet = set_combine(idleSet, {body="Councilor's Garb"})
  1361.         elseif (world.area:contains('Bastok') or world.area == "Metalworks") and item_available("Republic Aketon") then
  1362.             idleSet = set_combine(idleSet, {body="Republic Aketon"})
  1363.         elseif (world.area:contains('Windurst') or world.area == "Heavens Tower") and item_available("Federation Aketon") then
  1364.             idleSet = set_combine(idleSet, {body="Federation Aketon"})
  1365.         elseif (world.area:contains("San d'Oria") or world.area == "Chateau d'Oraguille") and item_available("Kingdom Aketon") then
  1366.             idleSet = set_combine(idleSet, {body="Kingdom Aketon"})
  1367.         elseif world.area == "Mog Garden" and item_available("Jubilee Shirt") then
  1368.             idleSet = set_combine(idleSet, {body="Jubilee Shirt"})
  1369.         end
  1370.     end
  1371.  
  1372.     idleSet = apply_passive(idleSet)
  1373.    
  1374.     if state.Capacity.value then
  1375.         idleSet = set_combine(idleSet, sets.Capacity)
  1376.     end
  1377.    
  1378.     idleSet = apply_defense(idleSet)
  1379.     idleSet = apply_kiting(idleSet)
  1380.    
  1381.     if silent_check_disable() and state.DefenseMode.value == 'None' then
  1382.         if state.IdleMode.value:contains('MDT') and sets.defense.MDT then
  1383.             idleSet = set_combine(idleSet, sets.defense.MDT)
  1384.         elseif sets.defense.PDT then
  1385.             idleSet = set_combine(idleSet, sets.defense.PDT)
  1386.         end
  1387.     end
  1388.    
  1389.     if (buffactive.sleep or buffactive.Lullaby) and (player.main_job == 'SMN' and pet.isvalid) then
  1390.         idleSet = set_combine(idleSet, sets.buff.Sleep)
  1391.     end
  1392.    
  1393.     if buffactive.doom then
  1394.         idleSet = set_combine(idleSet, sets.buff.Doom)
  1395.     end
  1396.  
  1397.     if extra_user_customize_idle_set then
  1398.         idleSet = extra_user_customize_idle_set(idleSet)
  1399.     end
  1400.  
  1401.     return idleSet
  1402. end
  1403.  
  1404.  
  1405. -- Returns the appropriate melee set based on current state values.
  1406. -- Set construction order (all sets after sets.engaged are optional):
  1407. --   sets.engaged[state.CombatForm][state.CombatWeapon][state.OffenseMode][state.DefenseMode][classes.CustomMeleeGroups (any number)]
  1408. function get_melee_set()
  1409.     local meleeSet = sets.engaged
  1410.    
  1411.     if not meleeSet then
  1412.         return {}
  1413.     end
  1414.    
  1415.     mote_vars.set_breadcrumbs:append('sets')
  1416.     mote_vars.set_breadcrumbs:append('engaged')
  1417.  
  1418.     if state.CombatForm.has_value and meleeSet[state.CombatForm.value] then
  1419.         meleeSet = meleeSet[state.CombatForm.value]
  1420.         mote_vars.set_breadcrumbs:append(state.CombatForm.value)
  1421.     end
  1422.  
  1423.     if state.CombatWeapon.has_value and meleeSet[state.CombatWeapon.value] then
  1424.         meleeSet = meleeSet[state.CombatWeapon.value]
  1425.         mote_vars.set_breadcrumbs:append(state.CombatWeapon.value)
  1426.     end
  1427.  
  1428.     if meleeSet[state.OffenseMode.current] then
  1429.         meleeSet = meleeSet[state.OffenseMode.current]
  1430.         mote_vars.set_breadcrumbs:append(state.OffenseMode.current)
  1431.     end
  1432.  
  1433.     if meleeSet[state.HybridMode.current] then
  1434.         meleeSet = meleeSet[state.HybridMode.current]
  1435.         mote_vars.set_breadcrumbs:append(state.HybridMode.current)
  1436.     end
  1437.  
  1438.     for _,group in ipairs(classes.CustomMeleeGroups) do
  1439.         if meleeSet[group] then
  1440.             meleeSet = meleeSet[group]
  1441.             mote_vars.set_breadcrumbs:append(group)
  1442.         end
  1443.     end
  1444.  
  1445.     if user_customize_melee_set then
  1446.         meleeSet = user_customize_melee_set(meleeSet)
  1447.     end
  1448.    
  1449.     if job_customize_melee_set then
  1450.         meleeSet = job_customize_melee_set(meleeSet)
  1451.     end
  1452.    
  1453.     if user_job_customize_melee_set then
  1454.         meleeSet = user_job_customize_melee_set(meleeSet)
  1455.     end
  1456.    
  1457.     meleeSet = apply_passive(meleeSet)
  1458.    
  1459.     if state.Capacity.value == true then
  1460.         meleeSet = set_combine(meleeSet, sets.Capacity)
  1461.     end
  1462.    
  1463.     meleeSet = apply_defense(meleeSet)
  1464.     meleeSet = apply_kiting(meleeSet)
  1465.    
  1466.     if silent_check_disable() and state.DefenseMode.value == 'None' then
  1467.         if state.HybridMode.value:contains('MDT') and sets.defense.MDT then
  1468.             meleeSet = set_combine(meleeSet, sets.defense.MDT)
  1469.         elseif sets.defense.PDT then
  1470.             meleeSet = set_combine(meleeSet, sets.defense.PDT)
  1471.         end
  1472.     end
  1473.    
  1474.     if sets.Reive and buffactive['Reive Mark'] then
  1475.         meleeSet = set_combine(meleeSet, sets.Reive)
  1476.     end
  1477.    
  1478.     if (buffactive.sleep or buffactive.Lullaby) and sets.buff.Sleep then
  1479.         meleeSet = set_combine(meleeSet, sets.buff.Sleep)
  1480.     end
  1481.    
  1482.     if buffactive.doom then
  1483.         meleeSet = set_combine(meleeSet, sets.buff.Doom)
  1484.     end
  1485.    
  1486.     if extra_user_customize_melee_set then
  1487.         meleeSet = extra_user_customize_melee_set(meleeSet)
  1488.     end
  1489.    
  1490.     return meleeSet
  1491. end
  1492.  
  1493.  
  1494. -- Returns the appropriate resting set based on current state values.
  1495. -- Set construction order:
  1496. --   sets.resting[state.RestingMode]
  1497. function get_resting_set()
  1498.     local restingSet = sets.resting
  1499.  
  1500.     if not restingSet then
  1501.         return {}
  1502.     end
  1503.  
  1504.     mote_vars.set_breadcrumbs:append('sets')
  1505.     mote_vars.set_breadcrumbs:append('resting')
  1506.  
  1507.     if restingSet[state.RestingMode.current] then
  1508.         restingSet = restingSet[state.RestingMode.current]
  1509.         mote_vars.set_breadcrumbs:append(state.RestingMode.current)
  1510.     end
  1511.  
  1512.     return restingSet
  1513. end
  1514.  
  1515.  
  1516. -------------------------------------------------------------------------------------------------------------------
  1517. -- Functions for constructing default gear sets based on action.
  1518. -------------------------------------------------------------------------------------------------------------------
  1519.  
  1520. -- Get the default precast gear set.
  1521. function get_precast_set(spell, spellMap)
  1522.     -- If there are no precast sets defined, bail out.
  1523.     if not sets.precast then
  1524.         return {}
  1525.     end
  1526.  
  1527.     local equipSet = sets.precast
  1528.  
  1529.     mote_vars.set_breadcrumbs:append('sets')
  1530.     mote_vars.set_breadcrumbs:append('precast')
  1531.    
  1532.     -- Determine base sub-table from type of action being performed.
  1533.    
  1534.     local cat
  1535.    
  1536.     if spell.action_type == 'Magic' then
  1537.         cat = 'FC'
  1538.     elseif spell.action_type == 'Ranged Attack' then
  1539.         cat = (sets.precast.RangedAttack and 'RangedAttack') or 'RA'
  1540.     elseif spell.action_type == 'Ability' then
  1541.         if spell.type == 'WeaponSkill' then
  1542.             cat = 'WS'
  1543.         elseif spell.type == 'JobAbility' then
  1544.             cat = 'JA'
  1545.         else
  1546.             -- Allow fallback to .JA table if spell.type isn't found, for all non-weaponskill abilities.
  1547.             cat = (sets.precast[spell.type] and spell.type) or 'JA'
  1548.         end
  1549.     elseif spell.action_type == 'Item' then
  1550.         cat = 'Item'
  1551.     end
  1552.    
  1553.     -- If no proper sub-category is defined in the job file, bail out.
  1554.     if cat then
  1555.         if equipSet[cat] then
  1556.             equipSet = equipSet[cat]
  1557.             mote_vars.set_breadcrumbs:append(cat)
  1558.         else
  1559.             mote_vars.set_breadcrumbs:clear()
  1560.             return {}
  1561.         end
  1562.     end
  1563.  
  1564.     classes.SkipSkillCheck = false
  1565.     -- Handle automatic selection of set based on spell class/name/map/skill/type.
  1566.     equipSet = select_specific_set(equipSet, spell, spellMap)
  1567.  
  1568.    
  1569.     -- Once we have a named base set, do checks for specialized modes (casting mode, weaponskill mode, etc).
  1570.    
  1571.     if spell.action_type == 'Magic' then
  1572.         if (state.CastingMode.current:contains('SIRD') or state.CastingMode.current:contains('DT')) and not (player.in_combat or being_attacked) then
  1573.         elseif equipSet[state.CastingMode.current] then
  1574.             equipSet = equipSet[state.CastingMode.current]
  1575.             mote_vars.set_breadcrumbs:append(state.CastingMode.current)
  1576.         end
  1577.     elseif spell.type == 'WeaponSkill' then
  1578.         equipSet = get_weaponskill_set(equipSet, spell, spellMap)
  1579.     elseif spell.action_type == 'Ability' then
  1580.         if classes.JAMode and equipSet[classes.JAMode] then
  1581.             equipSet = equipSet[classes.JAMode]
  1582.             mote_vars.set_breadcrumbs:append(classes.JAMode)
  1583.         end
  1584.     elseif spell.action_type == 'Ranged Attack' then
  1585.         equipSet = get_ranged_set(equipSet, spell, spellMap)
  1586.     end
  1587.  
  1588.     -- Update defintions for element-specific gear that may be used.
  1589.     set_elemental_gear(spell)
  1590.    
  1591.     -- Return whatever we've constructed.
  1592.     return equipSet
  1593. end
  1594.  
  1595.  
  1596.  
  1597. -- Get the default midcast gear set.
  1598. -- This builds on sets.midcast.
  1599. function get_midcast_set(spell, spellMap)
  1600.     -- If there are no midcast sets defined, bail out.
  1601.     if not sets.midcast then
  1602.         return {}
  1603.     end
  1604.    
  1605.     local equipSet = sets.midcast
  1606.  
  1607.     mote_vars.set_breadcrumbs:append('sets')
  1608.     mote_vars.set_breadcrumbs:append('midcast')
  1609.    
  1610.     -- Determine base sub-table from type of action being performed.
  1611.     -- Only ranged attacks and items get specific sub-categories here.
  1612.    
  1613.     local cat
  1614.  
  1615.     if spell.action_type == 'Ranged Attack' then
  1616.         cat = (sets.precast.RangedAttack and 'RangedAttack') or 'RA'
  1617.     elseif spell.action_type == 'Item' then
  1618.         cat = 'Item'
  1619.     end
  1620.    
  1621.     -- If no proper sub-category is defined in the job file, bail out.
  1622.     if cat then
  1623.         if equipSet[cat] then
  1624.             equipSet = equipSet[cat]
  1625.             mote_vars.set_breadcrumbs:append(cat)
  1626.         else
  1627.             mote_vars.set_breadcrumbs:clear()
  1628.             return {}
  1629.         end
  1630.     end
  1631.    
  1632.     classes.SkipSkillCheck = classes.NoSkillSpells:contains(spell.english)
  1633.     -- Handle automatic selection of set based on spell class/name/map/skill/type.
  1634.     equipSet = select_specific_set(equipSet, spell, spellMap)
  1635.    
  1636.     -- After the default checks, do checks for specialized modes (casting mode, etc).
  1637.    
  1638.     if spell.action_type == 'Magic' then
  1639.         if equipSet[state.CastingMode.current] then
  1640.             equipSet = equipSet[state.CastingMode.current]
  1641.             mote_vars.set_breadcrumbs:append(state.CastingMode.current)
  1642.         end
  1643.     elseif spell.action_type == 'Ranged Attack' then
  1644.         equipSet = get_ranged_set(equipSet, spell, spellMap)
  1645.     end
  1646.    
  1647.     -- Return whatever we've constructed.
  1648.     return equipSet
  1649. end
  1650.  
  1651.  
  1652. -- Get the default pet midcast gear set.
  1653. -- This is built in sets.midcast.Pet.
  1654. function get_pet_midcast_set(spell, spellMap)
  1655.     -- If there are no midcast sets defined, bail out.
  1656.     if not sets.midcast or not sets.midcast.Pet then
  1657.         return {}
  1658.     end
  1659.  
  1660.     local equipSet = sets.midcast.Pet
  1661.  
  1662.     mote_vars.set_breadcrumbs:append('sets')
  1663.     mote_vars.set_breadcrumbs:append('midcast')
  1664.     mote_vars.set_breadcrumbs:append('Pet')
  1665.  
  1666.     if sets.midcast and sets.midcast.Pet then
  1667.         classes.SkipSkillCheck = false
  1668.         equipSet = select_specific_set(equipSet, spell, spellMap)
  1669.  
  1670.         -- We can only generally be certain about whether the pet's action is
  1671.         -- Magic (ie: it cast a spell of its own volition) or Ability (it performed
  1672.         -- an action at the request of the player).  Allow CastinMode and
  1673.         -- OffenseMode to refine whatever set was selected above.
  1674.        
  1675.         if spell.action_type == 'Magic' then
  1676.             if equipSet[state.CastingMode.current] then
  1677.                 equipSet = equipSet[state.CastingMode.current]
  1678.                 mote_vars.set_breadcrumbs:append(state.CastingMode.current)
  1679.             end
  1680.         elseif spell.action_type == 'Ability' then
  1681.             if equipSet[state.OffenseMode.current] then
  1682.                 equipSet = equipSet[state.OffenseMode.current]
  1683.                 mote_vars.set_breadcrumbs:append(state.OffenseMode.current)
  1684.             end
  1685.         end
  1686.     end
  1687.  
  1688.     return equipSet
  1689. end
  1690.  
  1691.  
  1692. -- Function to handle the logic of selecting the proper weaponskill set.
  1693. function get_weaponskill_set(equipSet, spell, spellMap)
  1694.     -- Custom handling for weaponskills
  1695.     local ws_mode = state.WeaponskillMode.current
  1696.    
  1697.     if ws_mode == 'Match' then
  1698.         -- Weaponskill mode is specified to match, see if we have a weaponskill mode
  1699.         -- corresponding to the current offense mode.  If so, use that.
  1700.         if spell.skill == 'Archery' or spell.skill == 'Marksmanship' then
  1701.             if state.RangedMode.current ~= 'Normal' and state.WeaponskillMode:contains(state.RangedMode.current) then
  1702.                 ws_mode = state.RangedMode.current
  1703.             else
  1704.                 ws_mode = 'Normal'
  1705.             end
  1706.         else
  1707.             if state.OffenseMode.current ~= 'Normal' and state.WeaponskillMode:contains(state.OffenseMode.current) then
  1708.                 ws_mode = state.OffenseMode.current
  1709.             else
  1710.                 ws_mode = 'Normal'
  1711.             end
  1712.         end
  1713.     end
  1714.  
  1715.     local custom_wsmode
  1716.  
  1717.     -- Allow the job file to specify a preferred weaponskill mode
  1718.     if get_custom_wsmode then
  1719.         custom_wsmode = get_custom_wsmode(spell, spellMap, ws_mode)
  1720.     end
  1721.  
  1722.     -- If the job file returned a weaponskill mode, use that.
  1723.     if custom_wsmode then
  1724.         ws_mode = custom_wsmode
  1725.     end
  1726.  
  1727.     if equipSet[ws_mode] then
  1728.         equipSet = equipSet[ws_mode]
  1729.         mote_vars.set_breadcrumbs:append(ws_mode)
  1730.     end
  1731.    
  1732.     return equipSet
  1733. end
  1734.  
  1735.  
  1736. -- Function to handle the logic of selecting the proper ranged set.
  1737. function get_ranged_set(equipSet, spell, spellMap)
  1738.     -- Attach Combat Form and Combat Weapon to set checks
  1739.     if state.CombatForm.has_value and equipSet[state.CombatForm.value] then
  1740.         equipSet = equipSet[state.CombatForm.value]
  1741.         mote_vars.set_breadcrumbs:append(state.CombatForm.value)
  1742.     end
  1743.  
  1744.     if state.CombatWeapon.has_value and equipSet[state.CombatWeapon.value] then
  1745.         equipSet = equipSet[state.CombatWeapon.value]
  1746.         mote_vars.set_breadcrumbs:append(state.CombatWeapon.value)
  1747.     end
  1748.  
  1749.     -- Check for specific mode for ranged attacks (eg: Acc, Att, etc)
  1750.     if equipSet[state.RangedMode.current] then
  1751.         equipSet = equipSet[state.RangedMode.current]
  1752.         mote_vars.set_breadcrumbs:append(state.RangedMode.current)
  1753.     end
  1754.  
  1755.     -- Tack on any additionally specified custom groups, if the sets are defined.
  1756.     for _,group in ipairs(classes.CustomRangedGroups) do
  1757.         if equipSet[group] then
  1758.             equipSet = equipSet[group]
  1759.             mote_vars.set_breadcrumbs:append(group)
  1760.         end
  1761.     end
  1762.  
  1763.     return equipSet
  1764. end
  1765.  
  1766.  
  1767. -------------------------------------------------------------------------------------------------------------------
  1768. -- Functions for optional supplemental gear overriding the default sets defined above.
  1769. -------------------------------------------------------------------------------------------------------------------
  1770.  
  1771. -- Function to apply any active defense set on top of the supplied set
  1772. -- @param baseSet : The set that any currently active defense set will be applied on top of. (gear set table)
  1773.  
  1774. function apply_defense(baseSet)
  1775.     if state.DefenseMode.current ~= 'None' then
  1776.         local defenseSet = sets.defense
  1777.        
  1778.         defenseSet = sets.defense[state[state.DefenseMode.current .. 'DefenseMode'].current] or defenseSet
  1779.  
  1780.         for _,group in ipairs(classes.CustomDefenseGroups) do
  1781.             defenseSet = defenseSet[group] or defenseSet
  1782.         end
  1783.  
  1784.         if sets.Reive and buffactive['Reive Mark'] and sets.Reive.neck == "Adoulin's Refuge +1" then
  1785.             defenseSet = set_combine(defenseSet, sets.Reive)
  1786.         end
  1787.  
  1788.         if user_customize_defense_set then
  1789.             defenseSet = user_customize_defense_set(defenseSet)
  1790.         end
  1791.        
  1792.         if job_customize_defense_set then
  1793.             defenseSet = job_customize_defense_set(defenseSet)
  1794.         end
  1795.        
  1796.         if user_job_customize_defense_set then
  1797.             defenseSet = user_job_customize_defense_set(defenseSet)
  1798.         end
  1799.        
  1800.         if user_job_customize_defense_set then
  1801.             defenseSet = extra_user_customize_defense_set(defenseSet)
  1802.         end
  1803.  
  1804.         baseSet = set_combine(baseSet, defenseSet)
  1805.     end
  1806.    
  1807.     return baseSet
  1808. end
  1809.  
  1810. --Apply a set for special modes where we are engaged or idle, that still allows swapping for other more important things.
  1811. function apply_passive(baseSet)
  1812.     if state.Passive.value ~= 'None' then
  1813.         baseSet = set_combine(baseSet, sets.passive[state.Passive.value])
  1814.     end
  1815.    
  1816.     if user_customize_passive_set then
  1817.         baseSet = user_customize_passive_set(baseSet)
  1818.     end
  1819.    
  1820.     if job_customize_passive_set then
  1821.         baseSet = job_customize_passive_set(baseSet)
  1822.     end
  1823.    
  1824.     if user_job_customize_passive_set then
  1825.         baseSet = user_job_customize_passive_set(baseSet)
  1826.     end
  1827.  
  1828.     return baseSet
  1829. end
  1830.  
  1831. -- Function to add kiting gear on top of the base set if kiting state is true.
  1832. -- @param baseSet : The gear set that the kiting gear will be applied on top of.
  1833. function apply_kiting(baseSet)
  1834.     if sets.Kiting and (state.Kiting.value or (player.status == 'Idle' and moving and state.DefenseMode.value == 'None' and state.Passive.value == 'None' and (state.IdleMode.value == 'Normal' or state.IdleMode.value == 'Sphere' or not (player.in_combat or being_attacked)))) then
  1835.         baseSet = set_combine(baseSet, sets.Kiting)
  1836.     end
  1837.    
  1838.     if user_customize_kiting_set then
  1839.         baseSet = user_customize_kiting_set(baseSet)
  1840.     end
  1841.    
  1842.     if job_customize_kiting_set then
  1843.         baseSet = job_customize_kiting_set(baseSet)
  1844.     end
  1845.    
  1846.     if user_job_customize_kiting_set then
  1847.         baseSet = user_job_customize_kiting_set(baseSet)
  1848.     end
  1849.  
  1850.     return baseSet
  1851. end
  1852.  
  1853. -------------------------------------------------------------------------------------------------------------------
  1854. -- Utility functions for constructing default gear sets.
  1855. -------------------------------------------------------------------------------------------------------------------
  1856.  
  1857. -- Get a spell mapping for the spell.
  1858. function get_spell_map(spell)
  1859.     local defaultSpellMap = classes.SpellMaps[spell.english]
  1860.     local jobSpellMap
  1861.    
  1862.     if job_get_spell_map then
  1863.         jobSpellMap = job_get_spell_map(spell, defaultSpellMap)
  1864.     end
  1865.  
  1866.     return jobSpellMap or defaultSpellMap
  1867. end
  1868.  
  1869.  
  1870. -- Select the equipment set to equip from a given starting table, based on standard
  1871. -- selection order: custom class, spell name, spell map, spell skill, and spell type.
  1872. -- Spell skill and spell type may further refine their selections based on
  1873. -- custom class, spell name and spell map.
  1874. function select_specific_set(equipSet, spell, spellMap)
  1875.     -- Take the determined base equipment set and try to get the simple naming extensions that
  1876.     -- may apply to it (class, spell name, spell map).
  1877.     local namedSet = get_named_set(equipSet, spell, spellMap)
  1878.    
  1879.     -- If no simple naming sub-tables were found, and we simply got back the original equip set,
  1880.     -- check for spell.skill and spell.type, then check the simple naming extensions again.
  1881.     if namedSet == equipSet then
  1882.    
  1883.         if spell.skill and equipSet[spell.skill] and not classes.SkipSkillCheck then
  1884.             namedSet = equipSet[spell.skill]
  1885.             mote_vars.set_breadcrumbs:append(spell.skill)
  1886.         elseif spell.type and equipSet[spell.type] then
  1887.             namedSet = equipSet[spell.type]
  1888.             mote_vars.set_breadcrumbs:append(spell.type)
  1889.         else
  1890.             return equipSet
  1891.         end
  1892.        
  1893.         namedSet = get_named_set(namedSet, spell, spellMap)
  1894.     end
  1895.  
  1896.     return namedSet or equipSet
  1897. end
  1898.  
  1899.  
  1900. -- Simple utility function to handle a portion of the equipment set determination.
  1901. -- It attempts to select a sub-table of the provided equipment set based on the
  1902. -- standard search order of custom class, spell name, and spell map.
  1903. -- If no such set is found, it returns the original base set (equipSet) provided.
  1904. function get_named_set(equipSet, spell, spellMap)
  1905.     if equipSet then
  1906.         if classes.CustomClass and equipSet[classes.CustomClass] then
  1907.             mote_vars.set_breadcrumbs:append(classes.CustomClass)
  1908.             return equipSet[classes.CustomClass]
  1909.         elseif equipSet[spell.english] then
  1910.             mote_vars.set_breadcrumbs:append(spell.english)
  1911.             return equipSet[spell.english]
  1912.         elseif spellMap and equipSet[spellMap] then
  1913.             mote_vars.set_breadcrumbs:append(spellMap)
  1914.             return equipSet[spellMap]
  1915.         else
  1916.             return equipSet
  1917.         end
  1918.     end
  1919. end
  1920.  
  1921.  
  1922. -------------------------------------------------------------------------------------------------------------------
  1923. -- Hooks for other events.
  1924. -------------------------------------------------------------------------------------------------------------------
  1925.  
  1926. -- Called when the player's subjob changes.
  1927. function sub_job_change(newSubjob, oldSubjob)
  1928.     if user_setup then
  1929.         user_setup()
  1930.     end
  1931.    
  1932.     if extra_user_setup then
  1933.         extra_user_setup()
  1934.     end
  1935.    
  1936.     if job_sub_job_change then
  1937.         job_sub_job_change(newSubjob, oldSubjob)
  1938.     end
  1939.    
  1940.     send_command('gs c update')
  1941. end
  1942.  
  1943.  
  1944. -- Called when the player's status changes.
  1945. function status_change(newStatus, oldStatus)
  1946.     -- init a new eventArgs
  1947.     local eventArgs = {handled = false}
  1948.     mote_vars.set_breadcrumbs:clear()
  1949.  
  1950.     if not (newStatus == 'Idle' or newStatus == 'Engaged') then
  1951.         if state.RngHelper.value then
  1952.             send_command('gs rh clear')
  1953.         end
  1954.        
  1955.         if useItem then
  1956.             useItem = false
  1957.             if useItemSlot == 'item' then
  1958.                 windower.send_command('put '..useItemName..' satchel')
  1959.             elseif useItemSlot == 'set' then
  1960.                 local slots = T{}
  1961.                 for slot,item in pairs(sets[useItemName]) do
  1962.                     slots:append(slot)
  1963.                 end
  1964.                 enable(slots)
  1965.                 if player.inventory[useItemName] then
  1966.                     windower.send_command('wait 1;put '..set_to_item(useItemName)..' satchel')
  1967.                 end
  1968.             else
  1969.                 enable(useItemSlot)
  1970.                 if player.inventory[useItemName] then
  1971.                     windower.send_command('wait 1;put '..useItemName..' satchel')
  1972.                 end
  1973.             end
  1974.             add_to_chat(217,"Cancelling using "..useItemName..".")
  1975.             useItemName = ''
  1976.             useItemSlot = ''
  1977.         end
  1978.     end
  1979.    
  1980.     if newStatus == 'Engaged' then
  1981.         update_combat_form()
  1982.     end
  1983.    
  1984.     -- Allow a global function to be called on status change.
  1985.     if user_status_change then
  1986.         user_status_change(newStatus, oldStatus, eventArgs)
  1987.     end
  1988.    
  1989.     -- Then call individual jobs to handle status change events.
  1990.     if not eventArgs.handled then
  1991.         if user_job_status_change then
  1992.             user_job_status_change(newStatus, oldStatus, eventArgs)
  1993.         end
  1994.     end
  1995.    
  1996.     if not eventArgs.handled then
  1997.         if job_status_change then
  1998.             job_status_change(newStatus, oldStatus, eventArgs)
  1999.         end
  2000.     end
  2001.    
  2002.     if extra_user_status_change then
  2003.         extra_user_status_change(newStatus, oldStatus, eventArgs)
  2004.     end
  2005.  
  2006.     -- Handle equipping default gear if the job didn't mark this as handled.
  2007.     if not eventArgs.handled and not midaction() and not pet_midaction() then
  2008.         handle_equipping_gear(newStatus)
  2009.         display_breadcrumbs()
  2010.     end
  2011. end
  2012.  
  2013. -- Handle notifications of general state change.
  2014. function state_change(stateField, newValue, oldValue)
  2015.     if stateField == 'Weapons' then
  2016.         if (newValue:contains('DW') or newValue:contains('Dual')) and not (dualWieldJobs:contains(player.main_job) or (player.sub_job == 'DNC' or player.sub_job == 'NIN')) then
  2017.             local startindex = state.Weapons.index
  2018.             while (state.Weapons.value:contains('DW') or state.Weapons.value:contains('Dual')) and not (dualWieldJobs:contains(player.main_job) or (player.sub_job == 'DNC' or player.sub_job == 'NIN')) do
  2019.                 state.Weapons:cycle()
  2020.                 if startindex == state.Weapons.index then break end
  2021.             end
  2022.             handle_weapons({})
  2023.         elseif sets.weapons[newValue] then
  2024.             equip_weaponset(newValue)
  2025.         elseif newValue == 'None' then
  2026.             enable('main','sub','range','ammo')
  2027.         else
  2028.             state.Weapons:reset()
  2029.             if sets.weapons[state.Weapons.value] then
  2030.                 equip_weaponset(state.Weapons.value)
  2031.             end
  2032.         end
  2033.     elseif stateField == 'RngHelper' then
  2034.         if newValue == true then
  2035.             send_command('gs rh enable')
  2036.         else
  2037.             send_command('gs rh disable')
  2038.         end
  2039.     end
  2040.    
  2041.     if user_job_state_change then
  2042.         user_job_state_change(stateField, newValue, oldValue)
  2043.     end
  2044.    
  2045.     if user_state_change then
  2046.         user_state_change(stateField, newValue, oldValue)
  2047.     end
  2048.    
  2049.     if job_state_change then
  2050.         job_state_change(stateField, newValue, oldValue)
  2051.     end
  2052.    
  2053.     if stateField == 'Rune Element' then
  2054.         send_command('wait .001;gs c DisplayRune')
  2055.     elseif stateField == 'Elemental Mode' then
  2056.         if player.main_job == 'COR' then
  2057.             send_command('wait .001;gs c DisplayShot')
  2058.         else
  2059.             send_command('wait .001;gs c DisplayElement')
  2060.         end
  2061.     elseif stateField:contains('Auto') then
  2062.         tickdelay = 0
  2063.     elseif stateField == 'Capacity' and newValue == 'false' and cprings:contains(player.equipment.left_ring) then
  2064.             enable("left_ring")
  2065.     end
  2066.    
  2067.     if state.DisplayMode.value then update_job_states() end
  2068. end
  2069.  
  2070. -- Called when a player gains or loses a buff.
  2071. -- buff == buff gained or lost
  2072. -- gain == true if the buff was gained, false if it was lost.
  2073. function buff_change(buff, gain)
  2074.     -- Init a new eventArgs
  2075.     local eventArgs = {handled = false}
  2076.  
  2077.     if state.Buff[buff:ucfirst()] ~= nil then
  2078.         state.Buff[buff:ucfirst()] = gain
  2079.     end
  2080.  
  2081.     -- Allow a global function to be called on buff change.
  2082.     if user_buff_change then
  2083.         user_buff_change(buff, gain, eventArgs)
  2084.     end
  2085.    
  2086.     -- Allow jobs to handle buff change events.
  2087.     if not eventArgs.handled then
  2088.         if job_buff_change then
  2089.             job_buff_change(buff, gain, eventArgs)
  2090.         end
  2091.     end
  2092.    
  2093.     if user_job_buff_change then
  2094.         user_job_buff_change(buff, gain, eventArgs)
  2095.     end
  2096.  
  2097.     if S{'sleep','Lullaby'}:contains(buff) and state.CancelStoneskin.value then
  2098.         send_command('cancel stoneskin')
  2099.     end
  2100.    
  2101.     if S{'Commitment','Dedication'}:contains(buff) then
  2102.         if gain and (cprings:contains(player.equipment.left_ring) or xprings:contains(player.equipment.left_ring)) then
  2103.             enable("left_ring")
  2104.            
  2105.             if time_test and player.equipment.left_ring == 'Capacity Ring' then
  2106.                 --local CurrentTime = (os.time(os.date("!*t", os.time())) + time_offset)
  2107.                 local CurrentTime = os.time(os.date("!*t"))
  2108.                 time_test = false
  2109.                 local CapacityOffset = ((get_item_next_use('Capacity Ring').next_use_time) - CurrentTime)
  2110.                 local NegativeCapacityOffset = ((get_item_next_use('Capacity Ring').next_use_time) - CurrentTime) * -1
  2111.                 local CapacityOffsetPlus = CapacityOffset + 900
  2112.                 local CapacityOffsetMinus = CapacityOffset - 900
  2113.                 local NegativeCapacityOffsetPlus =  NegativeCapacityOffset + 900
  2114.                 local NegativeCapacityOffsetMinus = NegativeCapacityOffset - 900
  2115.                 if ((get_item_next_use('Capacity Ring').next_use_time) - (CurrentTime + CapacityOffsetPlus)) > 895 and ((get_item_next_use('Capacity Ring').next_use_time) - (CurrentTime + CapacityOffsetPlus)) < 905 then
  2116.                     windower.add_to_chat(123,"Capacity Ring Used: Your offset is: "..CapacityOffsetPlus.."")
  2117.                 elseif ((get_item_next_use('Capacity Ring').next_use_time) - (CurrentTime + CapacityOffsetMinus)) > 895 and ((get_item_next_use('Capacity Ring').next_use_time) - (CurrentTime + CapacityOffsetMinus)) < 905 then
  2118.                     windower.add_to_chat(123,"Capacity Ring Used: Your offset is: "..CapacityOffsetMinus.."")
  2119.                 elseif ((get_item_next_use('Capacity Ring').next_use_time) - (CurrentTime + NegativeCapacityOffsetPlus)) > 895 and ((get_item_next_use('Capacity Ring').next_use_time) - (CurrentTime + NegativeCapacityOffsetPlus)) < 905 then
  2120.                     windower.add_to_chat(123,"Capacity Ring Used: Your offset is: "..NegativeCapacityOffsetPlus.."")
  2121.                 elseif ((get_item_next_use('Capacity Ring').next_use_time) - (CurrentTime + NegativeCapacityOffsetMinus)) > 895 and ((get_item_next_use('Capacity Ring').next_use_time) - (CurrentTime + NegativeCapacityOffsetMinus)) < 905 then
  2122.                     windower.add_to_chat(123,"Capacity Ring Used: Your offset is: "..CapacityOffsetPlus.."")
  2123.                 else
  2124.                     windower.add_to_chat(123,"Unable to automatically determine your offset")
  2125.                     time_test = true
  2126.                 end
  2127.             end
  2128.            
  2129.         elseif gain and (player.equipment.head == "Guide Beret" or player.equipment.head == "Sprout Beret") then
  2130.             enable("head")
  2131.         end
  2132.     end
  2133.  
  2134.     if (S{'Blink','Third Eye'}:contains(buff) or buff:contains('Copy Image')) and not gain then
  2135.         lastshadow = "None"
  2136.     end
  2137.    
  2138.     if not midaction() and not pet_midaction() then
  2139.         handle_equipping_gear(player.status)
  2140.     end
  2141.    
  2142.     if extra_user_buff_change then
  2143.         extra_user_buff_change(buff, gain, eventArgs)
  2144.     end
  2145.    
  2146.     if state.DisplayMode.value then update_job_states() end
  2147. end
  2148.  
  2149.  
  2150. -- Called when a player gains or loses a pet.
  2151. -- pet == pet gained or lost
  2152. -- gain == true if the pet was gained, false if it was lost.
  2153. function pet_change(pet, gain)
  2154.     -- Init a new eventArgs
  2155.     local eventArgs = {handled = false}
  2156.  
  2157.     -- Allow jobs to handle pet change events.
  2158.     if user_job_pet_change then
  2159.         user_job_pet_change(pet, gain, eventArgs)
  2160.     end
  2161.    
  2162.     if user_pet_change and not not eventArgs.handled then
  2163.         user_pet_change(pet, gain, eventArgs)
  2164.     end
  2165.    
  2166.     if job_pet_change and not eventArgs.handled then
  2167.         job_pet_change(pet, gain, eventArgs)
  2168.     end
  2169.  
  2170.     -- Equip default gear if not handled by the job.
  2171.     if not eventArgs.handled then
  2172.         if not midaction() and not pet_midaction() then handle_equipping_gear(player.status) end
  2173.     end
  2174. end
  2175.  
  2176.  
  2177. -- Called when the player's pet's status changes.
  2178. -- Note that this is also called after pet_change when the pet is released.
  2179. -- As such, don't automatically handle gear equips.  Only do so if directed
  2180. -- to do so by the job.
  2181. function pet_status_change(newStatus, oldStatus)
  2182.     -- Init a new eventArgs
  2183.     local eventArgs = {handled = false}
  2184.  
  2185.     -- Allow jobs to override this code
  2186.     if job_pet_status_change then
  2187.         job_pet_status_change(newStatus, oldStatus, eventArgs)
  2188.     end
  2189.    
  2190.     if not midaction() and not pet_midaction() then handle_equipping_gear(player.status) end
  2191. end
  2192.  
  2193. -------------------------------------------------------------------------------------------------------------------
  2194. -- Debugging functions.
  2195. -------------------------------------------------------------------------------------------------------------------
  2196.  
  2197. -- This is a debugging function that will print the accumulated set selection
  2198. -- breadcrumbs for the default selected set for any given action stage.
  2199. function display_breadcrumbs(spell, spellMap, action)
  2200.     if not _settings.debug_mode then
  2201.         return
  2202.     end
  2203.    
  2204.     local msg = 'Default '
  2205.    
  2206.     if action and spell then
  2207.         msg = msg .. action .. ' set selection for ' .. spell.name
  2208.     end
  2209.    
  2210.     if spellMap then
  2211.         msg = msg .. ' (' .. spellMap .. ')'
  2212.     end
  2213.     msg = msg .. ' : '
  2214.    
  2215.     local cons
  2216.    
  2217.     for _,name in ipairs(mote_vars.set_breadcrumbs) do
  2218.         if not cons then
  2219.             cons = name
  2220.         else
  2221.             if name:contains(' ') or name:contains("'") then
  2222.                 cons = cons .. '["' .. name .. '"]'
  2223.             else
  2224.                 cons = cons .. '.' .. name
  2225.             end
  2226.         end
  2227.     end
  2228.  
  2229.     if cons then
  2230.         if action and cons == ('sets.' .. action) then
  2231.             msg = msg .. "None"
  2232.         else
  2233.             msg = msg .. tostring(cons)
  2234.         end
  2235.         add_to_chat(123, msg)
  2236.     end
  2237. end
  2238.  
  2239. -- Auto-initialize the include - Do this at the bottom so that other user-files can overwrite these functions.
  2240. init_include()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement