diff options
Diffstat (limited to 'Data/BuiltIn/Libraries/lua-addons/addons/Rhombus/Rhombus.lua')
-rw-r--r-- | Data/BuiltIn/Libraries/lua-addons/addons/Rhombus/Rhombus.lua | 596 |
1 files changed, 596 insertions, 0 deletions
diff --git a/Data/BuiltIn/Libraries/lua-addons/addons/Rhombus/Rhombus.lua b/Data/BuiltIn/Libraries/lua-addons/addons/Rhombus/Rhombus.lua new file mode 100644 index 0000000..1622b43 --- /dev/null +++ b/Data/BuiltIn/Libraries/lua-addons/addons/Rhombus/Rhombus.lua @@ -0,0 +1,596 @@ +--[[Copyright © 2014-2015, trv +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 Rhombus 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 trv 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.--]] + +_addon.name = 'Rhombus' +_addon.author = 'trv' +_addon.version = '1.2.1' + +config = require('config') +texts = require('texts') +res = require('resources') +bit = require('bit') +require 'tables' +require('lists') +require('sets') +require('logger') +require('defs') +require('helper_functions') + +config.register(_defaults, function(settings_table) + x_offset = settings_table.x_offset + y_offset = settings_table.y_offset + selector_pos.x = 102 + x_offset + + windower.prim.set_position('menu_backdrop',selector_pos.x,y_offset) + windower.prim.set_position('selector_rectangle',selector_pos.x,y_offset) + windower.prim.set_position('scroll_bar',selector_pos.x + 150,y_offset) + + display_text:pos(95 + x_offset, y_offset) + + menu_icon:pos(-12 + x_offset, -22 + y_offset) + menu_icon:show() +end) + +function get_templates() + if not windower.ffxi.get_info().logged_in then return end + local player = windower.ffxi.get_player() + player_info.id = player.id + player_info.main_job = main_job_id or player.main_job_id + player_info.sub_job = sub_job_id or player.sub_job_id + player_info.main_job_level = main_job_level or player.main_job_level + player_info.sub_job_level = sub_job_level or player.sub_job_level + + local main = res.jobs[player_info.main_job].en + local sub = res.jobs[player_info.sub_job].en + + local t_temp = L(res.spells:levels(function(t) return t[player_info.main_job] or t[player_info.sub_job] end):keyset()) + spells_template = loadfile(windower.addon_path .. 'data/spells_template.lua') + if not spells_template then + print('No template for spells was found.') + spells_template = t_temp + else + spells_template = spells_template() + count_table_elements(spells_template) + end + + t_temp = L(res.weapon_skills:keyset()) + ws_template = loadfile(windower.addon_path .. 'data/ws_template.lua') + if not ws_template then + print('No template for weapon skills was found.') + ws_template = t_temp + else + ws_template = ws_template() + count_table_elements(ws_template) + if ws_template[main] then + if ws_template[sub] then + ws_template = recursively_merge_tables(ws_template[main], ws_template[sub]) + else + ws_template = recursively_merge_tables(ws_template[main],t_temp) + end + elseif ws_template[sub] then + ws_template = recursively_merge_tables(ws_template[sub],t_temp) + else + ws_template = t_temp + end + end + + t_temp = L(res.job_abilities:prefix('/jobability'):keyset()) + ja_template = loadfile(windower.addon_path .. 'data/ja_template.lua') + if not ja_template then + print('No template for job abilities was found.') + ja_template = t_temp + else + ja_template = ja_template() + count_table_elements(ja_template) + if ja_template[main] then + if ja_template[sub] then + ja_template = recursively_merge_tables(ja_template[main], ja_template[sub]) + else + ja_template = recursively_merge_tables(ja_template[main],t_temp) + end + elseif ja_template[sub] then + ja_template = recursively_merge_tables(ja_template[sub],t_temp) + else + ja_template = t_temp + end + end + + t_temp = L(res.job_abilities:prefix('/pet'):keyset()) + pet_command_template = loadfile(windower.addon_path .. 'data/pet_command_template.lua') + if not pet_command_template then + print('No template for pet commands was found.') + pet_command_template = t_temp + else + pet_command_template = pet_command_template() + count_table_elements(pet_command_template) + if pet_command_template[main] then + if pet_command_template[sub] then + pet_command_template = recursively_merge_tables(pet_command_template[main], pet_command_template[sub]) + else + pet_command_template = recursively_merge_tables(pet_command_template[main],t_temp) + end + elseif pet_command_template[sub] then + pet_command_template = recursively_merge_tables(pet_command_template[sub],t_temp) + else + pet_command_template = t_temp + end + end + + spell_aliases = loadfile(windower.addon_path .. 'data/spell_aliases.lua') + if not spell_aliases then + spell_aliases = {} + else + spell_aliases = spell_aliases() + end + +end + +function menu_general_layout(t,t2,n) + available_category = t + if is_menu_open then + if last_menu_open.type == n then + is_menu_open = false + menu_layer_record:clear() + close_a_menu() + last_menu_open = {} + current_menu = {} + menu_history[n] = false + else + menu_history[last_menu_open.type] = list.copy(menu_layer_record) + if menu_history[n] then + last_menu_open.type = n + menu_layer_record = menu_history[n] + current_menu = recursively_copy_spells(t2) + if current_menu then + last_menu_open = current_menu + last_menu_open.type = n + for i = 1,menu_layer_record.n do + if current_menu[menu_layer_record[i]] then + current_menu = current_menu[menu_layer_record[i]] + else + for j = 1,menu_layer_record.n+1-i do + menu_layer_record:remove() + end + break + end + end + build_a_menu(current_menu) + else + close_a_menu() + current_menu = {} + end + else + menu_layer_record:clear() + last_menu_open.type = n + current_menu = recursively_copy_spells(t2) + if current_menu then + last_menu_open = current_menu + last_menu_open.type = n + build_a_menu(current_menu) + else + close_a_menu() + current_menu = {} + end + end + end + else + if menu_history[n] then + last_menu_open.type = n + menu_layer_record = menu_history[n] + current_menu = recursively_copy_spells(t2) + if current_menu then + last_menu_open = current_menu + last_menu_open.type = n + for i = 1,menu_layer_record.n do + if current_menu[menu_layer_record[i]] then + current_menu = current_menu[menu_layer_record[i]] + else + for j = 1,menu_layer_record.n+1-i do + menu_layer_record:remove() + end + break + end + end + build_a_menu(current_menu) + else + close_a_menu() + current_menu = {} + end + else + menu_layer_record:clear() + last_menu_open.type = n + current_menu = recursively_copy_spells(t2) + if current_menu then + last_menu_open = current_menu + last_menu_open.type = n + build_a_menu(current_menu) + else + close_a_menu() + current_menu = {} + end + end + end +end + +windower.register_event('incoming chunk', function(id, data) + if is_menu_open and id == 0x0AC and last_menu_open.type ~= 1 then + if not S(windower.ffxi.get_abilities()[category_to_resources[last_menu_open.type]]):equals(available_category) then + available_category = S(windower.ffxi.get_abilities()[category_to_resources[last_menu_open.type]]) + current_menu = recursively_copy_spells({spells_template,ws_template,ja_template,pet_command_template}[last_menu_open.type]) + menu_building_snippet() + end + end +end) + +windower.register_event('gain buff', function(buff_id) + if is_menu_open and refresh_ma_when[buff_id] and last_menu_open.type == 1 then + active_buffs:add(buff_id) + number_of_jps = count_job_points() + current_menu = recursively_copy_spells(spells_template) + menu_building_snippet() + end +end) + +windower.register_event('lose buff', function(buff_id) + if is_menu_open and refresh_ma_when[buff_id] and last_menu_open.type == 1 then + active_buffs:remove(buff_id) + number_of_jps = count_job_points() + current_menu = recursively_copy_spells(spells_template) + menu_building_snippet() + end +end) + +windower.register_event('job change',get_templates) + +windower.register_event('login', function() + get_templates:schedule(10) +end) + +windower.register_event('load', function() + get_templates() +end) + +windower.register_event('logout', function() + close_a_menu() + display_text:hide() + menu_icon:hide() +end) + +windower.register_event('mouse', function(type, x, y, delta, blocked) + if blocked then + return + end + if type == 0 then + local _x,_y = x-(51+x_offset),y-(51+y_offset) + if drag_and_drop then + x_offset = x-drag_and_drop.x + y_offset = y-drag_and_drop.y + display_text:pos(x_offset+95,y_offset) + menu_icon:pos(x_offset-12,y_offset-22) + selector_pos.x = x_offset+102 + windower.prim.set_position('menu_backdrop',selector_pos.x,y-drag_and_drop.y) + windower.prim.set_position('selector_rectangle',selector_pos.x,y_offset+selector_pos.y) + windower.prim.set_position('scroll_bar',selector_pos.x + 150,y_offset + ((12 * font_height_est * (1 - 12 / menu_list.n)) / (menu_list.n - 12)) * (menu_start - 1)) + elseif math.abs(_x) + math.abs(_y) <= 51 then + local tan = (_y)/(_x) + if _x > 0 then + if tan <= -1 then + if not is_icon.G then + menu_icon:color(111,255,111) + colors_of_the_wind('G') + end + elseif tan >= -1 and tan <= 1 then + if not is_icon.R then + menu_icon:color(255,111,111) + colors_of_the_wind('R') + end + elseif tan >= 1 then + if not is_icon.B then + menu_icon:color(111,111,255) + colors_of_the_wind('B') + end + end + elseif _x < 0 then + if tan <= -1 then + if not is_icon.B then + menu_icon:color(111,111,255) + colors_of_the_wind('B') + end + elseif tan >= -1 and tan <= 1 then + if not is_icon.Y then + menu_icon:color(255,255,111) + colors_of_the_wind('Y') + end + elseif tan >= 1 then + if not is_icon.G then + menu_icon:color(111,255,111) + colors_of_the_wind('G') + end + end + end + elseif is_menu_open then + if (x >= display_text:pos_x() and x <= display_text:pos_x() + 150) then + local _,_y = display_text:extents() + if y <= y_offset or y >= y_offset + _y then return end + local y_17 = math.ceil((y-y_offset)/font_height_est) + if (y_17) ~= selector_pos.y then + selector_pos.y = (y_17 - 1) * font_height_est + windower.prim.set_position('selector_rectangle',selector_pos.x,selector_pos.y + y_offset) + end + else + if not is_icon[letter_to_n[last_menu_open.type]] then + menu_icon:color(unpack(n_to_color[last_menu_open.type])) + colors_of_the_wind(letter_to_n[last_menu_open.type]) + end + end + elseif not is_icon.W then + menu_icon:color(255,255,255) + colors_of_the_wind('W') + end + elseif type == 1 then + local _x,_y = x-(51+x_offset),y-(51+y_offset) + if math.abs(_x) + math.abs(_y) <= 51 then + mouse_safety = true + if is_shift_modified then + drag_and_drop = {x=_x+51,y=_y+51} + return true + else + local tan = (_y)/(_x) + if _x >= 0 then + if tan <= -1 then + mouse_func[2]() + elseif tan >= -1 and tan <= 1 then + mouse_func[1]() + elseif tan >= 1 then + mouse_func[3]() + end + elseif _x < 0 then + if tan <= -1 then + mouse_func[3]() + elseif tan >= -1 and tan <= 1 then + mouse_func[4]() + elseif tan >= 1 then + mouse_func[2]() + end + end + return true + end + elseif is_menu_open and x >= display_text:pos_x() and x <= display_text:pos_x() + 150 then + local _,_y = display_text:extents() + if y <= y_offset or y >= y_offset + _y then return end + + local y_17 = math.ceil((y-y_offset)/font_height_est + menu_start - 1) + if current_menu.sub_menus and y_17 <= current_menu.sub_menus.n then + menu_layer_record:append(current_menu.sub_menus[y_17]) + current_menu = current_menu[menu_layer_record:last()] + build_a_menu(current_menu) + mouse_safety = true + return true + else + format_response(last_menu_open.type,current_menu[y_17-(current_menu.sub_menus and current_menu.sub_menus.n or 0)],is_shift_modified) + mouse_safety = true + return true + end + end + elseif type == 2 then + if drag_and_drop then + _defaults.x_offset = x_offset + _defaults.y_offset = y_offset + _defaults:save() + drag_and_drop = false + end + if mouse_safety then + mouse_safety = false + return true + end + elseif type == 10 then + if is_menu_open and menu_list.n > 12 + and x >= display_text:pos_x() and x<= display_text:pos_x() + 150 + and y >= display_text:pos_y() and y <= display_text:pos_y() + 12 * font_height_est then + + menu_start = menu_start - delta + if menu_start < 1 then menu_start = 1 end + if menu_start + 11 > menu_list.n then menu_start = menu_list.n - 11 end + display_text:text(menu_list:concat('\n',menu_start,menu_start+11)) + windower.prim.set_position('scroll_bar',selector_pos.x + 150,y_offset + ((12 * font_height_est * (1 - 12 / menu_list.n)) / (menu_list.n - 12)) * (menu_start - 1)) + return true + end + elseif type == 4 then + local _x,_y = x-(51+x_offset),y-(51+y_offset) + if math.abs(_x) + math.abs(_y) <= 51 then + mouse_safety = true + if is_menu_open then + menu_history[last_menu_open.type] = list.copy(menu_layer_record) + end + close_a_menu() + return true + elseif is_menu_open and x >= display_text:pos_x() and x <= display_text:pos_x() + 150 then + if y <= y_offset or y >= y_offset + font_height_est * 12 then return end + if menu_layer_record.n == 0 then + close_a_menu() + else + open_previous_menu() + end + mouse_safety = true + return true + end + elseif type == 5 then + if mouse_safety then + mouse_safety = false + return true + end + end +end) + +mouse_func = { + [1] = function() + active_buffs = S(windower.ffxi.get_player().buffs) + number_of_jps = count_job_points() + menu_general_layout(windower.ffxi.get_spells(),spells_template,1) + end, + [2] = function() + menu_general_layout(S(windower.ffxi.get_abilities().weapon_skills),ws_template,2) + end, + [3] = function() + menu_general_layout(S(remove_categories(windower.ffxi.get_abilities().job_abilities)),ja_template,3) + end, + [4] = function() + menu_general_layout(S(remove_categories(windower.ffxi.get_abilities().job_abilities)),pet_command_template,4) + end, +} + +function build_a_menu(t) + menu_start = 1 + is_menu_open = true + menu_list:clear() + if t.sub_menus and (t.sub_menus.n + t.n == 1) then + menu_layer_record:append(current_menu.sub_menus[1]) + current_menu = current_menu[menu_layer_record:last()] + build_a_menu(current_menu) + else + if t.sub_menus then + for i = 1,t.sub_menus.n do + menu_list:append(' \\cs(' .. (custom_menu_colors[t.sub_menus[i]] or '239,195,255') .. ')' .. t.sub_menus[i] .. '\\cr') + end + end + for i = 1,t.n do + menu_list:append(' ' .. get_string_from_id(t[i])) + end + if menu_list.n > 12 then + windower.prim.set_size('scroll_bar',10,(font_height_est * 144 / menu_list.n)) + windower.prim.set_visibility('scroll_bar',true) + windower.prim.set_position('scroll_bar',selector_pos.x + 150,y_offset) + else + windower.prim.set_visibility('scroll_bar',false) + end + display_text:text(menu_list:concat('\n',1,12)) + windower.prim.set_visibility('menu_backdrop',true) + selector_pos.y = y_offset + windower.prim.set_position('selector_rectangle',selector_pos.x,selector_pos.y) + windower.prim.set_visibility('selector_rectangle',true) + display_text:show() + end +end + +function close_a_menu() + is_menu_open = false + menu_layer_record:clear() + windower.prim.set_visibility('scroll_bar',false) + windower.prim.set_visibility('menu_backdrop',false) + windower.prim.set_visibility('selector_rectangle',false) + display_text:hide() +end + +function open_previous_menu() + menu_layer_record:remove() + current_menu = last_menu_open + for i = 1,menu_layer_record.n do + current_menu = current_menu[menu_layer_record[i]] + end + if current_menu.sub_menus and (current_menu.sub_menus.n + current_menu.n == 1) then + if menu_layer_record.n == 0 then + close_a_menu() + else + open_previous_menu() + end + else + build_a_menu(current_menu) + end +end + +function format_response(n,p,bool) + local t + if n == 1 then + if bool then + if not (res.spells[p].targets['Self'] or res.spells[p].targets['Corpse']) then + t = ' <stnpc>' + else + t = ' <stpc>' + end + else + t = '' + end + n,p = '/ma',res.spells[p].en + elseif n == 2 then + if bool then + if not (res.weapon_skills[p].targets['Self'] or res.weapon_skills[p].targets['Corpse']) then + t = ' <stnpc>' + else + t = ' <stpc>' + end + else + t = '' + end + n,p = '/ws',res.weapon_skills[p].en + else + if bool then + if not (res.job_abilities[p].targets['Self'] or res.job_abilities[p].targets['Corpse']) then + t = ' <stnpc>' + else + t = ' <stpc>' + end + else + t = '' + end + n,p = res.job_abilities[p].prefix,res.job_abilities[p].en + end + + windower.send_command('input %s %q%s':format(n,p,t)) +end + +windower.register_event('keyboard', function(dik, down, flags, blocked) + if dik == 42 and not bit.is_set(flags, 6) then + is_shift_modified = down + end +end) + +function determine_accessibility(spell,type) -- ability filter, slightly modified. Credit: Byrth + if type == 1 then + local spell_jobs = spell.levels + if not available_category[spell.id] and not (spell.id == 503) then + return false + elseif (not spell_jobs[player_info.main_job] or not (spell_jobs[player_info.main_job] <= player_info.main_job_level or + (spell_jobs[player_info.main_job] > 99 and number_of_jps >= spell_jobs[player_info.main_job]))) and + (not spell_jobs[player_info.sub_job] or not (spell_jobs[player_info.sub_job] <= player_info.sub_job_level)) then + return false + elseif player_info.main_job == 20 and ((addendum_white[spell.id] and not active_buffs[401] and not active_buffs[416]) or + (addendum_black[spell.id] and not active_buffs[402] and not active_buffs[416])) and + not (spell_jobs[player_info.sub_job] and spell_jobs[player_info.sub_job] <= player_info.sub_job_level) then + return false + elseif player_info.sub_job == 20 and ((addendum_white[spell.id] and not active_buffs[401] and not active_buffs[416]) or + (addendum_black[spell.id] and not active_buffs[402] and not active_buffs[416])) and + not (spell_jobs[player_info.main_job] and spell_jobs[player_info.main_job] <= player_info.main_job_level) then + return false + elseif spell.type == 'BlueMagic' and not ((player_info.main_job == 16 and table.contains(windower.ffxi.get_mjob_data().spells,spell.id)) or + ((active_buffs[485] or active_buffs[505]) and unbridled_learning_set[spell.english])) and not + (player.sub_job_id == 16 and table.contains(windower.ffxi.get_sjob_data().spells,spell.id)) then + return false + end + return true + else + return available_category:contains(spell.id) + end +end |