diff options
Diffstat (limited to 'Data/DefaultContent/Libraries/addons/addons/libs/actions.lua')
-rw-r--r-- | Data/DefaultContent/Libraries/addons/addons/libs/actions.lua | 625 |
1 files changed, 0 insertions, 625 deletions
diff --git a/Data/DefaultContent/Libraries/addons/addons/libs/actions.lua b/Data/DefaultContent/Libraries/addons/addons/libs/actions.lua deleted file mode 100644 index 14254ce..0000000 --- a/Data/DefaultContent/Libraries/addons/addons/libs/actions.lua +++ /dev/null @@ -1,625 +0,0 @@ ---[[ -A library to make the manipulation of the action packet easier. - -The primary functionality provided here are iterators which allow for -easy traversal of the sub-tables within the packet. Example: - -======================================================================================= -require('actions') - -function event_action(act) - action = Action(act) -- constructor - - -- print out all melee hits to the console - if actionpacket:get_category_string() == 'melee' then - for target in actionpacket:get_targets() do -- target iterator - for action in target:get_actions() do -- subaction iterator - if action.message == 1 then -- 1 is the code for messages - print(string.format("%s hit %s for %d damage", - actionpacket:get_actor_name(), target:get_name(), action.param)) - end - end - end - end -end -======================================================================================= - -]] - -_libs = _libs or {} - -require('tables') - -local table = _libs.tables -local res = require('resources') - -_libs.actions = true - -local category_strings = { - 'melee', - 'ranged_finish', - 'weaponskill_finish', - 'spell_finish', - 'item_finish', - 'job_ability', - 'weaponskill_begin', - 'casting_begin', - 'item_begin', - 'unknown', - 'mob_tp_finish', - 'ranged_begin', - 'avatar_tp_finish', - 'job_ability_unblinkable', - 'job_ability_run' -} - --- ActionPacket operations -ActionPacket = {} - -local actionpacket = {} --- Constructor for Actions. --- Usage: actionpacket = ActionPacket(raw_action) - -function ActionPacket.new(a) - if a == nil then - return - end - - local new_instance = {} - new_instance.raw = a - - return setmetatable(new_instance, {__index = function(t, k) if rawget(t, k) ~= nil then return t[k] else return actionpacket[k] end end}) -end - -local function act_to_string(original,act) - if type(act) ~= 'table' then return act end - - function assemble_bit_packed(init,val,initial_length,final_length) - if not init then return init end - - if type(val) == 'boolean' then - if val then val = 1 else val = 0 end - elseif type(val) ~= 'number' then - return false - end - local bits = initial_length%8 - local byte_length = math.ceil(final_length/8) - - local out_val = 0 - if bits > 0 then - out_val = init:byte(#init) -- Initialize out_val to the remainder in the active byte. - init = init:sub(1,#init-1) -- Take off the active byte - end - out_val = out_val + val*2^bits -- left-shift val by the appropriate amount and add it to the remainder (now the lsb-s in val) - - while out_val > 0 do - init = init..string.char(out_val%256) - out_val = math.floor(out_val/256) - end - while #init < byte_length do - init = init..string.char(0) - end - return init - end - - local react = assemble_bit_packed(original:sub(1,4),act.size,32,40) - react = assemble_bit_packed(react,act.actor_id,40,72) - react = assemble_bit_packed(react,act.target_count,72,82) - react = assemble_bit_packed(react,act.category,82,86) - react = assemble_bit_packed(react,act.param,86,102) - react = assemble_bit_packed(react,act.unknown,102,118) - react = assemble_bit_packed(react,act.recast,118,150) - - local offset = 150 - for i = 1,act.target_count do - react = assemble_bit_packed(react,act.targets[i].id,offset,offset+32) - react = assemble_bit_packed(react,act.targets[i].action_count,offset+32,offset+36) - offset = offset + 36 - for n = 1,act.targets[i].action_count do - react = assemble_bit_packed(react,act.targets[i].actions[n].reaction,offset,offset+5) - react = assemble_bit_packed(react,act.targets[i].actions[n].animation,offset+5,offset+17) - react = assemble_bit_packed(react,act.targets[i].actions[n].effect,offset+17,offset+21) - react = assemble_bit_packed(react,act.targets[i].actions[n].stagger,offset+21,offset+24) - react = assemble_bit_packed(react,act.targets[i].actions[n].knockback,offset+24,offset+27) - react = assemble_bit_packed(react,act.targets[i].actions[n].param,offset+27,offset+44) - react = assemble_bit_packed(react,act.targets[i].actions[n].message,offset+44,offset+54) - react = assemble_bit_packed(react,act.targets[i].actions[n].unknown,offset+54,offset+85) - - react = assemble_bit_packed(react,act.targets[i].actions[n].has_add_effect,offset+85,offset+86) - offset = offset + 86 - if act.targets[i].actions[n].has_add_effect then - react = assemble_bit_packed(react,act.targets[i].actions[n].add_effect_animation,offset,offset+6) - react = assemble_bit_packed(react,act.targets[i].actions[n].add_effect_effect,offset+6,offset+10) - react = assemble_bit_packed(react,act.targets[i].actions[n].add_effect_param,offset+10,offset+27) - react = assemble_bit_packed(react,act.targets[i].actions[n].add_effect_message,offset+27,offset+37) - offset = offset + 37 - end - react = assemble_bit_packed(react,act.targets[i].actions[n].has_spike_effect,offset,offset+1) - offset = offset + 1 - if act.targets[i].actions[n].has_spike_effect then - react = assemble_bit_packed(react,act.targets[i].actions[n].spike_effect_animation,offset,offset+6) - react = assemble_bit_packed(react,act.targets[i].actions[n].spike_effect_effect,offset+6,offset+10) - react = assemble_bit_packed(react,act.targets[i].actions[n].spike_effect_param,offset+10,offset+24) - react = assemble_bit_packed(react,act.targets[i].actions[n].spike_effect_message,offset+24,offset+34) - offset = offset + 34 - end - end - end - if react then - while #react < #original do - react = react..original:sub(#react+1,#react+1) - end - else - print('Action Library failure in '..(_addon.name or 'Unknown Addon')..': Invalid Act table returned.') - end - return react -end - --- Opens a listener event for the action packet at the incoming chunk level before modifications. --- Passes in the documented act structures for the original and modified packets. --- If a table is returned, the library will treat it as a modified act table and recompose the packet string from it. --- If an invalid act table is passed, it will silently fail to be returned. -function ActionPacket.open_listener(funct) - if not funct or type(funct) ~= 'function' then return end - local id = windower.register_event('incoming chunk',function(id, org, modi, is_injected, is_blocked) - if id == 0x28 then - local act_org = windower.packets.parse_action(org) - act_org.size = org:byte(5) - local act_mod = windower.packets.parse_action(modi) - act_mod.size = modi:byte(5) - return act_to_string(org,funct(act_org,act_mod)) - end - end) - return id -end - -function ActionPacket.close_listener(id) - if not id or type(id) ~= 'number' then return end - windower.unregister_event(id) -end - - -local actor_animation_twoCC = { - wh='White Magic', - bk='Black Magic', - bl='Blue Magic', - sm='Summoning Magic', - te='TP Move', - ['k0']='Melee Attack', - ['lg']='Ranged Attack', - } - -function actionpacket:get_animation_string() - return actor_animation_twoCC[string.char(actor_animation_twoCC[self.raw['unknown']]%256,math.floor(actor_animation_twoCC[self.raw['unknown']]/256))] -end - - -function actionpacket:get_category_string() - return category_strings[self.raw['category']] -end - -function actionpacket:get_spell() - local info = self:get_targets()():get_actions()():get_basic_info() - if rawget(info,'resource') and rawget(info,'spell_id') and rawget(rawget(res,rawget(info,'resource')),rawget(info,'spell_id')) then - local copied_line = {} - for i,v in pairs(rawget(rawget(res,rawget(info,'resource')),rawget(info,'spell_id'))) do - rawset(copied_line,i,v) - end - setmetatable(copied_line,getmetatable(res[rawget(info,'resource')][rawget(info,'spell_id')])) - return copied_line - end -end - --- Returns the name of this actor if there is one -function actionpacket:get_actor_name() - local mob = windower.ffxi.get_mob_by_id(self.raw['actor_id']) - - if mob then - return mob['name'] - else - return nil - end -end - ---Returns the id of the actor -function actionpacket:get_id() - return self.raw['actor_id'] -end - --- Returns an iterator for this actionpacket's targets -function actionpacket:get_targets() - local targets = self.raw['targets'] - local target_count = self.raw['target_count'] - local i = 0 - return function () - i = i + 1 - if i <= target_count then - return Target(self.raw['category'],self.raw['param'],targets[i]) - end - end -end - -local target = {} - --- Constructor for target wrapper -function Target(category,top_level_param,t) - if t == nil then - return - end - - local new_instance = {} - new_instance.raw = t - new_instance.category = category - new_instance.top_level_param = top_level_param - new_instance.id = t.id - - return setmetatable(new_instance, {__index = function (t, k) if rawget(t, k) ~= nil then return t[k] else return target[k] end end}) -end - --- Returns an iterator for this target's actions -function target:get_actions() - local action_count = self.raw['action_count'] - local i = 0 - return function () - i = i + 1 - if i <= action_count then - return Action(self.category,self.top_level_param,self.raw['actions'][i]) - end - end -end - --- Returns the name of this target if there is one -function target:get_name() - local mob = windower.ffxi.get_mob_by_id(self.raw['id']) - - if mob then - return mob['name'] - else - return nil - end -end - -local reaction_strings = { - [1] = 'evade', - [2] = 'parry', - [4] = 'block/guard', - [8] = 'hit' - -- 12 = blocked? - } - -local animation_strings = { - [0] = 'main hand', - [1] = 'off hand', - [2] = 'left kick', - [3] = 'right kick', - [4] = 'daken throw' - } - -local effect_strings = { - [2] = 'critical hit' - } - -local stagger_strings = { - } - -local action = {} - -function Action(category,top_level_param,t) - if category == nil or t == nil then - return - end - - local new_instance = {} - new_instance.raw = t - new_instance.raw.category = category_strings[category] or category - new_instance.raw.top_level_param = top_level_param - - return setmetatable(new_instance, {__index = function (t, k) if rawget(t, k) ~= nil then return t[k] else return action[k] or rawget(rawget(t,'raw'),k) end end}) -end - -function action:get_basic_info() - local reaction = self:get_reaction_string() - local animation = self:get_animation_string() - local effect = self:get_effect_string() - local stagger = self:get_stagger_string() - local message_id = self:get_message_id() - - local param, resource, spell_id, interruption, conclusion = self:get_spell() - - return {reaction = reaction, animation = animation, effect=effect, message_id = message_id, - stagger = stagger, param = param, resource = resource, spell_id = spell_id, - interruption = interruption, conclusion = conclusion} -end - -function action:get_reaction_string() - local reaction = rawget(rawget(self,'raw'),'reaction') - return rawget(reaction_strings,reaction) or reaction -end - -function action:get_animation_string() - local animation = rawget(rawget(self,'raw'),'animation') - return rawget(animation_strings,animation) or animation -end - -function action:get_effect_string() - local effect = rawget(rawget(self,'raw'),'effect') - return rawget(effect_strings,effect) or effect -end - -function action:get_stagger_string() - local stagger = rawget(rawget(self,'raw'),'stagger') - return rawget(stagger_strings,stagger) or stagger -end - -local cat_to_res_map = {['weaponskill_finish']='weapon_skills', ['spell_finish']='spells', - ['item_finish']='items', ['job_ability']='job_abilities', ['weaponskill_begin']='weapon_skills', - ['casting_begin']='spells', ['item_begin']='items', ['mob_tp_finish']='monster_abilities', - ['avatar_tp_finish']='job_abilities', ['job_ability_unblinkable']='job_abilities', - ['job_ability_run']='job_abilities'} -local begin_categories = {['weaponskill_begin']=true, ['casting_begin']=true, ['item_begin']=true, ['ranged_begin']=true} -local finish_categories = {['melee']=true,['ranged_finish']=true,['weaponskill_finish']=true, ['spell_finish']=true, ['item_finish']=true, - ['job_ability']=true, ['mob_tp_finish']=true, ['avatar_tp_finish']=true, ['job_ability_unblinkable']=true, - ['job_ability_run']=true} -local msg_id_to_conclusion_map = { - [26] = {subject="target", verb="gains", objects={"HP","MP"} }, - [31] = {subject="target", verb="loses", objects={"shadows"} }, - [112] = {subject="target", verb="count", objects={"doom"} }, - [120] = {subject="actor", verb="gains", objects={"Gil"} }, - [132] = {subject="target", verb="steals", objects={"HP"} }, - [133] = {subject="actor", verb="steals", objects={"Petra"} }, - [152] = {subject="actor", verb="gains", objects={"MP"} }, - [229] = {subject="target", verb="loses", objects={"HP"} }, - [231] = {subject="actor", verb="loses", objects={"effects"} }, - [530] = {subject="target", verb="count", objects={"petrify"} }, -- Gradual Petrify - [557] = {subject="actor", verb="gains", objects={"Alexandrite"} }, -- Using a pouch - [560] = {subject="actor", verb="gains", objects={"FMs"} }, -- No Foot Rise - [572] = {subject="actor", verb="steals", objects={"ailments"} }, -- Sacrifice - [585] = {subject="actor", verb="has", objects={"enmity"} }, -- Libra with actor - [586] = {subject="target", verb="has", objects={"enmity"} }, -- Libra without actor - [674] = {subject="actor", verb="gains", objects={"items"} }, -- Scavenge - [730] = {subject="target", verb="has", objects={"TP"} }, - } -local expandable = {} -expandable[{1, 2, 67, 77, 110,157, - 163,185,196,197,223,252, - 264,265,288,289,290,291, - 292,293,294,295,296,297, - 298,299,300,301,302,317, - 352,353,379,419,522,576, - 577,648,650,732,767,768}] = {subject="target", verb="loses", objects={"HP"} } -expandable[{122,167,383}] = {subject="actor", verb="gains", objects={"HP"} } -expandable[{7, 24, 102,103,238,263, - 306,318,357,367,373,382,384, - 385,386,387,388,389,390,391, - 392,393,394,395,396,397,398, - 539,587,606,651,769,770}] = {subject="target", verb="gains", objects={"HP"} } -expandable[{25, 224,276,358,451,588}] = {subject="target", verb="gains", objects={"MP"} } -expandable[{161,187,227,274,281}] = {subject="actor", verb="steals", objects={"HP"} } -expandable[{165,226,454,652}] = {subject="actor", verb="steals", objects={"TP"} } -expandable[{162,225,228,275,366}] = {subject="actor", verb="steals", objects={"MP"} } -expandable[{362,363}] = {subject="target", verb="loses", objects={"TP"} } -expandable[{369,403,417}] = {subject="actor", verb="steals", objects={"attributes"} } -expandable[{370,404,642}] = {subject="actor", verb="steals", objects={"effects"} } -expandable[{400,570,571,589,607}] = {subject="target", verb="loses", objects={"ailments"} } -expandable[{401,405,644}] = {subject="target", verb="loses", objects={"effects"} } -expandable[{409,452,537}] = {subject="target", verb="gains", objects={"TP"} } -expandable[{519,520,521,591}] = {subject="target", verb="gains", objects={"daze"} } -expandable[{14, 535}] = {subject="actor", verb="loses", object={"shadows"} } -expandable[{603,608}] = {subject="target", verb="gains", objects={"TH"} } -expandable[{33, 44, 536,}] = {subject="actor", verb="loses", objects={"HP"} } -for ids,tab in pairs(expandable) do - for _,id in pairs(ids) do - msg_id_to_conclusion_map[id] = tab - end -end -local function msg_id_to_conclusion(msg_id) - return rawget(msg_id_to_conclusion_map,msg_id) or false -end - -function action:get_spell() - local category = rawget(rawget(self,'raw'),'category') - -- It's far more accurate to filter by the resources line. - - local function fieldsearch(message_id) - if not message_id or not res.action_messages[message_id] or not res.action_messages[message_id].en then return false end - local fields = {} - res.action_messages[message_id].en:gsub("${(.-)}", function(a) if a ~= "actor" and a ~= "target" and a ~= 'lb' then rawset(fields,a,true) end end) - return fields - end - - local message_id = self:get_message_id() - local fields = fieldsearch(message_id) - local param = rawget(finish_categories, category) and rawget(rawget(self, 'raw'), 'param') - local spell_id = rawget(begin_categories, category) and rawget(rawget(self, 'raw'), 'param') or - rawget(finish_categories, category) and rawget(rawget(self, 'raw'), 'top_level_param') - local interruption = rawget(begin_categories, category) and rawget(rawget(self, 'raw'), 'top_level_param') == 28787 - if interruption == nil then interruption = false end - - local conclusion = msg_id_to_conclusion(message_id) - - local resource - if not fields or message_id == 31 then - -- If there is no message, assume the resources type based on the category. - if category == 'weaponskill_begin' and spell_id <= 256 then - resource = 'weapon_skills' - elseif category == 'weaponskill_begin' then - resource = 'monster_abilities' - else - resource = rawget(cat_to_res_map,category) or false - end - else - local msgID_to_res_map = { - [244] = 'job_abilities', -- Mug - [328] = 'job_abilities', -- BPs that are out of range - } - -- If there is a message, interpret the fields. - resource = msgID_to_res_map[message_id] or fields.spell and 'spells' or - fields.weapon_skill and spell_id <= 256 and 'weapon_skills' or - fields.weapon_skill and spell_id > 256 and 'monster_abilities' or - fields.ability and 'job_abilities' or - fields.item and 'items' or rawget(cat_to_res_map,category) - local msgID_to_spell_id_map = { - [240] = 43, -- Hide - [241] = 43, -- Hide failing - [303] = 74, -- Divine Seal - [304] = 75, -- Elemental Seal - [305] = 76, -- Trick Attack - [311] = 79, -- Cover - } - spell_id = msgID_to_spell_id_map[message_id] or spell_id - end - - -- param will be a number or false - -- resource will be a string or false - -- spell_id will either be a number or false - -- interruption will be true or false - -- conclusion will either be a table or false - - return param, resource, spell_id, interruption, conclusion -end - -function action:get_message_id() - local message_id = rawget(rawget(self,'raw'),'message') - return message_id or 0 -end - ----------------------------------------- Additional Effects ---------------------------------------- -local add_effect_animation_strings = {} - -add_effect_animation_strings['melee'] = { - [1] = 'enfire', - [2] = 'enblizzard', - [3] = 'enaero', - [4] = 'enstone', - [5] = 'enthunder', - [6] = 'enwater', - [7] = 'enlight', - [8] = 'endark', - [12] = 'enblind', - [14] = 'enpetrify', - [21] = 'endrain', - [22] = 'enaspir', - [23] = 'enhaste', - } - -add_effect_animation_strings['ranged_finish'] = add_effect_animation_strings['melee'] - -add_effect_animation_strings['weaponskill_finish'] = { - [1] = 'light', - [2] = 'darkness', - [3] = 'gravitation', - [4] = 'fragmentation', - [5] = 'distortion', - [6] = 'fusion', - [7] = 'compression', - [8] = 'liquefaction', - [9] = 'induration', - [10] = 'reverberation', - [11] = 'transfixion', - [12] = 'scission', - [13] = 'detonation', - [14] = 'impaction', - [15] = 'radiance', - [16] = 'umbra', - } - -add_effect_animation_strings['spell_finish'] = add_effect_animation_strings['weaponskill_finish'] -add_effect_animation_strings['mob_tp_finish'] = add_effect_animation_strings['weaponskill_finish'] -add_effect_animation_strings['avatar_tp_finish'] = add_effect_animation_strings['weaponskill_finish'] - -local add_effect_effect_strings = {} - -function action:get_add_effect() - if not rawget(rawget(self,'raw'),'has_add_effect') then return false end - local animation = self:get_add_effect_animation_string() - local effect = self:get_add_effect_effect_string() - local param = rawget(rawget(self,'raw'),'add_effect_param') - local message_id = rawget(rawget(self,'raw'),'add_effect_message') - local conclusion = msg_id_to_conclusion(message_id) - return {animation = animation, effect = effect, param = param, - message_id = message_id,conclusion = conclusion} -end - -function action:get_add_effect_animation_string() - local add_effect_animation = rawget(rawget(self,'raw'),'add_effect_animation') - local add_eff_animation_tab = rawget(add_effect_animation_strings,rawget(rawget(self,'raw'),'category')) - return add_eff_animation_tab and rawget(add_eff_animation_tab,add_effect_animation) or add_effect_animation -end - -function action:get_add_effect_effect_string() - local add_effect_effect = rawget(rawget(self,'raw'),'add_effect_effect') - return rawget(add_effect_effect_strings,add_effect_effect) or add_effect_effect -end - -function action:get_add_effect_conclusion() - return msg_id_to_conclusion(rawget(rawget(self,'raw'),'add_effect_message')) -end - - -------------------------------------------- Spike Effects ------------------------------------------ -local spike_effect_animation_strings = { - [1] = 'blaze spikes', - [2] = 'ice spikes', - [3] = 'dread spikes', - [4] = 'water spikes', - [5] = 'shock spikes', - [6] = 'reprisal', - [7] = 'wind spikes', - [8] = 'stone spikes', - [63] = 'counter', - } - -local spike_effect_effect_strings = { - } -function action:get_spike_effect() - if not rawget(rawget(self,'raw'),'has_spike_effect') then return false end - local effect = self:get_spike_effect_effect_string() - local animation = self:get_spike_effect_animation_string() - local param = rawget(rawget(self,'raw'),'spike_effect_param') - local message_id = rawget(rawget(self,'raw'),'spike_effect_message') - local conclusion = msg_id_to_conclusion(message_id) - return {animation = animation, effect = effect, param = param, - message_id = message_id,conclusion = conclusion} -end - -function action:get_spike_effect_effect_string() - local spike_effect_effect = rawget(rawget(self,'raw'),'spike_effect_effect') - return rawget(spike_effect_effect_strings,spike_effect_effect) or spike_effect_effect -end - -function action:get_spike_effect_animation_string() - local spike_effect_animation = rawget(rawget(self,'raw'),'spike_effect_animation') - return rawget(spike_effect_animation_strings,spike_effect_animation) or spike_effect_animation -end - -function action:get_additional_effect_conclusion() - return msg_id_to_conclusion(rawget(rawget(self,'raw'),'spike_effect_message')) -end - ---[[ -Copyright © 2013, Suji -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of actions nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL SUJI BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -]] |