Code:
#!/usr/bin/perl -w
use strict;
my $charProfile = << 'END'
/*
** Player Profile
** Length: 18496 Octets
** OpCode: CharProfileCode
*/
struct charProfileStruct
{
/*0000*/ uint32_t checksum; //
/*0004*/ char name[64]; // Name of player
/*0068*/ char lastName[32]; // Last name of player
/*0100*/ uint32_t gender; // Player Gender - 0 Male, 1 Female
/*0104*/ uint32_t race; // Player race
/*0108*/ uint32_t class_; // Player class
/*0112*/ uint32_t unknown0112; // *** Placeholder
/*0116*/ uint32_t level; // Level of player (might be one byte)
/*0120*/ uint32_t bind_zone_id[5]; // Bind info (zone, x, y, z, heading)
/*0140*/ float bind_x[5]; // 0 is normal bind
/*0160*/ float bind_y[5]; // 5 is some weird point in newbie zone
/*0180*/ float bind_z[5]; // (which is secondary bind for wiz/dru?)
/*0200*/ float bind_heading[5]; // Unused slots show newbie bind
/*0220*/ uint32_t deity; // deity
/*0224*/ int32_t guildID; // guildID
/*0228*/ uint32_t birthdayTime; // character birthday
/*0232*/ uint32_t lastSaveTime; // character last save time
/*0236*/ uint32_t timePlayedMin; // time character played
/*0240*/ uint8_t pvp; // 1=pvp, 0=not pvp
/*0241*/ uint8_t level1; // Level of Player
/*0242*/ uint8_t anon; // 2=roleplay, 1=anon, 0=not anon
/*0243*/ uint8_t gm; // 0=no, 1=yes
/*0244*/ int8_t guildstatus; // 0=member, 1=officer, 2=guildleader
/*0245*/ uint8_t unknown0245[55]; // *** Placeholder
/*0300*/ uint8_t haircolor; // Player hair color
/*0301*/ uint8_t beardcolor; // Player beard color
/*0302*/ uint8_t eyecolor1; // Player left eye color
/*0303*/ uint8_t eyecolor2; // Player right eye color
/*0304*/ uint8_t hairstyle; // Player hair style
/*0305*/ uint8_t beard; // Player beard type
/*0306*/ uint8_t unknown0302[6]; // *** Placeholder
/*0312*/ uint32_t item_material[9]; // Item texture/material of worn items
/*0348*/ uint8_t unknown0348[48]; // *** Placeholder
/*0396*/ Color_Struct item_tint[9]; // RR GG BB 00
/*0432*/ AA_Array aa_array[MAX_AA]; // AAs
/*1392*/ char servername[32]; // server the char was created on
/*1424*/ uint8_t unknown1452[68]; // *** Placeholder
/*1492*/ uint32_t exp; // Current Experience
/*1496*/ uint32_t unknown1496; // *** Placeholder
/*1500*/ uint32_t points; // Unspent Practice points
/*1504*/ uint32_t MANA; // Current MANA
/*1508*/ uint32_t curHp; // Current HP without +HP equipment
/*1512*/ uint32_t unknown1512; // 0x05
/*1516*/ uint32_t STR; // Strength
/*1520*/ uint32_t STA; // Stamina
/*1524*/ uint32_t CHA; // Charisma
/*1528*/ uint32_t DEX; // Dexterity
/*1532*/ uint32_t INT; // Intelligence
/*1536*/ uint32_t AGI; // Agility
/*1540*/ uint32_t WIS; // Wisdom
/*1544*/ uint8_t face; // Player face
/*1545*/ uint8_t unknown1545[47]; // *** Placeholder
/*1592*/ uint8_t languages[25]; // List of languages (MAX_KNOWN_LANGS)
/*1617*/ uint8_t unknown1617[7]; // All 0x00 (language buffer?)
/*1624*/ int32_t sSpellBook[400]; // List of the Spells in spellbook
/*3224*/ uint8_t unknown3224[448]; // all 0xff after last spell
/*3672*/ int32_t sMemSpells[9]; // List of spells memorized
/*3708*/ uint8_t unknown3708[32]; // *** Placeholder
/*3740*/ float x; // Players x position
/*3744*/ float y; // Players y position
/*3748*/ float z; // Players z position
/*3752*/ float heading; // Players heading
/*3756*/ uint8_t unknown3756[4]; // *** Placeholder
/*3760*/ uint32_t platinum; // Platinum Pieces on player
/*3764*/ uint32_t gold; // Gold Pieces on player
/*3768*/ uint32_t silver; // Silver Pieces on player
/*3772*/ uint32_t copper; // Copper Pieces on player
/*3776*/ uint32_t platinum_bank; // Platinum Pieces in Bank
/*3780*/ uint32_t gold_bank; // Gold Pieces in Bank
/*3784*/ uint32_t silver_bank; // Silver Pieces in Bank
/*3788*/ uint32_t copper_bank; // Copper Pieces in Bank
/*3792*/ uint32_t platinum_cursor; // Platinum Pieces on cursor
/*3796*/ uint32_t gold_cursor; // Gold Pieces on cursor
/*3800*/ uint32_t silver_cursor; // Silver Pieces on cursor
/*3804*/ uint32_t copper_cursor; // Copper Pieces on cursor
/*3808*/ uint32_t platinum_shared; // Shared platinum pieces
/*3812*/ uint8_t unknown3812[20]; // Unknown - all zero
/*3832*/ uint32_t skills[75]; // List of skills (MAX_KNOWN_SKILLS)
/*4132*/ uint8_t unknown4132[348]; // *** Placeholder
/*4480*/ uint32_t expAA; // Current AA experience
/*4484*/ uint8_t unknown4484[4]; // *** Placeholder
/*4488*/ uint32_t expansions; // Bitmask for expansions
/*4492*/ uint8_t unknown4492[20]; // *** Placeholder
/*4512*/ uint32_t hunger; // Food (ticks till next eat)
/*4516*/ uint32_t thirst; // Drink (ticks till next drink)
/*4520*/ uint8_t unknown4520[20]; // *** Placeholder
/*4540*/ uint16_t zoneId; // see zones.h
/*4542*/ uint16_t zoneInstance; // Instance id
/*4544*/ spellBuff buffs[MAX_BUFFS]; // Buffs currently on the player
/*4944*/ char groupMembers[MAX_GROUP_MEMBERS][64];// all the members in group, including self
/*5328*/ uint8_t unknown5328[668]; // *** Placeholder
/*5996*/ uint32_t ldon_guk_points; // Earned GUK points
/*6000*/ uint32_t ldon_mir_points; // Earned MIR points
/*6004*/ uint32_t ldon_mmc_points; // Earned MMC points
/*6008*/ uint32_t ldon_ruj_points; // Earned RUJ points
/*6012*/ uint32_t ldon_tak_points; // Earned TAK points
/*6016*/ uint32_t ldon_avail_points; // Available LDON points
/*6020*/ uint8_t unknown6020[112]; // *** Placeholder
/*6132*/ uint32_t tributeTime; // Time remaining on tribute (millisecs)
/*6136*/ uint32_t unknown6136; // *** Placeholder
/*6140*/ uint32_t careerTribute; // Total favor points for this char
/*6144*/ uint32_t unknown6144; // *** Placeholder
/*6148*/ uint32_t currentTribute; // Current tribute points
/*6152*/ uint32_t unknown6152; // *** Placeholder
/*6156*/ uint32_t tributeActive; // 0 = off, 1=on
/*6160*/ TributeStruct tributes[MAX_TRIBUTES]; // Current tribute loadout
/*6200*/ uint32_t disciplines[MAX_DISCIPLINES]; // Known disciplines
/*6400*/ uint8_t unknown6400[440]; // *** Placeholder
/*6840*/ uint32_t endurance; // Current endurance
/*6844*/ uint8_t unknown6844[276]; // *** Placeholder
/*7120*/ uint32_t airRemaining; // Air supply (seconds)
/*7124*/ uint8_t unknown7124[4608]; // *** Placeholder
/*11732*/ uint32_t aa_spent; // Number of spent AA points
/*11736*/ uint32_t unknown11736; // *** Placeholder
/*11740*/ uint32_t aa_unspent; // Unspent AA points
/*11744*/ uint8_t unknown11744[36]; // *** Placeholder
/*11780*/ BandolierStruct bandoliers[MAX_BANDOLIERS]; // bandolier contents
/*13060*/ uint8_t unknown13060[5120]; // *** Placeholder
/*18180*/ InlineItem potionBelt[MAX_POTIONS_IN_BELT]; // potion belt
/*18468*/ uint8_t unknown18468[8]; // *** Placeholder
/*18476*/ uint32_t currentRadCrystals; // Current count of radiant crystals
/*18480*/ uint32_t careerRadCrystals; // Total count of radiant crystals ever
/*18484*/ uint32_t currentEbonCrystals;// Current count of ebon crystals
/*18488*/ uint32_t careerEbonCrystals; // Total count of ebon crystals ever
/*18492*/ uint32_t unknown18492; // *** Placeholder
}; /* 18496 */
END
;
# load struct
my @struct = ();
while ($charProfile =~ /^(.*)$/mcg) {
my $line = $1;
if ($line =~ /^.*\s(\S+)\s+(\S+)\;/) {
my $type = $1;
my $name = $2;
push(@struct, { 'name' => $name, 'type' => $type } );
}
}
# load data
my @data = ();
open(PACKET, "./packet.txt");
while (my $line = <PACKET>) {
if ($line =~ /^\d+ \| ([0-9a-f ]+?) \|/) {
$line = $1;
while ($line =~ /([0-9a-f]{2})/mcg) {
push(@data, hex($1));
}
}
}
close(PACKET);
print "Loaded ". ($#data + 1) ." bytes.\n";
# fill in struct
my $offset = 0;
foreach my $i (0..$#struct) {
my $type = $struct[$i]{'type'};
my $name = $struct[$i]{'name'};
my $alen = 0;
my $size = 0;
if ($name =~ /(\S+)\[([0-9]+)\]/) {
$name = $1;
$alen = $2 - 1;
}
if ($alen > 0) {
printf("%04d: %s\t%s[%d]: ", $offset, $type, $name, $alen + 1);
} else {
printf("%04d: %s\t%s: ", $offset, $type, $name);
}
if ($type eq "uint8_t") {
$size = 1;
foreach my $j (0..$alen) {
print unpack("C", pack("C", $data[$offset + $j * $size])) ." ";
}
} elsif ($type eq "uint16_t") {
$size = 2;
foreach my $j (0..$alen) {
print unpack("S", pack("CC", $data[$offset + $j * $size], $data[$offset + 1 + $j * $size])) ." ";
}
} elsif ($type eq "uint32_t") {
if ($name eq "disciplines[MAX_DISCIPLINES]") {
$alen = 50 - 1;
$size = 4;
} else {
$size = 4;
foreach my $j (0..$alen) {
print unpack("L", pack("CCCC", $data[$offset + $j * $size], $data[$offset + 1 + $j * $size],
$data[$offset + 2 + $j * $size], $data[$offset + 3 + $j * $size])) ." ";
}
}
} elsif ($type eq "int8_t") {
$size = 1;
foreach my $j (0..$alen) {
print unpack("c", pack("C", $data[$offset + $j * $size])) ." ";
}
} elsif ($type eq "int16_t") {
$size = 2;
foreach my $j (0..$alen) {
print unpack("s", pack("CC", $data[$offset + $j * $size], $data[$offset + 1 + $j * $size])) ." ";
}
} elsif ($type eq "int32_t") {
$size = 4;
foreach my $j (0..$alen) {
print unpack("l", pack("CCCC", $data[$offset + $j * $size], $data[$offset + 1 + $j * $size],
$data[$offset + 2 + $j * $size], $data[$offset + 3 + $j * $size])) ." ";
}
} elsif ($type eq "float") {
$size = 4;
foreach my $j (0..$alen) {
my $num = pack("CCCC", $data[$offset + 0], $data[$offset + 1],
$data[$offset + 2], $data[$offset + 3]);
print unpack("f", $num) ." ";
}
} elsif ($type eq "char") {
if ($name eq "groupMembers[MAX_GROUP_MEMBERS]") {
$alen = 6 - 1;
$size = 64;
} else {
foreach my $j (0..$alen) {
if ($data[$offset + $j] > 0x1f && $data[$offset + $j] < 0x80) {
printf("%c", $data[$offset+$j]);
} else {
print ".";
}
}
$size = 1;
}
} elsif ($type eq "Color_Struct") {
# B R G A
$size = 4;
} elsif ($type eq "AA_Array") {
# AA value
$alen = 120 - 1;
$size = 8;
} elsif ($type eq "spellBuff") {
# slotid level effect spellid padding duration unknown
$alen = 25 - 1;
$size = 16;
} elsif ($name eq "groupMembers") {
# Group members
$alen = 6 - 1;
$size = 64;
} elsif ($type eq "TributeStruct") {
# Group Members
$alen = 5 - 1;
$size = 8;
} elsif ($type eq "BandolierStruct") {
# Bandolier Structure
$alen = 4 - 1;
$size = 320;
} elsif ($type eq "InlineItem") {
# Potion Belt
$alen = 4 - 1;
$size = 72;
} else {
die "Unknown type: $type\n";
}
print "\n";
$offset += ($size * ($alen + 1));
}
printf("%04d: END\n", $offset);
I had to do some updating to it, but I'm not a perl programmer. It works but isn't done right.