Advertisement
smd111

packet_parsing

Oct 8th, 2016
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 26.83 KB | None | 0 0
  1. --Copyright (c) 2013~2016, Byrthnoth
  2. --All rights reserved.
  3.  
  4. --Redistribution and use in source and binary forms, with or without
  5. --modification, are permitted provided that the following conditions are met:
  6.  
  7. --    * Redistributions of source code must retain the above copyright
  8. --      notice, this list of conditions and the following disclaimer.
  9. --    * Redistributions in binary form must reproduce the above copyright
  10. --      notice, this list of conditions and the following disclaimer in the
  11. --      documentation and/or other materials provided with the distribution.
  12. --    * Neither the name of <addon name> nor the
  13. --      names of its contributors may be used to endorse or promote products
  14. --      derived from this software without specific prior written permission.
  15.  
  16. --THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  17. --ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. --WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. --DISCLAIMED. IN NO EVENT SHALL <your name> BE LIABLE FOR ANY
  20. --DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. --(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. --LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. --ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. --(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. --SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26.  
  27. parse = {
  28.     i={}, -- Incoming packets
  29.     o={}  -- Outgoing packets, currently none are really parsed for information
  30.     }
  31.  
  32. parse.i[0x00A] = function (data)
  33.     windower.debug('zone change')
  34.     command_registry = Command_Registry.new()
  35.     table.clear(not_sent_out_equip)
  36.    
  37.     player.id = data:unpack('I',0x05)
  38.     player.index = data:unpack('H',0x09)
  39.     if player.main_job_id and player.main_job_id ~= data:byte(0xB5) and player.name and player.name == data:unpack('z',0x85) and not gearswap_disabled then
  40.         windower.debug('job change on zone')
  41.         load_user_files(data:byte(0xB5))
  42.     else
  43.         player.name = data:unpack('z',0x85)
  44.     end
  45.     player.main_job_id = data:byte(0xB5)
  46.     player.sub_job_id = data:byte(0xB8)
  47.     player.vitals.max_hp = data:unpack('I',0xE9)
  48.     player.vitals.max_mp = data:unpack('I',0xED)
  49.     player.max_hp = data:unpack('I',0xE9)
  50.     player.max_mp = data:unpack('I',0xED)
  51.     update_job_names()
  52.    
  53.     world.zone_id = data:unpack('H',0x31)
  54.     _ExtraData.world.conquest = false
  55.     for i,v in pairs(region_to_zone_map) do
  56.         if v:contains(world.zone_id) then
  57.             _ExtraData.world.conquest = {
  58.                 region_id = i,
  59.                 region_name = res.regions[i][language],
  60.                 }
  61.             break
  62.         end
  63.     end
  64.     weather_update(data:byte(0x69))
  65.     world.logged_in = true
  66.    
  67.     _ExtraData.world.in_mog_house = data:byte(0x81) == 1
  68.    
  69.     _ExtraData.player.base_str = data:unpack('H',0xCD)
  70.     _ExtraData.player.base_dex = data:unpack('H',0xCF)
  71.     _ExtraData.player.base_vit = data:unpack('H',0xD1)
  72.     _ExtraData.player.base_agi = data:unpack('H',0xD3)
  73.     _ExtraData.player.base_int = data:unpack('H',0xD5)
  74.     _ExtraData.player.base_mnd = data:unpack('H',0xD7)
  75.     _ExtraData.player.base_chr = data:unpack('H',0xD9)
  76.     _ExtraData.player.add_str = data:unpack('h',0xDB)
  77.     _ExtraData.player.add_dex = data:unpack('h',0xDD)
  78.     _ExtraData.player.add_vit = data:unpack('h',0xDF)
  79.     _ExtraData.player.add_agi = data:unpack('h',0xE1)
  80.     _ExtraData.player.add_int = data:unpack('h',0xE3)
  81.     _ExtraData.player.add_mnd = data:unpack('h',0xE5)
  82.     _ExtraData.player.add_chr = data:unpack('h',0xE7)
  83.    
  84.     _ExtraData.player.str = _ExtraData.player.base_str + _ExtraData.player.add_str
  85.     _ExtraData.player.dex = _ExtraData.player.base_dex + _ExtraData.player.add_dex
  86.     _ExtraData.player.vit = _ExtraData.player.base_vit + _ExtraData.player.add_vit
  87.     _ExtraData.player.agi = _ExtraData.player.base_agi + _ExtraData.player.add_agi
  88.     _ExtraData.player.int = _ExtraData.player.base_int + _ExtraData.player.add_int
  89.     _ExtraData.player.mnd = _ExtraData.player.base_mnd + _ExtraData.player.add_mnd
  90.     _ExtraData.player.chr = _ExtraData.player.base_chr + _ExtraData.player.add_chr
  91.     refresh_ffxi_info()
  92.    
  93.     delay_0x063_v9 = true
  94. end
  95.  
  96. parse.i[0x00B] = function(data)
  97.     -- Blank temporary items when zoning.
  98.     items.temporary = make_inventory_table()
  99. end
  100.  
  101. parse.i[0x00E] = function (data)
  102.     if pet.index and pet.index == data:unpack('H',9) and math.floor((data:byte(11)%8)/4)== 1 then
  103.         local status_id = data:byte(32)
  104.         -- Filter all statuses aside from Idle/Engaged/Dead/Engaged dead.
  105.         if pet.status_id ~= status_id and (status_id < 4 or status_id == 33 or status_id == 47) then
  106.             if not next_packet_events then next_packet_events = {sequence_id = data:unpack('H',3)} end
  107.             next_packet_events.pet_status_change = {newstatus=res.statuses[status_id][language],oldstatus=pet.status}
  108.             pet.status = res.statuses[status_id][language]
  109.             pet.status_id = status_id
  110.         end
  111.     end
  112. end
  113.  
  114. parse.i[0x01B] = function (data)
  115.     for job_id = 1,23 do
  116.         player.jobs[to_windower_api(res.jobs[job_id].english)] = data:byte(job_id + 72)
  117.     end
  118.    
  119.     local enc = data:unpack('H',0x61)
  120.     local tab = {}
  121.     for slot_id,slot_name in pairs(default_slot_map) do
  122.         local tf = (((enc%(2^(slot_id+1))) / 2^slot_id) >= 1)
  123.         if encumbrance_table[slot_id] and not tf and not_sent_out_equip[slot_name] and not disable_table[i] then
  124.             tab[slot_name] = not_sent_out_equip[slot_name]
  125.             not_sent_out_equip[slot_name] = nil
  126.         end
  127.         if encumbrance_table[slot_id] and not tf then
  128.             msg.debugging("Your "..slot_name.." slot is now unlocked.")
  129.         end
  130.         encumbrance_table[slot_id] = tf
  131.     end
  132.     if table.length(tab) > 0 and not gearswap_disabled then
  133.         refresh_globals()
  134.         equip_sets('equip_command',nil,tab)
  135.     end
  136. end
  137.  
  138. parse.i[0x01D] = function (data)
  139.     --all item updates only need to be triggered when this packet is sent
  140.     local cur_equip = table.reassign({},items.equipment)
  141.     player.equipment = make_user_table()
  142.     table.reassign(player.equipment,to_names_set(cur_equip))
  143.     for i,bag in pairs(res.bags) do
  144.         local bag_name = to_windower_bag_api(bag.en)
  145.         if items[bag_name] then player[bag_name] = refresh_item_list(items[bag_name]) end
  146.     end
  147. end
  148.  
  149. parse.i[0x01E] = function (data)
  150.     local bag = to_windower_compact(res.bags[data:byte(0x09)].english)
  151.     local slot = data:byte(0x0A)
  152.     local count = data:unpack('I',5)
  153.     local status = data:byte(0x0B)
  154.     if not items[bag][slot] then items[bag][slot] = make_empty_item_table(slot) end
  155.     items[bag][slot].count = count
  156.     items[bag][slot].status = status
  157.     if count == 0 then
  158.         items[bag][slot].id = 0
  159.         items[bag][slot].bazaar = 0
  160.         items[bag][slot].status = 0
  161.     end
  162. end
  163.  
  164. parse.i[0x01F] = function (data)
  165.     local bag = to_windower_compact(res.bags[data:byte(0x0B)].english)
  166.     local slot = data:byte(0x0C)
  167.     if not items[bag][slot] then items[bag][slot] = make_empty_item_table(slot) end
  168.     items[bag][slot].id = data:unpack('H',9)
  169.     items[bag][slot].count = data:unpack('I',5)
  170.     items[bag][slot].status = data:byte(0x0D)
  171. end
  172.  
  173. parse.i[0x020] = function (data)
  174.         local bag = to_windower_compact(res.bags[data:byte(0x0F)].english)
  175.         local slot = data:byte(0x10)
  176.         if not items[bag][slot] then items[bag][slot] = make_empty_item_table(slot) end
  177.         items[bag][slot].id = data:unpack('H',0x0D)
  178.         items[bag][slot].count = data:unpack('I',5)
  179.         items[bag][slot].bazaar = data:unpack('I',9)
  180.         items[bag][slot].status = data:byte(0x11)
  181.         items[bag][slot].extdata = data:sub(0x12,0x29)
  182.         -- Did not mess with linkshell stuff
  183. end
  184.  
  185. parse.i[0x037] = function (data)
  186.     player.status_id = data:byte(0x31)
  187.     --[[local bitmask = data:sub(0x4D,0x54)
  188.     for i = 1,32 do
  189.         local bitmask_position = 2*((i-1)%4)
  190.         local id = data:byte(4+i) + 256*math.floor(bitmask:byte(1+math.floor((i-1)/4))%(2^(bitmask_position+2))/(2^bitmask_position))
  191.         if player.buffs[i] ~= id then
  192.             if id == 255 and player.buffs[i] then
  193.                 player.buffs[i] = nil
  194.             elseif id ~= 255 then
  195.                 player.buffs[i] = id
  196.             end
  197.         end
  198.     end]]
  199.    
  200.     local indi_byte = data:byte(0x59)
  201.     if indi_byte%128/64 >= 1 then
  202.         local temp_indi = _ExtraData.player.indi
  203.         _ExtraData.player.indi = {
  204.                 element = res.elements[indi_byte%8][language],
  205.                 element_id = indi_byte%8,
  206.                 size = math.floor((indi_byte%64)/16) + 1, -- Size range of 1~4
  207.             }
  208.         if (indi_byte%16)/8 >= 1 then
  209.             _ExtraData.player.indi.target = 'Enemy'
  210.         else
  211.             _ExtraData.player.indi.target = 'Ally'
  212.         end
  213.         if not gearswap_disabled then
  214.             if not temp_indi then
  215.                 -- There was not an indi spell up
  216.                 refresh_globals()
  217.                 equip_sets('indi_change',nil,_ExtraData.player.indi,true)
  218.             elseif temp_indi.element_id ~= _ExtraData.player.indi.element_id or temp_indi.target ~= _ExtraData.player.indi.target or temp_indi.size ~= _ExtraData.player.indi.size then
  219.                 -- There was already an indi spell up, so check if it changed
  220.                 refresh_globals()
  221.                 equip_sets('indi_change',nil,temp_indi,false)
  222.                 equip_sets('indi_change',nil,_ExtraData.player.indi,true)
  223.             end
  224.         end
  225.     elseif _ExtraData.player.indi then
  226.         -- An indi effect has been lost.
  227.         local temp_indi = _ExtraData.player.indi
  228.         _ExtraData.player.indi = nil
  229.         if not gearswap_disabled then
  230.             refresh_globals()
  231.             equip_sets('indi_change',nil,temp_indi,false)
  232.         end
  233.     end
  234.  
  235.     local subj_ind = data:unpack('H', 0x35) / 8
  236.     if subj_ind == 0 and pet.isvalid then
  237.         if not next_packet_events then next_packet_events = {sequence_id = data:unpack('H',3)} end
  238.         refresh_globals()
  239.         pet.isvalid = false
  240.         _ExtraData.pet = {}
  241.         next_packet_events.pet_change = {pet = table.reassign({},pet)}
  242.     elseif subj_ind ~= 0 and not pet.isvalid then
  243.         if not next_packet_events then next_packet_events = {sequence_id = data:unpack('H',3)} end
  244.         _ExtraData.pet.tp = 0
  245.         next_packet_events.pet_change = {subj_ind = subj_ind}
  246.     end
  247. end
  248.  
  249. parse.i[0x044] = function (data) --add Automation skills to gearswap data
  250.     if data:unpack('C',0x05) == 0x12 then
  251.         player.skills.automaton_melee = data:unpack('H',0x71)
  252.         player.skills.automaton_archery = data:unpack('H',0x75)
  253.         player.skills.automaton_magic = data:unpack('H',0x79)
  254.     end
  255. end
  256.  
  257. parse.i[0x050] = function (data)
  258.     local inv = items[to_windower_compact(res.bags[data:byte(7)].english)]
  259.     if data:byte(5) ~= 0 then
  260.         items.equipment[toslotname(data:byte(6))] = {slot=data:byte(5),bag_id = data:byte(7)}
  261.         if not inv[data:byte(5)] then inv[data:byte(5)] = make_empty_item_table(data:byte(5)) end
  262.         items[to_windower_compact(res.bags[data:byte(7)].english)][data:byte(5)].status = 5 -- Set the status to "equipped"
  263.     else
  264.         items.equipment[toslotname(data:byte(6))] = {slot=empty,bag_id=0}
  265.         if not inv[data:byte(5)] then inv[data:byte(5)] = make_empty_item_table(data:byte(5)) end
  266.         items[to_windower_compact(res.bags[data:byte(7)].english)][data:byte(5)].status = 0 -- Set the status to "unequipped"
  267.     end
  268. end
  269.  
  270. parse.i[0x053] = function (data)
  271.     if data:unpack('H',0xD) == 0x12D and player then
  272.         -- You're unable to use trust magic if you're not the party leader or solo
  273.         local ts,tab = command_registry:find_by_time()
  274.         if tab and tab.spell and tab.spell.prefix ~= '/pet' and not gearswap_disabled then
  275.             tab.spell.action_type = 'Interruption'
  276.             tab.spell.interrupted = true
  277.             equip_sets('aftercast',nil,tab.spell)
  278.         end
  279.     end
  280. end
  281.  
  282. parse.i[0x05E] = function (data)
  283.     -- Conquest ID
  284.     if _ExtraData.world.conquest then
  285.         local offset = _ExtraData.world.conquest.region_id*4 + 11
  286.         if offset == 99 then
  287.             offset = 95
  288.         elseif offset == 107 then
  289.             offset = 99
  290.         end
  291.         local strength_map = {[0]='Minimal',[1]='Minor',[2]='Major',[3]='Dominant'}
  292.         local nation_map = {[0]={english='Neutral',japanese='Neutral'},[1]=res.regions[0],[2]=res.regions[1],
  293.             [3]=res.regions[2],[4]={english='Beastman',japanese='Beastman'},[0xFF]=res.regions[3]}
  294.         _ExtraData.world.conquest.strengths = {
  295.             sandoria=strength_map[data:byte(offset+2)%4],
  296.             bastok=strength_map[math.floor(data:byte(offset+2)%16/4)],
  297.             windurst=strength_map[math.floor(data:byte(offset+2)%64/16)],
  298.             beastmen=strength_map[math.floor(data:byte(offset+2)/64)],}
  299.         _ExtraData.world.conquest.nation = nation_map[data:byte(offset+3)][language]
  300.         _ExtraData.world.conquest.sandoria = data:byte(0x87)
  301.         _ExtraData.world.conquest.bastok = data:byte(0x88)
  302.         _ExtraData.world.conquest.windurst = data:byte(0x89)
  303.         _ExtraData.world.conquest.beastmen = 100-data:byte(0x87)-data:byte(0x88)-data:byte(0x89)
  304.     end
  305. end
  306.  
  307. parse.i[0x061] = function (data)
  308.     player.vitals.max_hp = data:unpack('I',5)
  309.     player.vitals.max_mp = data:unpack('I',9)
  310.     player.max_hp = data:unpack('I',5)
  311.     player.max_mp = data:unpack('I',9)
  312.     player.main_job_id = data:byte(13)
  313.     player.main_job_level = data:byte(14)
  314.    
  315.     _ExtraData.player.nation_id = data:byte(0x51)
  316.     _ExtraData.player.nation = res.regions[_ExtraData.player.nation_id][language] or 'None'
  317.     _ExtraData.player.base_str = data:unpack('H',0x15)
  318.     _ExtraData.player.base_dex = data:unpack('H',0x17)
  319.     _ExtraData.player.base_vit = data:unpack('H',0x19)
  320.     _ExtraData.player.base_agi = data:unpack('H',0x1B)
  321.     _ExtraData.player.base_int = data:unpack('H',0x1D)
  322.     _ExtraData.player.base_mnd = data:unpack('H',0x1F)
  323.     _ExtraData.player.base_chr = data:unpack('H',0x21)
  324.     _ExtraData.player.add_str = data:unpack('h',0x23)
  325.     _ExtraData.player.add_dex = data:unpack('h',0x25)
  326.     _ExtraData.player.add_vit = data:unpack('h',0x27)
  327.     _ExtraData.player.add_agi = data:unpack('h',0x29)
  328.     _ExtraData.player.add_int = data:unpack('h',0x2B)
  329.     _ExtraData.player.add_mnd = data:unpack('h',0x2D)
  330.     _ExtraData.player.add_chr = data:unpack('h',0x2F)
  331.     _ExtraData.player.attack = data:unpack('H',0x31)
  332.     _ExtraData.player.defense = data:unpack('H',0x33)
  333.     _ExtraData.player.fire_resistance = data:unpack('h',0x35)
  334.     _ExtraData.player.wind_resistance = data:unpack('h',0x37)
  335.     _ExtraData.player.lightning_resistance = data:unpack('h',0x39)
  336.     _ExtraData.player.light_resistance = data:unpack('h',0x3B)
  337.     _ExtraData.player.ice_resistance = data:unpack('h',0x3D)
  338.     _ExtraData.player.earth_resistance = data:unpack('h',0x3F)
  339.     _ExtraData.player.water_resistance = data:unpack('h',0x41)
  340.     _ExtraData.player.dark_resistance = data:unpack('h',0x43)
  341.    
  342.     _ExtraData.player.str = _ExtraData.player.base_str + _ExtraData.player.add_str
  343.     _ExtraData.player.dex = _ExtraData.player.base_dex + _ExtraData.player.add_dex
  344.     _ExtraData.player.vit = _ExtraData.player.base_vit + _ExtraData.player.add_vit
  345.     _ExtraData.player.agi = _ExtraData.player.base_agi + _ExtraData.player.add_agi
  346.     _ExtraData.player.int = _ExtraData.player.base_int + _ExtraData.player.add_int
  347.     _ExtraData.player.mnd = _ExtraData.player.base_mnd + _ExtraData.player.add_mnd
  348.     _ExtraData.player.chr = _ExtraData.player.base_chr + _ExtraData.player.add_chr
  349.            
  350.     if player.sub_job_id ~= data:byte(15) then
  351.         -- Subjob change event
  352.         local temp_sub = player.sub_job
  353.         player.sub_job_id = data:byte(15)
  354.         player.sub_job_level = data:byte(16)
  355.         update_job_names()
  356.         if not gearswap_disabled then
  357.             refresh_globals()
  358.             equip_sets('sub_job_change',nil,player.sub_job,temp_sub)
  359.         end
  360.     end
  361.     update_job_names()
  362. end
  363.  
  364. parse.i[0x062] = function (data)
  365.     for i = 1,0x71,2 do
  366.         local skill = data:unpack('H',i + 0x82)%32768
  367.         local current_skill = res.skills[math.floor(i/2)+1]
  368.         if current_skill then
  369.             player.skills[to_windower_api(current_skill.english)] = skill
  370.         end
  371.     end
  372. end
  373.  
  374. parse.i[0x063] = function (data)
  375.     if data:byte(0x05) == 0x09 and not delay_0x063_v9 then
  376.         local newbuffs = {}
  377.         for i=1,32 do
  378.             local buff_id = data:unpack('H',i*2+7)
  379.             if buff_id ~= 255 and buff_id ~= 0 then -- 255 is used for "no buff"
  380.                 local t = data:unpack('I',i*4+0x45)/60+1439307535
  381.                 newbuffs[i] = setmetatable({
  382.                     name=res.buffs[buff_id].name,
  383.                     buff=copy_entry(res.buffs[buff_id]),
  384.                     id = buff_id,
  385.                     time=t,
  386.                     date=os.date('*t',t),
  387.                     },
  388.                     {__index=function(t,k)
  389.                         if k and k=='duration' then
  390.                             return rawget(t,'time')-os.time()
  391.                         else
  392.                             return rawget(t,k)
  393.                         end
  394.                     end})
  395.             end
  396.         end
  397.         if seen_0x063_type9 then
  398.        
  399.             for n,new in pairs(newbuffs) do        
  400.                 -- Look for matches
  401.                 local matched_exactly = false
  402.                 local matched_imprecisely = false
  403.                 for i,old in pairs(_ExtraData.player.buff_details) do
  404.                     if old.id == new.id then
  405.                         -- Find unchanged buffs
  406.                         if math.abs(old.time-new.time) < 1 and not old.matched_exactly then
  407.                             matched_exactly = true
  408.                             _ExtraData.player.buff_details[i].matched_exactly = true
  409.                             break
  410.                         -- Find changed buffs
  411.                         elseif not (old.matched_exactly or old.matched_imprecisely) then
  412.                             matched_imprecisely = true
  413.                             _ExtraData.player.buff_details[i].matched_imprecisely = true
  414.                             break
  415.                         end
  416.                     end
  417.                 end
  418.                
  419.                 if matched_imprecisely then
  420.                     -- Matched a previous buff, but the time didn't jive so it's assumed
  421.                     -- that it was overwritten with the same status effect
  422.                     if not res.buffs[new.id] then
  423.                         error('GearSwap: No known status for buff id #'..tostring(new.id))
  424.                     end
  425.                     local buff_name = res.buffs[new.id][language]
  426.                     windower.debug('refresh buff '..buff_name..' ('..tostring(new.id)..')')
  427.                     if not gearswap_disabled then
  428.                         refresh_globals()
  429.                         equip_sets('buff_refresh',nil,buff_name,new)
  430.                     end
  431.                 elseif not matched_exactly then
  432.                     -- Not matched, so it's assumed the buff is new
  433.                     if not res.buffs[new.id] then
  434.                         error('GearSwap: No known status for buff id #'..tostring(new.id))
  435.                     end
  436.                     local buff_name = res.buffs[new.id][language]
  437.                     windower.debug('gain buff '..buff_name..' ('..tostring(new.id)..')')
  438.                     -- Need to figure out what I'm going to do with this:
  439.                     if T{'terror','sleep','stun','petrification','charm','weakness'}:contains(buff_name:lower()) then
  440.                         for ts,v in pairs(command_registry) do
  441.                             if v.midaction then
  442.                                 command_registry:delete_entry(ts)
  443.                             end
  444.                         end
  445.                     end
  446.                     if not gearswap_disabled then
  447.                         refresh_globals()
  448.                         equip_sets('buff_change',nil,buff_name,true,new)
  449.                     end
  450.                 end
  451.             end
  452.            
  453.             for i,old in pairs(_ExtraData.player.buff_details) do
  454.                 if not (old.matched_exactly or old.matched_imprecisely) then
  455.                     -- Old status was not matched to any new status, so it's assumed it was lost
  456.                     if not res.buffs[old.id] then
  457.                         error('GearSwap: No known status for buff id #'..tostring(old.id))
  458.                     end
  459.                     local buff_name = res.buffs[old.id][language]
  460.                     windower.debug('lose buff '..buff_name..' ('..tostring(old.id)..')')
  461.                     if not gearswap_disabled then
  462.                         refresh_globals()
  463.                         equip_sets('buff_change',nil,buff_name,false,old)
  464.                     end
  465.                 end
  466.             end
  467.         end
  468.        
  469.         table.reassign(_ExtraData.player.buff_details,newbuffs)
  470.         for i=1,32 do
  471.             player.buffs[i] = (newbuffs[i] and newbuffs[i].id) or nil
  472.         end
  473.         -- Cannot reliably recall this packet using last_incoming on load because there
  474.         -- are 9 version of it and you only get the last one. Hence, this flag:
  475.         seen_0x063_type9 = true
  476.     elseif data:byte(0x05) == 0x09 then
  477.         delay_0x063_v9 = false
  478.     end
  479. end
  480.  
  481. parse.i[0x067] = function (data)
  482.     if data:byte(7)%128 == 4 and player.index == data:unpack('H',0x0D) then -- You are the owner
  483.         _ExtraData.pet.tp = data:unpack('H',0x11)
  484.     end
  485. end
  486.  
  487. parse.i[0x068] = function (data)
  488.     if data:byte(7)%128 == 4 and player.id == data:unpack('I',0x09) then -- You are the owner
  489.         _ExtraData.pet.tp = data:unpack('H',0x11)
  490.     end
  491. end
  492.  
  493. parse.i[0x076] = function (data)
  494.     partybuffs = {}
  495.     for i = 0,4 do
  496.         if data:unpack('I',i*48+5) == 0 then
  497.             break
  498.         else
  499.             local index = data:unpack('H',i*48+5+4)
  500.             partybuffs[index] = {
  501.                 id = data:unpack('I',i*48+5+0),
  502.                 index = data:unpack('H',i*48+5+4),
  503.                 buffs = {}
  504.             }
  505.             for n=1,32 do
  506.                 partybuffs[index].buffs[n] = data:byte(i*48+5+16+n-1) + 256*( math.floor( data:byte(i*48+5+8+ math.floor((n-1)/4)) / 4^((n-1)%4) )%4)
  507.             end
  508.            
  509.            
  510.             if alliance[1] then
  511.                 local cur_player
  512.                 for n,m in pairs(alliance[1]) do
  513.                     if type(m) == 'table' and m.mob and m.mob.index == index then
  514.                         cur_player = m
  515.                         break
  516.                     end
  517.                 end
  518.                 local new_buffs = convert_buff_list(partybuffs[index].buffs)
  519.                 if cur_player and cur_player.buffactive and not gearswap_disabled then
  520.                     local old_buffs = cur_player.buffactive
  521.                 -- Make sure the character existed before (with a buffactive list) - Avoids zoning.
  522.                     for n,m in pairs(new_buffs) do
  523.                         if type(n) == 'number' and m ~= old_buffs[n] then
  524.                             if not old_buffs[n] or m > old_buffs[n] then -- gaining buff
  525.                                 equip_sets('party_buff_change',nil,cur_player,res.buffs[n][language],true,copy_entry(res.buffs[n]))
  526.                                 old_buffs[n] = nil
  527.                             else -- losing buff
  528.                                 equip_sets('party_buff_change',nil,cur_player,res.buffs[n][language],false,copy_entry(res.buffs[n]))
  529.                                 old_buffs[n] = nil
  530.                             end
  531.                         elseif type(n) ~= 'number' then
  532.                             -- Clear out the string entries so we don't have to iterate over them in the second loop
  533.                             old_buffs[n] = nil
  534.                         end
  535.                     end
  536.                    
  537.                     for n,m in pairs(old_buffs) do
  538.                         if type(n) == 'number' and m ~= new_buffs[n] then-- losing buff
  539.                             equip_sets('party_buff_change',nil,cur_player,res.buffs[n][language],false,copy_entry(res.buffs[n]))
  540.                         end
  541.                     end
  542.                 end
  543.                 if cur_player then
  544.                     cur_player.buffactive = new_buffs
  545.                 end
  546.             end
  547.            
  548.         end
  549.     end
  550. end
  551.  
  552. parse.i[0x0DF] = function (data)
  553.     if data:unpack('I',5) == player.id then
  554.         player.vitals.hp = data:unpack('I',9)
  555.         player.vitals.mp = data:unpack('I',13)
  556.         player.vitals.tp = data:unpack('I',0x11)
  557.         player.vitals.hpp = data:byte(0x17)
  558.         player.vitals.mpp = data:byte(0x18)
  559.        
  560.         player.hp = data:unpack('I',9)
  561.         player.mp = data:unpack('I',13)
  562.         player.tp = data:unpack('I',0x11)
  563.         player.hpp = data:byte(0x17)
  564.         player.mpp = data:byte(0x18)
  565.     end
  566. end
  567.  
  568. parse.i[0x0E2] = function (data)
  569.     if data:unpack('I',5)==player.id then
  570.         player.vitals.hp = data:unpack('I',9)
  571.         player.vitals.mp = data:unpack('I',0xB)
  572.         player.vitals.tp = data:unpack('I',0x11)
  573.         player.vitals.hpp = data:byte(0x1E)
  574.         player.vitals.mpp = data:byte(0x1F)
  575.        
  576.         player.hp = data:unpack('I',9)
  577.         player.mp = data:unpack('I',0xB)
  578.         player.tp = data:unpack('I',0x11)
  579.         player.hpp = data:byte(0x1E)
  580.         player.mpp = data:byte(0x1F)
  581.     end
  582. end
  583.  
  584. parse.i[0x117] = function (data)
  585.     for i=0x49,0x85,4 do
  586.         local arr = data:sub(i,i+3)
  587.         local inv = items[to_windower_compact(res.bags[arr:byte(3)].english)]
  588.         if arr:byte(1) ~= 0 then
  589.             items.equipment[toslotname(arr:byte(2))] = {slot=arr:byte(1),bag_id = arr:byte(3)}
  590.             if not inv[arr:byte(1)] then inv[arr:byte(1)] = make_empty_item_table(arr:byte(1)) end
  591.             items[to_windower_compact(res.bags[arr:byte(3)].english)][arr:byte(1)].status = 5 -- Set the status to "equipped"
  592.         else
  593.             items.equipment[toslotname(arr:byte(2))] = {slot=empty,bag_id=0}
  594.             if not inv[arr:byte(1)] then inv[arr:byte(1)] = make_empty_item_table(arr:byte(1)) end
  595.             items[to_windower_compact(res.bags[arr:byte(3)].english)][arr:byte(1)].status = 0 -- Set the status to "unequipped"
  596.         end
  597.     end
  598. end
  599.  
  600. function initialize_packet_parsing()
  601.     for i,v in pairs(parse.i) do
  602.         local lastpacket = windower.packets.last_incoming(i)
  603.         if lastpacket then
  604.             v(lastpacket)
  605.         end
  606.     end
  607. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement