|
|
@ -23,9 +23,9 @@ |
|
|
|
* No warranties are given. |
|
|
|
* No warranties are given. |
|
|
|
]]-- |
|
|
|
]]-- |
|
|
|
|
|
|
|
|
|
|
|
_addon.author = 'tornac'; |
|
|
|
_addon.author = 'Tornac'; |
|
|
|
_addon.name = 'pupatt'; |
|
|
|
_addon.name = 'pupatt'; |
|
|
|
_addon.version = '1.10'; |
|
|
|
_addon.version = '1.12'; |
|
|
|
|
|
|
|
|
|
|
|
--------------------------------- |
|
|
|
--------------------------------- |
|
|
|
--DO NOT EDIT BELOW THIS LINE |
|
|
|
--DO NOT EDIT BELOW THIS LINE |
|
|
@ -39,26 +39,25 @@ require 'timer' |
|
|
|
-------------------------------------------------------------- |
|
|
|
-------------------------------------------------------------- |
|
|
|
-- Default settings. |
|
|
|
-- Default settings. |
|
|
|
-------------------------------------------------------------- |
|
|
|
-------------------------------------------------------------- |
|
|
|
|
|
|
|
currentProfile = { }; |
|
|
|
objDelay = 0.65; -- The delay to prevent spamming packets. |
|
|
|
attachmentQueue = { }; -- Table to hold commands queued for sending |
|
|
|
objTimer = 0; -- The current time used for delaying packets. |
|
|
|
objDelay = 0.65; -- The delay to prevent spamming packets. |
|
|
|
unequip = 0x00; |
|
|
|
objTimer = 0; -- The current time used for delaying packets. |
|
|
|
pupSub = 0x00; |
|
|
|
unequip = 0x00; |
|
|
|
offset = 0x04; |
|
|
|
pupSub = 0x00; |
|
|
|
local PlayerName = nil; |
|
|
|
offset = 0x04; |
|
|
|
inProgress = false; -- packet sending is in progress. |
|
|
|
|
|
|
|
queOffset = 1; -- smoother experience for packets. |
|
|
|
inProgress = false; -- packet sending is in progress. |
|
|
|
|
|
|
|
queOffset = 1; -- smoother experience for packets. |
|
|
|
currentProfile = { }; |
|
|
|
defaultAtt = false; |
|
|
|
attachmentQueue = { }; -- Table to hold commands queued for sending |
|
|
|
|
|
|
|
currentAttachments = { }; -- table for holding current attachments |
|
|
|
pupattProfiles = { }; -- table for holding attachment profiles |
|
|
|
pupattProfiles = { }; -- table for holding attachment profiles |
|
|
|
petlessZones = {50,235,234,224,284,233,70,257,251,14,242,250,226,245, |
|
|
|
petlessZones = {50,235,234,224,284,233,70,257,251,14,242,250,226,245, |
|
|
|
237,249,131,53,252,231,236,246,232,240,247,243,223,248,230, |
|
|
|
237,249,131,53,252,231,236,246,232,240,247,243,223,248,230, |
|
|
|
26,71,244,239,238,241,256,257} |
|
|
|
26,71,244,239,238,241,256,257} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------- |
|
|
|
--------------------------------------------------------------- |
|
|
|
--try to load file when addon is loaded. |
|
|
|
--try to load file when addon is loaded |
|
|
|
--------------------------------------------------------------- |
|
|
|
--------------------------------------------------------------- |
|
|
|
|
|
|
|
|
|
|
|
ashita.register_event('load', function() |
|
|
|
ashita.register_event('load', function() |
|
|
@ -70,12 +69,12 @@ end); |
|
|
|
--------------------------------------------------------------- |
|
|
|
--------------------------------------------------------------- |
|
|
|
|
|
|
|
|
|
|
|
function contains(table, val) |
|
|
|
function contains(table, val) |
|
|
|
for i=1,#table do |
|
|
|
for i=1,#table do |
|
|
|
if table[i] == val then |
|
|
|
if table[i] == val then |
|
|
|
return true |
|
|
|
return true |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
end; |
|
|
|
end; |
|
|
|
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------------------------ |
|
|
|
------------------------------------------------------------------------------------------------ |
|
|
@ -85,20 +84,17 @@ end; |
|
|
|
ashita.register_event('incoming_packet', function(id, size, packet) |
|
|
|
ashita.register_event('incoming_packet', function(id, size, packet) |
|
|
|
-- Party Member's Status |
|
|
|
-- Party Member's Status |
|
|
|
if (id == 0x044) then |
|
|
|
if (id == 0x044) then |
|
|
|
DiffPack = struct.unpack('B', packet, 0x05 + 1); |
|
|
|
DiffPack = struct.unpack('B', packet, 0x05 + 1); |
|
|
|
equippedOffset = 1; -- Increase by one byte every loop |
|
|
|
equippedOffset = 1; -- Increase by one byte every loop |
|
|
|
if (DiffPack == 0) then |
|
|
|
if (DiffPack == 0) then |
|
|
|
-- Unpack 14 bytes and set the slotid:attachmentid into currentAttachments table |
|
|
|
-- Unpack 14 bytes and set the slotid:attachmentid into currentAttachments table |
|
|
|
for i = 1, 14 do |
|
|
|
for i = 1, 14 do |
|
|
|
attachmentId = string.format("0x%X" , struct.unpack('B', packet, 0x08 + equippedOffset)); |
|
|
|
attachmentId = string.format("0x%X" , struct.unpack('B', packet, 0x08 + equippedOffset)); |
|
|
|
currentAttachments[i] = attachmentId; |
|
|
|
currentAttachments[i] = attachmentId; |
|
|
|
equippedOffset = equippedOffset + 1; |
|
|
|
equippedOffset = equippedOffset + 1; |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
if (id == 0x000A) then |
|
|
|
|
|
|
|
attFromMemory() |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
return false; |
|
|
|
return false; |
|
|
|
end); |
|
|
|
end); |
|
|
|
|
|
|
|
|
|
|
@ -120,8 +116,8 @@ end; |
|
|
|
---------------------------------------------------------------------------------------------------- |
|
|
|
---------------------------------------------------------------------------------------------------- |
|
|
|
|
|
|
|
|
|
|
|
function clearAttachments() |
|
|
|
function clearAttachments() |
|
|
|
local player = GetPlayerEntity(); |
|
|
|
local player = GetPlayerEntity(); |
|
|
|
local pet = GetEntity(player.PetTargetIndex); |
|
|
|
local pet = GetEntity(player.PetTargetIndex); |
|
|
|
|
|
|
|
|
|
|
|
if(pet == nil) then |
|
|
|
if(pet == nil) then |
|
|
|
print ("Clearing Attachments"); |
|
|
|
print ("Clearing Attachments"); |
|
|
@ -151,10 +147,10 @@ function load_pupatt(attachmentSet) |
|
|
|
if ((MainJob == 18 or SubJob == 18)and pet == nil) then |
|
|
|
if ((MainJob == 18 or SubJob == 18)and pet == nil) then |
|
|
|
if (SubJob == 18) then |
|
|
|
if (SubJob == 18) then |
|
|
|
local pupSub = 0x01; |
|
|
|
local pupSub = 0x01; |
|
|
|
end |
|
|
|
end |
|
|
|
for slot,item in ipairs(attachmentSet) do |
|
|
|
for slot,item in ipairs(attachmentSet) do |
|
|
|
addAttachment(slot,item); |
|
|
|
addAttachment(slot,item); |
|
|
|
end |
|
|
|
end |
|
|
|
else |
|
|
|
else |
|
|
|
print("Puppet is still out please please despawn pet to make changes to attachments.") |
|
|
|
print("Puppet is still out please please despawn pet to make changes to attachments.") |
|
|
|
end |
|
|
|
end |
|
|
@ -165,9 +161,9 @@ end; |
|
|
|
---------------------------------------------------------------------------------------------------- |
|
|
|
---------------------------------------------------------------------------------------------------- |
|
|
|
|
|
|
|
|
|
|
|
function despawn_pet() |
|
|
|
function despawn_pet() |
|
|
|
local recastTimerDeactivate = ashita.ffxi.recast.get_ability_recast_by_id(208); |
|
|
|
local recastTimerDeactivate = ashita.ffxi.recast.get_ability_recast_by_id(208); |
|
|
|
local player = GetPlayerEntity(); |
|
|
|
local player = GetPlayerEntity(); |
|
|
|
local pet = GetEntity(player.PetTargetIndex); |
|
|
|
local pet = GetEntity(player.PetTargetIndex); |
|
|
|
|
|
|
|
|
|
|
|
if (recastTimerDeactivate == 0 and pet ~= nil) then |
|
|
|
if (recastTimerDeactivate == 0 and pet ~= nil) then |
|
|
|
AshitaCore:GetChatManager():QueueCommand('/ja "Deactivate" <me>' , 1); |
|
|
|
AshitaCore:GetChatManager():QueueCommand('/ja "Deactivate" <me>' , 1); |
|
|
@ -181,11 +177,11 @@ end; |
|
|
|
---------------------------------------------------------------------------------------------------- |
|
|
|
---------------------------------------------------------------------------------------------------- |
|
|
|
|
|
|
|
|
|
|
|
function Summon_pet() |
|
|
|
function Summon_pet() |
|
|
|
local recastTimerActivate = ashita.ffxi.recast.get_ability_recast_by_id(205); |
|
|
|
local recastTimerActivate = ashita.ffxi.recast.get_ability_recast_by_id(205); |
|
|
|
local recastTimerdeusex = ashita.ffxi.recast.get_ability_recast_by_id(115); |
|
|
|
local recastTimerdeusex = ashita.ffxi.recast.get_ability_recast_by_id(115); |
|
|
|
local zone_id = AshitaCore:GetDataManager():GetParty():GetMemberZone(0); |
|
|
|
local zone_id = AshitaCore:GetDataManager():GetParty():GetMemberZone(0); |
|
|
|
local player = GetPlayerEntity(); |
|
|
|
local player = GetPlayerEntity(); |
|
|
|
local pet = GetEntity(player.PetTargetIndex); |
|
|
|
local pet = GetEntity(player.PetTargetIndex); |
|
|
|
|
|
|
|
|
|
|
|
if (pet == nil) then |
|
|
|
if (pet == nil) then |
|
|
|
if contains(petlessZones, zone_id) then |
|
|
|
if contains(petlessZones, zone_id) then |
|
|
@ -199,8 +195,8 @@ function Summon_pet() |
|
|
|
AshitaCore:GetChatManager():QueueCommand('/ja "Deus Ex Automata" <me>' , 1); |
|
|
|
AshitaCore:GetChatManager():QueueCommand('/ja "Deus Ex Automata" <me>' , 1); |
|
|
|
elseif(recastTimerdeusex > 0 and recastTimerdeusex > 0) then |
|
|
|
elseif(recastTimerdeusex > 0 and recastTimerdeusex > 0) then |
|
|
|
print('<<Pupatt: Activate and Deus Ex Automata is not ready yet please try again later>>') |
|
|
|
print('<<Pupatt: Activate and Deus Ex Automata is not ready yet please try again later>>') |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
else |
|
|
|
else |
|
|
|
print("Your puppet is already out") |
|
|
|
print("Your puppet is already out") |
|
|
|
end |
|
|
|
end |
|
|
@ -214,7 +210,6 @@ end; |
|
|
|
function process_queue() |
|
|
|
function process_queue() |
|
|
|
if (os.clock() >= (objTimer + objDelay)) then |
|
|
|
if (os.clock() >= (objTimer + objDelay)) then |
|
|
|
objTimer = os.clock(); |
|
|
|
objTimer = os.clock(); |
|
|
|
|
|
|
|
|
|
|
|
-- Ensure the queue has something to process.. |
|
|
|
-- Ensure the queue has something to process.. |
|
|
|
if (#attachmentQueue > queOffset) then |
|
|
|
if (#attachmentQueue > queOffset) then |
|
|
|
queOffset = 0 |
|
|
|
queOffset = 0 |
|
|
@ -223,12 +218,12 @@ function process_queue() |
|
|
|
local data = table.remove(attachmentQueue, 1); |
|
|
|
local data = table.remove(attachmentQueue, 1); |
|
|
|
|
|
|
|
|
|
|
|
-- Send the queued object.. |
|
|
|
-- Send the queued object.. |
|
|
|
--print("Sending packet #"..(#attachmentQueue + 1)) |
|
|
|
--print("Sending packet #"..(#attachmentQueue + 1)) |
|
|
|
AddOutgoingPacket(data[1], data[2]); |
|
|
|
AddOutgoingPacket(data[1], data[2]); |
|
|
|
elseif (#attachmentQueue == queOffset and inProgress == true) then |
|
|
|
elseif (#attachmentQueue == queOffset and inProgress == true) then |
|
|
|
print("Attachment change completed") |
|
|
|
print("Attachment change completed") |
|
|
|
inProgress = false |
|
|
|
inProgress = false |
|
|
|
queOffset = 1 |
|
|
|
queOffset = 1 |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
@ -241,8 +236,10 @@ end |
|
|
|
ashita.register_event('render', function() |
|
|
|
ashita.register_event('render', function() |
|
|
|
-- Process the objectives packet queue.. |
|
|
|
-- Process the objectives packet queue.. |
|
|
|
process_queue(); |
|
|
|
process_queue(); |
|
|
|
|
|
|
|
attFromMemory(); |
|
|
|
end); |
|
|
|
end); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------------------------- |
|
|
|
--------------------------------------------------------------------------------------------------- |
|
|
|
-- func: load_pupattSettings |
|
|
|
-- func: load_pupattSettings |
|
|
|
-- desc: load pup attachments from a file and sets currentattachment equip. |
|
|
|
-- desc: load pup attachments from a file and sets currentattachment equip. |
|
|
@ -250,7 +247,6 @@ end); |
|
|
|
|
|
|
|
|
|
|
|
function load_pupattSettings() |
|
|
|
function load_pupattSettings() |
|
|
|
local tempCommands = ashita.settings.load(_addon.path .. '/settings/pupattProfiles.json'); |
|
|
|
local tempCommands = ashita.settings.load(_addon.path .. '/settings/pupattProfiles.json'); |
|
|
|
|
|
|
|
|
|
|
|
if tempCommands ~= nil then |
|
|
|
if tempCommands ~= nil then |
|
|
|
print('Stored objective profiles found.'); |
|
|
|
print('Stored objective profiles found.'); |
|
|
|
pupattProfiles = tempCommands; |
|
|
|
pupattProfiles = tempCommands; |
|
|
@ -275,9 +271,9 @@ function new_profile(profileName) |
|
|
|
print(convk) |
|
|
|
print(convk) |
|
|
|
print(convv) |
|
|
|
print(convv) |
|
|
|
end |
|
|
|
end |
|
|
|
table.insert(newProfile, convv) |
|
|
|
table.insert(newProfile, convv) |
|
|
|
end |
|
|
|
end |
|
|
|
pupattProfiles[profileName] = newProfile; |
|
|
|
pupattProfiles[profileName] = newProfile; |
|
|
|
end; |
|
|
|
end; |
|
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------------------------- |
|
|
|
--------------------------------------------------------------------------------------------------- |
|
|
@ -296,16 +292,21 @@ end; |
|
|
|
--------------------------------------------------------------- |
|
|
|
--------------------------------------------------------------- |
|
|
|
|
|
|
|
|
|
|
|
function attFromMemory() |
|
|
|
function attFromMemory() |
|
|
|
local pointer1 = ashita.memory.findpattern('FFXiMain.dll', 0, 'C1E1032BC8B0018D????????????B9????????F3A55F5E5B', 10, 0); |
|
|
|
if (defaultAtt == false) then |
|
|
|
if (pointer1 == 0) then |
|
|
|
local pointer1 = ashita.memory.findpattern('FFXiMain.dll', 0, 'C1E1032BC8B0018D????????????B9????????F3A55F5E5B', 10, 0); |
|
|
|
err('Failed to locate current attachments, please cycle a attachment to continue.'); |
|
|
|
if (pointer1 == 0) then |
|
|
|
else |
|
|
|
err('Failed to locate current attachments, please cycle a attachment to continue.'); |
|
|
|
local offset1 = ashita.memory.read_uint32(pointer1); |
|
|
|
else |
|
|
|
pointer = ashita.memory.read_uint32(AshitaCore:GetPointerManager():GetPointer('inventory')); |
|
|
|
local offset1 = ashita.memory.read_uint32(pointer1); |
|
|
|
pointer = ashita.memory.read_uint32(pointer); |
|
|
|
pointer = ashita.memory.read_uint32(AshitaCore:GetPointerManager():GetPointer('inventory')); |
|
|
|
currentAttachments = ashita.memory.read_array((pointer + offset1) + offset, 0x0E); |
|
|
|
pointer = ashita.memory.read_uint32(pointer); |
|
|
|
for i = 1, 14 do |
|
|
|
currentAttachments = ashita.memory.read_array((pointer + offset1) + offset, 0x0E); |
|
|
|
currentAttachments[i] = string.format("0x%X" , currentAttachments[i]); |
|
|
|
if (currentAttachments ~= nil) then |
|
|
|
|
|
|
|
for i = 1, 14 do |
|
|
|
|
|
|
|
currentAttachments[i] = string.format("0x%X" , currentAttachments[i]); |
|
|
|
|
|
|
|
end |
|
|
|
|
|
|
|
defaultAtt = true |
|
|
|
|
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
end; |
|
|
|
end; |
|
|
@ -346,13 +347,13 @@ ashita.register_event('command', function(command, ntype) |
|
|
|
local args = command:args(); |
|
|
|
local args = command:args(); |
|
|
|
|
|
|
|
|
|
|
|
if (args[1] ~= '/pupatt') then |
|
|
|
if (args[1] ~= '/pupatt') then |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
end |
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
if (#args == 3 and args[2] == 'newprofile') then |
|
|
|
if (#args == 3 and args[2] == 'newprofile') then |
|
|
|
new_profile(args[3]) |
|
|
|
new_profile(args[3]) |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
end |
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
if (#args >= 2 and args[2] == 'list') then |
|
|
|
if (#args >= 2 and args[2] == 'list') then |
|
|
|
list_profiles() |
|
|
|
list_profiles() |
|
|
@ -393,19 +394,21 @@ ashita.register_event('command', function(command, ntype) |
|
|
|
else |
|
|
|
else |
|
|
|
print (args[3] .. " profile not found"); |
|
|
|
print (args[3] .. " profile not found"); |
|
|
|
end |
|
|
|
end |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
end |
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
-- Prints the addon help.. |
|
|
|
-- Prints the addon help.. |
|
|
|
print_help('/pupatt', { |
|
|
|
print_help('/pupatt', { |
|
|
|
{'/pupatt load profileName', ' - Loads a saved profile from settings. '}, |
|
|
|
{'/pupatt load profileName', ' - Loads a saved profile from settings. '}, |
|
|
|
{'/pupatt newprofile profileName', ' - creates a new profile.'}, |
|
|
|
{'/pupatt newprofile profileName', ' - creates a new profile.'}, |
|
|
|
{'/pupatt save', ' - Saves the new profile created.'}, |
|
|
|
{'/pupatt save', ' - Saves the new profile created.'}, |
|
|
|
{'/pupatt list', ' - Lists the profiles as well as the hex values for each attachment.'}, |
|
|
|
{'/pupatt list', ' - Lists the profiles as well as the hex values for each attachment.'}, |
|
|
|
{'/pupatt current', ' - Lists the current attachments hex values.'}, |
|
|
|
{'/pupatt current', ' - Lists the current attachments hex values.'}, |
|
|
|
{'/pupatt clear', ' - Clears the current attachments.'}, |
|
|
|
{'/pupatt clear', ' - Clears the current attachments.'}, |
|
|
|
{'/pupatt spawn', ' - Spawns the puppet using whatever is off cooldown.'}, |
|
|
|
{'/pupatt spawn', ' - Spawns the puppet using whatever is off cooldown.'}, |
|
|
|
{'/pupatt despawn', ' - despawns the puppet.'}, |
|
|
|
{'/pupatt despawn', ' - despawns the puppet.'}, |
|
|
|
}); |
|
|
|
}); |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
end); |
|
|
|
end); |
|
|
|