summaryrefslogtreecommitdiff
path: root/Data/BuiltIn/Libraries/lua-addons/addons/PetTP/PetTP.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Data/BuiltIn/Libraries/lua-addons/addons/PetTP/PetTP.lua')
-rw-r--r--Data/BuiltIn/Libraries/lua-addons/addons/PetTP/PetTP.lua416
1 files changed, 416 insertions, 0 deletions
diff --git a/Data/BuiltIn/Libraries/lua-addons/addons/PetTP/PetTP.lua b/Data/BuiltIn/Libraries/lua-addons/addons/PetTP/PetTP.lua
new file mode 100644
index 0000000..76171b6
--- /dev/null
+++ b/Data/BuiltIn/Libraries/lua-addons/addons/PetTP/PetTP.lua
@@ -0,0 +1,416 @@
+config = require ('config')
+texts = require('texts')
+packets = require('packets')
+require('pack')
+
+_addon.name = 'PetTP'
+_addon.author = 'SnickySnacks'
+_addon.version = '1.02'
+_addon.commands = {'ptp','pettp'}
+
+petname = nil
+mypet_idx = nil
+current_hp = 0
+max_hp = 0
+current_mp = 0
+max_mp = 0
+current_hp_percent = 0
+current_mp_percent = 0
+current_tp_percent = 0
+petactive = false
+verbose = false
+superverbose = false
+timercountdown = 0
+
+defaults = T{}
+
+defaults.autocolor = true
+
+defaults.pos = T{}
+defaults.pos.x = windower.get_windower_settings().x_res*2/3
+defaults.pos.y = windower.get_windower_settings().y_res-17
+
+defaults.bg = T{}
+defaults.bg.alpha = 255
+defaults.bg.red = 0
+defaults.bg.green = 0
+defaults.bg.blue = 0
+defaults.bg.visible = true
+
+defaults.flags = {}
+defaults.flags.right = false
+defaults.flags.bottom = false
+defaults.flags.bold = false
+defaults.flags.italic = false
+
+defaults.text = {}
+defaults.text.size = 10
+defaults.text.font = 'Courier New'
+defaults.text.alpha = 255
+defaults.text.red = 255
+defaults.text.green = 255
+defaults.text.blue = 255
+
+settings = config.load(defaults)
+pettp = texts.new(settings)
+
+function make_visible()
+ petactive = true
+ pettp:visible(true);
+ if verbose == true then windower.add_to_chat(8, 'PetTP Visible') end
+end
+
+function make_invisible()
+ if petactive then
+ pettp:text('')
+ pettp:visible(false)
+ if verbose == true then windower.add_to_chat(8, 'PetTP Invisible') end
+ end
+ petactive = false
+ mypet_idx = nil
+ petname = nil
+ current_hp = 0
+ max_hp = 0
+ current_mp = 0
+ max_mp = 0
+ current_hp_percent = 0
+ current_mp_percent = 0
+ current_tp_percent = 0
+end
+
+function valid_pet(source,pet_idx_in, own_idx_in)
+ local player = windower.ffxi.get_player()
+ if superverbose == true then windower.add_to_chat(8, 'valid_pet('..source..'): petactive: '..tostring(petactive)..', mypet_idx: '..(mypet_idx or 'nil')..', pet_idx_in: '..(pet_idx_in or 'nil')..', own_idx_in: '..(own_idx_in or 'nil')..', player.index '..player.index) end
+ if player.vitals.hp == 0 then
+ if superverbose == true then windower.add_to_chat(8, 'valid_pet() : false : Player is dead') end
+ timercountdown = 0
+ return
+ end
+
+ if petactive then
+ if mypet_idx then
+ if not pet_idx_in or mypet_idx == pet_idx_in then
+ if superverbose == true then windower.add_to_chat(8, 'valid_pet() : true : using mypet_idx') end
+ return mypet_idx
+ else
+ if superverbose == true then
+ windower.add_to_chat(8, 'mypet_idx ~= pet_idx_in '..mypet_idx..' vs. '..pet_idx_in)
+ end
+ end
+ elseif own_idx_in and player.index == own_idx_in then
+ if superverbose == true then windower.add_to_chat(8, 'valid_pet() : true : using pet_idx_in') end
+ mypet_idx = pet_idx_in
+ return mypet_idx
+ end
+ end
+
+ local pet = windower.ffxi.get_mob_by_target('pet')
+ if pet_idx_in and pet and pet_idx_in ~= pet.index then
+ if superverbose == true then windower.add_to_chat(8, 'valid_pet() : false : pet.index ~= pet_idx_in '..pet.index..' vs. '..pet_idx_in) end
+ return
+ elseif pet_idx_in and player.mob and player.mob.pet_index and pet_idx_in ~= player.mob.pet_index then
+ if superverbose == true then windower.add_to_chat(8, 'valid_pet() : false : player.mob.pet_index ~= pet_idx_in '..player.mob.pet_index..' vs. '..pet_idx_in) end
+ return
+ elseif pet then
+ if superverbose == true then windower.add_to_chat(8, 'valid_pet() : true : Using pet.index') end
+ mypet_idx = pet.index
+ return mypet_idx
+ elseif player.mob and player.mob.pet_index then
+ if superverbose == true then windower.add_to_chat(8, 'valid_pet() : true : Using player.mob.pet_index') end
+ mypet_idx = player.mob.pet_index
+ return mypet_idx
+ end
+ if superverbose == true then windower.add_to_chat(8, 'valid_pet() : false : No pet found') end
+ return
+end
+function update_pet(source,pet_idx_in,own_idx_in)
+ pet_idx = valid_pet(source,pet_idx_in,own_idx_in)
+
+ if pet_idx == nil then
+ if superverbose == true then windower.add_to_chat(8, 'update_pet() : false : pet_idx == nil, pet_idx_in: '..(pet_idx_in or 'nil')..', own_idx_in: '..(own_idx_in or 'nil')) end
+ return false
+ end
+
+ local pet_table = windower.ffxi.get_mob_by_index(pet_idx)
+ if pet_table == nil then
+ if petactive then -- presumably we have a pet, he just hasn't loaded, yet...
+ if superverbose == true then windower.add_to_chat(8, 'update_pet() : true : pet_table == nil, pet_idx: '..(pet_idx or 'nil')..', '..(own_idx_in or 'nil')) end
+ return true
+ end
+ if superverbose == true then windower.add_to_chat(8, 'update_pet() : false: pet_table == nil, pet_idx: '..(pet_idx or 'nil')..', '..(own_idx_in or 'nil')) end
+ make_invisible()
+ return false
+ end
+
+ petname = pet_table['name']
+ if superverbose == true then windower.add_to_chat(8, 'update_pet() : Updating PetName: '..petname) end
+ current_hp_percent = pet_table['hpp']
+ if not petactive and current_hp_percent == 0 then -- we're likely picking up a dead or despawning pet
+ if superverbose == true then windower.add_to_chat(8, 'update_pet() : Picked up a likely dead pet') end
+ make_invisible()
+ return false
+ end
+ if superverbose == true then windower.add_to_chat(8, 'update_pet() : true : Picked up a pet: '..petname..', hp%: '..current_hp_percent..', pet_idx: '..pet_idx) end
+ return true
+end
+
+function printpettp(pet_idx_in,own_idx_in)
+ if not petactive then
+ return
+ end
+ if petname == nil then
+ if update_pet('printpettp',pet_idx_in,own_idx_in) == false then
+ return
+ end
+ end
+
+ local output
+
+ output = (petname or 'Unknown')..': '
+ if settings.autocolor == true then
+ if current_hp_percent > 75 then
+ output = output..'\\cr\\cs(128,255,128)'
+ elseif current_hp_percent > 50 then
+ output = output..'\\cr\\cs(255,255,0)'
+ elseif current_hp_percent > 25 then
+ output = output..'\\cr\\cs(255,160,0)'
+ else
+ output = output..'\\cr\\cs(255,0,0)'
+ end
+ end
+ if max_hp > 0 then
+ output = output..current_hp..'/'..max_hp..' '..'('..current_hp_percent..'%)'
+ else
+ output = output..current_hp_percent..'%'
+ end
+ if settings.autocolor == true then output = output..'\\cr\\cs('..settings.text.red..','..settings.text.green..','..settings.text.blue..')' end
+ output = output..' ['
+ if settings.autocolor == true and current_tp_percent >= 1000 then output = output..'\\cr\\cs(128,255,128)' end
+ output = output..current_tp_percent
+ if settings.autocolor == true and current_tp_percent >= 1000 then output = output..'\\cr\\cs('..settings.text.red..','..settings.text.green..','..settings.text.blue..')' end
+ output = output..']'
+ if max_mp > 0 then
+ if current_mp_percent > 75 then
+ output = output..'\\cr\\cs(128,255,128)'
+ elseif current_mp_percent > 50 then
+ output = output..'\\cr\\cs(255,255,0)'
+ elseif current_mp_percent > 25 then
+ output = output..'\\cr\\cs(255,160,0)'
+ else
+ output = output..'\\cr\\cs(255,0,0)'
+ end
+ output = output..' '..current_mp..'/'..max_mp..' ('..current_mp_percent..'%)'
+ if settings.autocolor == true then output = output..'\\cr\\cs('..settings.text.red..','..settings.text.green..','..settings.text.blue..')' end
+ end
+ output = output..'\\cr'
+
+ pettp:text(output)
+end
+
+windower.register_event('time change', function()
+ if timercountdown == 0 then
+ return
+ elseif petactive then
+ if superverbose == true then windower.add_to_chat(8, 'SCAN: Pet appeared between scans!') end
+ timercountdown = 0
+ else
+ timercountdown = timercountdown - 1
+ if update_pet('scan') == true then
+ if superverbose == true then windower.add_to_chat(8, 'SCAN: Found a pet!') end
+ timercountdown = 0
+ make_visible()
+ printpettp()
+ elseif timercountdown == 0 then
+ if superverbose == true then windower.add_to_chat(8, 'SCAN: No pet found in 5 ticks') end
+ end
+ end
+end)
+
+windower.register_event('incoming chunk',function(id,original,modified,injected,blocked)
+ if not injected then
+ if id == 0x44 then
+ if original:unpack('C', 0x05) == 0x12 then -- puppet update
+ local new_current_hp, new_max_hp, new_current_mp, new_max_mp = original:unpack('HHHH', 0x069)
+
+ if (not petactive) or (petname == nil) or (petname == "") or (new_current_hp ~= current_hp) or (new_max_hp ~= max_hp) or (new_current_mp ~= current_mp) or (new_max_mp ~= max_mp) then
+ if superverbose == true then
+ windower.add_to_chat(8, '0x44'
+ ..', cur_hp: '..new_current_hp
+ ..', max_hp: '..new_max_hp
+ ..', cur_mp: '..new_current_mp
+ ..', max_mp: '..new_max_mp
+ ..', name: '.. original:unpack('z', 0x59)
+ )
+ end
+
+ if petactive then
+ local new_petname = original:unpack('z', 0x59)
+ if petname == nil or petname == "" then
+ if superverbose == true then windower.add_to_chat(8, 'Updating PuppetName: '..new_petname) end
+ petname = new_petname
+ end
+ if petname == new_petname then -- make sure we only update if we actually have a puppet out
+ current_hp = new_current_hp
+ max_hp = new_max_hp
+ current_mp = new_current_mp
+ max_mp = new_max_mp
+ if max_hp ~= 0 then
+ current_hp_percent=math.floor(100*current_hp/max_hp)
+ else
+ current_hp_percent=0
+ end
+ if max_mp ~= 0 then
+ current_mp_percent=math.floor(100*current_mp/max_mp)
+ else
+ current_mp_percent=0
+ end
+ printpettp()
+ else
+ if superverbose == true then windower.add_to_chat(8, '0x44, pet is not a puppet') end
+ end
+ else
+ if superverbose == true then windower.add_to_chat(8, '0x44, puppet not active') end
+ end
+ end
+ end
+ elseif id == 0x67 or id == 0x068 then -- general hp/tp/mp update
+ local packet = packets.parse('incoming', original)
+ local msg_type = packet['Message Type']
+ local msg_len = packet['Message Length']
+ pet_idx = packet['Pet Index']
+ own_idx = packet['Owner Index']
+
+ if (msg_type == 0x04) and id == 0x067 then
+ pet_idx, own_idx = own_idx, pet_idx
+ end
+
+ if superverbose == true and id == 0x067 and not (
+ (msg_type == 0x02) -- not pet related
+ or (msg_type == 0x03 and (own_idx == 0)) -- NPC pops
+ or (msg_type == 0x03 and (own_idx ~= windower.ffxi.get_player().index)) -- other people summoning
+ ) then
+ windower.add_to_chat(8, '0x67'
+ ..', msg_type: '..string.format('0x%02x', msg_type)
+ ..', msg_len: '..msg_len
+ ..', pet_idx: '..pet_idx
+ ..', pet_id: '..(original:byte(0x09)+original:byte(0x0A)*256)
+ ..', own_idx: '..own_idx
+ ..', hp%: '..original:byte(0x0F)
+ ..', mp%: '..original:byte(0x10)
+ ..', tp%: '..(original:byte(0x11)+original:byte(0x12)*256)
+ ..', name: '.. ((msg_len > 24) and original:unpack('z', 0x19) or "")
+ )
+ end
+ if (msg_type == 0x04) then
+ if (pet_idx == 0) then
+ if verbose == true then windower.add_to_chat(8, 'Pet died/despawned') end
+ make_invisible()
+ else
+ local newpet = false
+ if not petactive then
+ petactive = true -- force our pet to appear even if it's not attached to us yet
+ if update_pet('0x67-0x*4',pet_idx,own_idx) == true then
+ make_visible()
+ newpet = true
+ else
+ if superverbose == true then windower.add_to_chat(8, 'Pet not found') end
+ make_invisible()
+ end
+ end
+ local new_hp_percent = packet['Current HP%']
+ local new_mp_percent = packet['Current MP%']
+ local new_tp_percent = packet['Pet TP']
+ if newpet or (new_hp_percent ~= current_hp_percent) or (new_mp_percent ~= current_mp_percent) or (new_tp_percent ~= current_tp_percent) or (petname == nil) or (petname == "") then
+ if (max_hp ~= 0) and (new_hp_percent ~= current_hp_percent) then
+ current_hp = math.floor(new_hp_percent * max_hp / 100)
+ end
+ if (max_mp ~= 0) and (new_mp_percent ~= current_mp_percent) then
+ current_mp = math.floor(new_mp_percent * max_mp / 100)
+ end
+ if ((petname == nil) or (petname == "")) then
+ petname = packet['Pet Name']
+ if superverbose == true then windower.add_to_chat(8, 'Updated PetName: '..petname) end
+ end
+ current_hp_percent = new_hp_percent
+ current_mp_percent = new_mp_percent
+ current_tp_percent = new_tp_percent
+ printpettp(pet_idx,own_idx)
+ end
+ end
+ elseif not petactive and (msg_type == 0x03) and (own_idx == windower.ffxi.get_player().index) then
+ if update_pet('0x67-0x03',pet_idx,own_idx) == true then
+ make_visible()
+ printpettp(pet_idx,own_idx_in)
+ else -- last resort
+ timercountdown = 5
+ if superverbose == true then windower.add_to_chat(8, 'Starting to scan for a pet...') end
+ end
+ end
+ elseif id==0x0E and S{0x07,0x0F}:contains(original:byte(0x0B)) then -- npc update
+ if mypet_idx == original:unpack('H', 0x09) then
+ if current_hp_percent ~= original:byte(0x1F) then
+ if superverbose == true then windower.add_to_chat(8, '0x0E - '..original:byte(0x0B)..': '..original:byte(0x1F)) end
+ current_hp_percent = original:byte(0x1F)
+ if max_hp ~= 0 then
+ current_hp = math.floor(current_hp_percent * max_hp / 100)
+ end
+ printpettp(mypet_idx)
+ end
+ end
+ elseif id==0x0E and not S{0x00,0x01,0x08,0x09,0x20}:contains(original:byte(0x0B)) and mypet_idx == (original:byte(0x09)+original:byte(0x0A)*256) then
+ if superverbose == true then windower.add_to_chat(8, '0x0E ~ '..original:byte(0x0B)..': '..original:byte(0x1F)) end
+ end
+ end
+end)
+
+windower.register_event('load', function()
+ if superverbose == true then
+ windower.add_to_chat(8, 'Player index: '..windower.ffxi.get_player().index)
+ if windower.ffxi.get_mob_by_target('pet') then
+ windower.add_to_chat(8, 'Pet index: '..windower.ffxi.get_mob_by_target('pet').index)
+ end
+ end
+ if windower.ffxi.get_player() then
+ if update_pet('load') == true then
+ make_visible()
+ printpettp()
+ end
+ end
+end)
+
+windower.register_event('zone change', function()
+ mypet_idx = nil
+ if update_pet('zone') == true then
+ if verbose == true then windower.add_to_chat(8, 'Found pet after zoning...') end
+ make_visible()
+ printpettp()
+ elseif petactive then
+ make_invisible()
+ if verbose == true then windower.add_to_chat(8, 'Lost pet after zoning...') end
+ end
+end)
+
+windower.register_event('job change', function()
+ make_invisible()
+end)
+
+windower.register_event('addon command', function(...)
+ local splitarr = {...}
+
+ for i,v in pairs(splitarr) do
+ if v:lower() == 'save' then
+ config.save(settings, 'all')
+ elseif v:lower() == 'verbose' then
+ verbose = not verbose
+ windower.add_to_chat(121,'PetTP: Verbose Mode flipped! - '..tostring(verbose))
+ elseif v:lower() == 'superverbose' then
+ superverbose = not superverbose
+ windower.add_to_chat(121,'PetTP: SuperVerbose Mode flipped! - '..tostring(superverbose))
+ elseif v:lower() == 'help' then
+ print(' ::: '.._addon.name..' ('.._addon.version..') :::')
+ print('Utilities:')
+ print(' 1. verbose --- Some light logging, Default = false')
+ print(' 2. help --- shows this menu')
+ end
+ end
+end)