diff options
Diffstat (limited to 'Data/BuiltIn/Libraries/lua-addons/addons/InfoBar/InfoBar.lua')
-rw-r--r-- | Data/BuiltIn/Libraries/lua-addons/addons/InfoBar/InfoBar.lua | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/Data/BuiltIn/Libraries/lua-addons/addons/InfoBar/InfoBar.lua b/Data/BuiltIn/Libraries/lua-addons/addons/InfoBar/InfoBar.lua new file mode 100644 index 0000000..8b03d0e --- /dev/null +++ b/Data/BuiltIn/Libraries/lua-addons/addons/InfoBar/InfoBar.lua @@ -0,0 +1,276 @@ +--[[Copyright © 2018, Kenshi +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 InfoBar 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 KENSHI 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 = 'Infobar' +_addon.author = 'Kenshi' +_addon.version = '1.0' +_addon.commands = {'ib', 'infobar'} + +config = require('config') +texts = require('texts') +require('vectors') +res = require('resources') +require('sqlite3') + +defaults = {} +defaults.NoTarget = "${name} (${main_job}${main_job_level}/${sub_job}${sub_job_level}) (${x},${y},${z})" +defaults.TargetPC = "${name}" +defaults.TargetNPC = "${name}" +defaults.TargetMOB = "${name}" +defaults.display = {} +defaults.display.pos = {} +defaults.display.pos.x = 0 +defaults.display.pos.y = 0 +defaults.display.bg = {} +defaults.display.bg.red = 0 +defaults.display.bg.green = 0 +defaults.display.bg.blue = 0 +defaults.display.bg.alpha = 102 +defaults.display.text = {} +defaults.display.text.font = 'Consolas' +defaults.display.text.red = 255 +defaults.display.text.green = 255 +defaults.display.text.blue = 255 +defaults.display.text.alpha = 255 +defaults.display.text.size = 12 + +settings = config.load(defaults) + +box = texts.new("", settings.display, settings) + +local infobar = {} +infobar.new_line = '\n' + +windower.register_event('load',function() + db = sqlite3.open(windower.addon_path..'/database.db') + notesdb = sqlite3.open(windower.addon_path..'/notes.db') + notesdb:exec('CREATE TABLE IF NOT EXISTS notes(name TEXT primary key, note TEXT)') + if not windower.ffxi.get_info().logged_in then return end + local target = windower.ffxi.get_mob_by_target('st') or windower.ffxi.get_mob_by_target('t') or windower.ffxi.get_player() + get_target(target.index) +end) + +windower.register_event('unload',function() + db:close() + notesdb:close() +end) + +function getDegrees(value) + return math.round(360 / math.tau * value) +end + +local dir_sets = L{'W', 'WNW', 'NW', 'NNW', 'N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW', 'W'} +function DegreesToDirection(val) + return dir_sets[math.round((val + math.pi) / math.pi * 8) + 1] +end + +function get_db(target, zones, level) + local query = 'SELECT * FROM "monster" WHERE name = "'..target..'" AND zone = "'..zones..'"' + local MOB_infobar = {} + box:bold(false) + + if db:isopen() and query then + for id,name,family,job,zone,isaggressive,islinking,isnm,isfishing,levelmin,levelmax,sight,sound,magic,lowhp,healing,ts,th,scent,weakness,resistances,immunities,drops,stolen,spawn,spawntime in db:urows(query) do + if name == target and zone == zones then + MOB_infobar.family = family or '' + MOB_infobar.job = job or '' + MOB_infobar.levelrange = levelmin and levelmax and levelmin.."-"..levelmax or '' + MOB_infobar.weakness = weakness or '' + MOB_infobar.resistances = resistances or '' + MOB_infobar.immunities = immunities or '' + MOB_infobar.drops = drops or '' + MOB_infobar.stolen = stolen or '' + MOB_infobar.spawns = spawn or '' + MOB_infobar.spawntime = spawntime or '' + if isaggressive == 1 then + MOB_infobar.isagressive = 'A' + if type(levelmax) == 'number' and (level - levelmax) <= 10 then + box:bold(true) + end + else + MOB_infobar.isagressive = 'NA' + end + MOB_infobar.islinking = islinking == 1 and 'L' or 'NL' + MOB_infobar.isnm = isnm == 1 and 'NM' or 'No NM' + MOB_infobar.isfishing = isfishing == 1 and 'F' or 'NF' + local detect = L{ + sight == 1 and 'S' or '', + sound == 1 and 'H' or '', + magic == 1 and 'M' or '', + lowhp == 1 and 'HP' or '', + healing == 1 and 'R' or '', + ts == 1 and 'TS' or '', + th == 1 and 'TH' or '', + scent == 1 and 'Sc' or '', + } + MOB_infobar.detect = detect:filter(-''):concat(',') + end + end + end + box:update(MOB_infobar) +end + +function get_notes(target) + local statement = notesdb:prepare('SELECT * FROM "notes" WHERE name = ?;') + if notesdb:isopen() and statement then + statement:bind(1, target) + for name, note in statement:urows(query, { target }) do + if name == target then + return note or nil + end + end + end +end + +function get_target(index) + local player = windower.ffxi.get_player() + local target = windower.ffxi.get_mob_by_target('st') or windower.ffxi.get_mob_by_target('t') or player + infobar.name = target.name + infobar.id = target.id + infobar.index = target.index + infobar.notes = get_notes(target.name) + if index == 0 or index == player.index then + infobar.main_job = player.main_job + infobar.main_job_level = player.main_job_level + infobar.sub_job = player.sub_job + infobar.sub_job_level = player.sub_job_level + box:color(255,255,255) + box:bold(false) + box:text(settings.NoTarget) + else + if target.spawn_type == 13 or target.spawn_type == 14 or target.spawn_type == 9 or target.spawn_type == 1 then + box:bold(false) + if target.spawn_type == 1 then + box:color(255,255,255) + else + box:color(128,255,255) + end + box:text(settings.TargetPC) + elseif target.spawn_type == 2 or target.spawn_type == 34 then + box:color(128,255,128) + box:text(settings.TargetNPC) + box:bold(false) + elseif target.spawn_type == 16 then + local zone = res.zones[windower.ffxi.get_info().zone].name + box:color(255,255,128) + box:text(settings.TargetMOB) + get_db(target.name, zone, player.main_job_level) + end + end + box:update(infobar) +end + +windower.register_event('incoming chunk',function(id,org,modi,is_injected,is_blocked) + if id == 0xB then + zoning_bool = true + elseif id == 0xA then + zoning_bool = false + end +end) + +windower.register_event('prerender', function() + local info = windower.ffxi.get_info() + + if not info.logged_in or not windower.ffxi.get_player() or zoning_bool then + box:hide() + return + end + + infobar.game_moon = res.moon_phases[info.moon_phase].name + infobar.game_moon_pct = info.moon..'%' + infobar.zone_name = res.zones[info.zone].name + + local pos = windower.ffxi.get_mob_by_target('st') or windower.ffxi.get_mob_by_target('t') or windower.ffxi.get_mob_by_target('me') + if not pos then return end + infobar.x = string.format('%0.3f', pos.x) + infobar.y = string.format('%0.3f', pos.y) + infobar.z = string.format('%0.3f', pos.z) + infobar.facing = tostring(getDegrees(pos.facing))..'°' + infobar.facing_dir = DegreesToDirection(pos.facing) + + box:update(infobar) + box:show() +end) + +windower.register_event('target change', get_target) +windower.register_event('job change', function() + get_target(windower.ffxi.get_player().index) +end) + +windower.register_event('time change', function(new, old) + local alchemy = new >= 8*60 and new <= 23*60 and 'Open' or 'Closed' + infobar.alchemy = alchemy == "Closed" and '\\cs(255,0,0)'..alchemy..'\\cr' or '\\cs(0,255,0)'..alchemy..'\\cr' + local bonecraft = new >= 8*60 and new <= 23*60 and 'Open' or 'Closed' + infobar.bonecraft = bonecraft == "Closed" and '\\cs(255,0,0)'..bonecraft..'\\cr' or '\\cs(0,255,0)'..bonecraft..'\\cr' + local clothcraft = new >= 6*60 and new <= 21*60 and 'Open' or 'Closed' + infobar.clothcraft = clothcraft == "Closed" and '\\cs(255,0,0)'..clothcraft..'\\cr' or '\\cs(0,255,0)'..clothcraft..'\\cr' + local cooking = new >= 5*60 and new <= 20*60 and 'Open' or 'Closed' + infobar.cooking = cooking == "Closed" and '\\cs(255,0,0)'..cooking..'\\cr' or '\\cs(0,255,0)'..cooking..'\\cr' + local fishing = new >= 3*60 and new <= 18*60 and 'Open' or 'Closed' + infobar.fishing = fishing == "Closed" and '\\cs(255,0,0)'..fishing..'\\cr' or '\\cs(0,255,0)'..fishing..'\\cr' + local goldsmithing = new >= 8*60 and new <= 23*60 and 'Open' or 'Closed' + infobar.goldsmithing = goldsmithing == "Closed" and '\\cs(255,0,0)'..goldsmithing..'\\cr' or '\\cs(0,255,0)'..goldsmithing..'\\cr' + local leathercraft = new >= 3*60 and new <= 18*60 and 'Open' or 'Closed' + infobar.leathercraft = leathercraft == "Closed" and '\\cs(255,0,0)'..leathercraft..'\\cr' or '\\cs(0,255,0)'..leathercraft..'\\cr' + local smithing = new >= 8*60 and new <= 23*60 and 'Open' or 'Closed' + infobar.smithing = smithing == "Closed" and '\\cs(255,0,0)'..smithing..'\\cr' or '\\cs(0,255,0)'..smithing..'\\cr' + local woodworking = new >= 6*60 and new <= 21*60 and 'Open' or 'Closed' + infobar.woodworking = woodworking == "Closed" and '\\cs(255,0,0)'..woodworking..'\\cr' or '\\cs(0,255,0)'..woodworking..'\\cr' + box:update(infobar) +end) + +windower.register_event('addon command', function(...) + local args = T{...} + if args[1] then + if args[1]:lower() == 'help' then + windower.add_to_chat(207,"Infobar Commands:") + windower.add_to_chat(207,"//ib|infobar notes add 'string'") + windower.add_to_chat(207,"//ib|infobar notes delete") + elseif args[1]:lower() == 'notes' then + local target = windower.ffxi.get_mob_by_target('t') + local tname = string.gsub(target.name, ' ', '_') + if not args[2] then + windower.add_to_chat(207,"Second argument not specified, use '//ib|infobar help' for info.") + elseif args[2]:lower() == 'add' then + if not target then windower.add_to_chat(207,"No target selected") return end + for i,v in pairs(args) do args[i]=windower.convert_auto_trans(args[i]) end + local str = table.concat(args," ",3) + notesdb:exec('INSERT OR REPLACE INTO notes VALUES ("'..target.name..'","'..str..'")') + get_target(target.index) + elseif args[2]:lower() == 'delete' then + if not target then windower.add_to_chat(207,"No target selected") return end + notesdb:exec('DELETE FROM notes WHERE name = "'..target.name..'"') + get_target(target.index) + else + windower.add_to_chat(207,"Second argument wrong, use '//ib|infobar help' for info.") + end + else + windower.add_to_chat(207,"First argument wrong, use '//ib|infobar help' for info.") + end + else + windower.add_to_chat(207,"First argument not specified, use '//ib|infobar help' for info.") + end +end) |