diff options
Diffstat (limited to 'Data/BuiltIn/Libraries/lua-addons/addons/GearSwap/libs/Mote-TreasureHunter.lua')
-rw-r--r-- | Data/BuiltIn/Libraries/lua-addons/addons/GearSwap/libs/Mote-TreasureHunter.lua | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/Data/BuiltIn/Libraries/lua-addons/addons/GearSwap/libs/Mote-TreasureHunter.lua b/Data/BuiltIn/Libraries/lua-addons/addons/GearSwap/libs/Mote-TreasureHunter.lua new file mode 100644 index 0000000..d1fd52a --- /dev/null +++ b/Data/BuiltIn/Libraries/lua-addons/addons/GearSwap/libs/Mote-TreasureHunter.lua @@ -0,0 +1,297 @@ +------------------------------------------------------------------------------------------------------------------- +-- Utility include for applying and tracking Treasure Hunter effects. +-- +-- Include this if you want a means of applying TH on the first contact +-- with a mob, then resume using normal gear. +-- Thf also has modes to use TH gear for SATA and for keeping it on fulltime. +-- +-- Command: include('Mote-TreasureHunter') +-- Place this in your job_setup() function, or user_setup() function if using +-- a sidecar file, or get_sets() function if your job file isn't based +-- on my includes. +-- Be sure to define your own sets.TreasureHunter gear set after the include. +-- If using a job file based on my includes, simply place it in the +-- standard init_gear_sets() function. +-- +-- If you define TH gear sets for common actions (eg: Provoke, Box Step, etc), +-- then make sure they are accounted for in a th_action_check function +-- (signature: th_action_check(category, param)) in the job file. It's passed +-- category and param value for actions the user takes, and if it returns true, +-- that means that it's considered a valid tagging action. +-- +-- If using this in a job file that isn't based on my includes, you must +-- handle cycling the options values on your own, unless you also include +-- Mote-SelfCommands. +-- +-- The job file must handle the 'update' self-command (gs c update auto). +-- This is automatically handled if using my includes, but must be ensured +-- if being used with a user-built job file. +-- When called, it merely needs to equip standard melee gear for the current +-- configuration. +-- +-- Create a macro or keybind to cycle the Treasure Mode value: +-- gs c cycle TreasureMode +------------------------------------------------------------------------------------------------------------------- + + +------------------------------------------------------------------------------------------------------------------- +-- Setup vars and events when first running the include. +------------------------------------------------------------------------------------------------------------------- + +-- Ensure base tables are defined +options = options or {} +state = state or {} +info = info or {} +state.TreasureMode = M{['description']='Treasure Mode'} + +-- TH mode handling +if player.main_job == 'THF' then + state.TreasureMode:options('None','Tag','SATA','Fulltime') + state.TreasureMode:set('Tag') +else + state.TreasureMode:options('None','Tag') +end + +-- Tracking vars for TH. +info.tagged_mobs = T{} +info.last_player_target_index = 0 +state.th_gear_is_locked = false + +-- Required gear set. Expand this in the job file when defining sets. +sets.TreasureHunter = {} + +-- Event registration is done at the bottom of this file. + + +------------------------------------------------------------------------------------------------------------------- +-- User-callable functions for TH handling utility. +------------------------------------------------------------------------------------------------------------------- + +-- Can call to force a status refresh. +-- Also displays the current tagged mob table if in debug mode. +function th_update(cmdParams, eventArgs) + if (cmdParams and cmdParams[1] == 'user') or not cmdParams then + TH_for_first_hit() + + if _settings.debug_mode then + print_set(info.tagged_mobs, 'Tagged mobs') + end + end +end + + +------------------------------------------------------------------------------------------------------------------- +-- Local functions to support TH handling. +------------------------------------------------------------------------------------------------------------------- + +-- Set locked TH flag to true, and disable relevant gear slots. +function lock_TH() + state.th_gear_is_locked = true + local slots = T{} + for slot,item in pairs(sets.TreasureHunter) do + slots:append(slot) + end + disable(slots) +end + + +-- Set locked TH flag to false, and enable relevant gear slots. +function unlock_TH() + state.th_gear_is_locked = false + local slots = T{} + for slot,item in pairs(sets.TreasureHunter) do + slots:append(slot) + end + enable(slots) + send_command('gs c update auto') +end + + +-- For any active TH mode, if we haven't already tagged this target, equip TH gear and lock slots until we manage to hit it. +function TH_for_first_hit() + if player.status == 'Engaged' and state.TreasureMode.value ~= 'None' then + if not info.tagged_mobs[player.target.id] then + if _settings.debug_mode then add_to_chat(123,'Prepping for first hit on '..tostring(player.target.id)..'.') end + equip(sets.TreasureHunter) + lock_TH() + elseif state.th_gear_is_locked then + if _settings.debug_mode then add_to_chat(123,'Target '..player.target.id..' has been tagged. Unlocking.') end + unlock_TH() + else + if _settings.debug_mode then add_to_chat(123,'Prepping for first hit on '..player.target.id..'. Target has already been tagged.') end + end + else + unlock_TH() + end +end + + +------------------------------------------------------------------------------------------------------------------- +-- Event handlers to allow tracking TH application. +------------------------------------------------------------------------------------------------------------------- + +-- On engaging a mob, attempt to add TH gear. For any other status change, unlock TH gear slots. +function on_status_change_for_th(new_status_id, old_status_id) + if gearswap.gearswap_disabled or T{2,3,4}:contains(old_status_id) or T{2,3,4}:contains(new_status_id) then return end + + local new_status = gearswap.res.statuses[new_status_id].english + local old_status = gearswap.res.statuses[old_status_id].english + + if new_status == 'Engaged' then + if _settings.debug_mode then add_to_chat(123,'Engaging '..player.target.id..'.') end + info.last_player_target_index = player.target.index + TH_for_first_hit() + elseif old_status == 'Engaged' then + if _settings.debug_mode and state.th_gear_is_locked then add_to_chat(123,'Disengaging. Unlocking TH.') end + info.last_player_target_index = 0 + unlock_TH() + end +end + + +-- On changing targets, attempt to add TH gear. +function on_target_change_for_th(new_index, old_index) + -- Only care about changing targets while we're engaged, either manually or via current target death. + if player.status == 'Engaged' then + -- If the current player.target is the same as the new mob then we're actually + -- engaged with it. + -- If it's different than the last known mob, then we've actually changed targets. + if player.target.index == new_index and new_index ~= info.last_player_target_index then + if _settings.debug_mode then add_to_chat(123,'Changing target to '..player.target.id..'.') end + info.last_player_target_index = player.target.index + TH_for_first_hit() + end + end +end + + +-- On any action event, mark mobs that we tag with TH. Also, update the last time tagged mobs were acted on. +function on_action_for_th(action) + --add_to_chat(123,'cat='..action.category..',param='..action.param) + -- If player takes action, adjust TH tagging information + if state.TreasureMode.value ~= 'None' then + if action.actor_id == player.id then + -- category == 1=melee, 2=ranged, 3=weaponskill, 4=spell, 6=job ability, 14=unblinkable JA + if state.TreasureMode.value == 'Fulltime' or + (state.TreasureMode.value == 'SATA' and (action.category == 1 or ((state.Buff['Sneak Attack'] or state.Buff['Trick Attack']) and action.category == 3))) or + (state.TreasureMode.value == 'Tag' and action.category == 1 and state.th_gear_is_locked) or -- Tagging with a melee hit + (th_action_check and th_action_check(action.category, action.param)) -- Any user-specified tagging actions + then + for index,target in pairs(action.targets) do + if not info.tagged_mobs[target.id] and _settings.debug_mode then + add_to_chat(123,'Mob '..target.id..' hit. Adding to tagged mobs table.') + end + info.tagged_mobs[target.id] = os.time() + end + + if state.th_gear_is_locked then + unlock_TH() + end + end + elseif info.tagged_mobs[action.actor_id] then + -- If mob acts, keep an update of last action time for TH bookkeeping + info.tagged_mobs[action.actor_id] = os.time() + else + -- If anyone else acts, check if any of the targets are our tagged mobs + for index,target in pairs(action.targets) do + if info.tagged_mobs[target.id] then + info.tagged_mobs[target.id] = os.time() + end + end + end + end + + cleanup_tagged_mobs() +end + + +-- Need to use this event handler to listen for deaths in case Battlemod is loaded, +-- because Battlemod blocks the 'action message' event. +-- +-- This function removes mobs from our tracking table when they die. +function on_incoming_chunk_for_th(id, data, modified, injected, blocked) + if id == 0x29 then + local target_id = data:unpack('I',0x09) + local message_id = data:unpack('H',0x19)%32768 + + -- Remove mobs that die from our tagged mobs list. + if info.tagged_mobs[target_id] then + -- 6 == actor defeats target + -- 20 == target falls to the ground + if message_id == 6 or message_id == 20 then + if _settings.debug_mode then add_to_chat(123,'Mob '..target_id..' died. Removing from tagged mobs table.') end + info.tagged_mobs[target_id] = nil + end + end + end +end + + +-- Clear out the entire tagged mobs table when zoning. +function on_zone_change_for_th(new_zone, old_zone) + if _settings.debug_mode then add_to_chat(123,'Zoning. Clearing tagged mobs table.') end + info.tagged_mobs:clear() +end + + +-- Save the existing function, if it exists, and call it after our own handling. +if job_state_change then + job_state_change_via_th = job_state_change +end + + +-- Called if we change any user state fields. +function job_state_change(stateField, newValue, oldValue) + if stateField == 'Treasure Mode' then + if newValue == 'None' and state.th_gear_is_locked then + if _settings.debug_mode then add_to_chat(123,'TH Mode set to None. Unlocking gear.') end + unlock_TH() + elseif oldValue == 'None' then + TH_for_first_hit() + end + end + + if job_state_change_via_th then + job_state_change_via_th(stateField, newValue, oldValue) + end +end + +------------------------------------------------------------------------------------------------------------------- +-- Extra utility functions. +------------------------------------------------------------------------------------------------------------------- + +-- Remove mobs that we've marked as tagged with TH if we haven't seen any activity from or on them +-- for over 3 minutes. This is to handle deagros, player deaths, or other random stuff where the +-- mob is lost, but doesn't die. +function cleanup_tagged_mobs() + -- If it's been more than 3 minutes since an action on or by a tagged mob, + -- remove them from the tagged mobs list. + local current_time = os.time() + local remove_mobs = S{} + -- Search list and flag old entries. + for target_id,action_time in pairs(info.tagged_mobs) do + local time_since_last_action = current_time - action_time + if time_since_last_action > 180 then + remove_mobs:add(target_id) + if _settings.debug_mode then add_to_chat(123,'Over 3 minutes since last action on mob '..target_id..'. Removing from tagged mobs list.') end + end + end + -- Clean out mobs flagged for removal. + for mob_id,_ in pairs(remove_mobs) do + info.tagged_mobs[mob_id] = nil + end +end + + +------------------------------------------------------------------------------------------------------------------- +-- Event function registration calls. +-- Can call these now that the above functions have been defined. +------------------------------------------------------------------------------------------------------------------- + +-- Register events to allow us to manage TH application. +windower.register_event('status change', on_status_change_for_th) +windower.register_event('target change', on_target_change_for_th) +windower.raw_register_event('action', on_action_for_th) +windower.raw_register_event('incoming chunk', on_incoming_chunk_for_th) +windower.raw_register_event('zone change', on_zone_change_for_th) + |