=pod SAMPLE OUTPUT: -------------------------------------- Name: my_b Title information: 00001111 Character title: Patriarch/Matriarch Type: Sorceress Level: 1 Hell town: Act 1 Normal waypoints: 1000000000000000000000000000000000000000 Nightmare waypoints: 1000000000000000000000000000000000000000 Hell waypoints: 1111111111111111111111111111111111111111 Strength: 10 Energy: 35 Dexterity: 25 Vitality: 10 Statpts: 0 Newskills: 0 Hitpoints: 40 MaxHP: 40 Mana: 35 MaxMana: 35 Stamina: 74 MaxStamina: 74 Level: 1 Experience: 0 Gold: 0 GoldBank: 372352 Skill#1:0 Skill#2:0 Skill#3:0 Skill#4:0 Skill#5:0 Skill#6:0 Skill#7:0 Skill#8:0 Skill#9:0 Skill#10:0 Skill#11:0 Skill#12:0 Skill#13:0 Skill#14:0 Skill#15:0 Skill#16:0 Skill#17:0 Skill#18:0 Skill#19:0 Skill#20:0 Skill#21:0 Skill#22:0 Skill#23:0 Skill#24:0 Skill#25:0 Skill#26:0 Skill#27:0 Skill#28:0 Skill#29:0 Skill#30:0 =cut #TODO: # -make sure the magic numbers are proper or die() # -be able to change the quests. use warnings; use strict; use Data::Dumper; # my $D2s = 'aTotal_Bitch.d2s'; #file to get/give information about. # open(my ${f}, '<', $D2s) or die $!; my $tmp; my $szContents = ''; { local $/; $szContents = <$f>; } #Name { ($tmp) = unpack('Z*', substr($szContents, 20, 16)); print qq{Name: $tmp\n}; } #Character title (Slayer, Champion, Patriarch/Matriarch) { ($tmp) = unpack('C', substr($szContents, 37, 1)); print "Title information: ", sprintf("%08b\n", $tmp); if($tmp <= 3){ print "(Character has no title.)\n"; } elsif($tmp <= 8){ print "Character title: Slayer\n"; } elsif($tmp <= 13){ print "Character title: Champion\n"; } elsif($tmp == 15){ print "Character title: Patriarch/Matriarch\n"; } else{ print "(Character has strange title information.)\n"; } } #Type of character (Sorc, Ama, druid, assassin, etc) { ($tmp) = unpack('C', substr($szContents, 40, 1)); if($tmp == 0){print "Type: Amazon\n"} elsif($tmp == 1){print "Type: Sorceress\n"} elsif($tmp == 2){print "Type: Necromancer\n"} elsif($tmp == 3){print "Type: Paladin\n"} elsif($tmp == 4){print "Type: Barbarian\n"} elsif($tmp == 5){print "Type: Druid\n"} elsif($tmp == 6){print "Type: Assassin\n"} } #Character level { ($tmp) = unpack('C', substr($szContents, 43, 1)); print "Level: $tmp\n"; } #Current spawning town location per difficulty { my %difficulty = ( 168 => 'Normal', 169 => 'Nightmare', 170 => 'Hell' ); for my $i(168 .. 170){ ($tmp) = unpack('C', substr($szContents, $i, 1)); my $active = ($tmp & 0x80) ? 1 : 0; my $town = $tmp & 0x07; if($active){ if($town == 0){print "$difficulty{$i} town: Act 1\n";} elsif($town == 1){print "$difficulty{$i} town: Act 2\n";} elsif($town == 2){print "$difficulty{$i} town: Act 3\n";} elsif($town == 3){print "$difficulty{$i} town: Act 4\n";} elsif($town == 4){print "$difficulty{$i} town: Act 5\n";} } } } #Waypoint information { #($tmp) = unpack('b88888') ($tmp) = unpack('b40', substr($szContents, 643, 5)); print "Normal waypoints: ", $tmp, "\n"; ($tmp) = unpack('b40', substr($szContents, 667, 5)); print "Nightmare waypoints: ", $tmp, "\n"; ($tmp) = unpack('b40', substr($szContents, 691, 5)); print "Hell waypoints: ", $tmp, "\n"; } =pod Quests: Normal: 345 (length 96) 345,346 Warriv 347-358 Act 1 359,360 act I -> act II travel 361,362 Jerhyn intro 262-374 Act II 375,376 act II -> act III travel 377,378 Hralti intro 379-390 Act III 391,392 act III -> act IV travel 393,394 act IV intro 395-400 Act IV 401,402 act IV -> act V 403-408 unknown 409,410 talk to cain after killing diablo 411-414 unknown 415-426 Act V 427-440 unknown Nightmare: 441 (length 96) 441,442 Nightmare warriv 443-454 Act I Hell: 537 (length 96) End: 633 =cut =pod Misc Data =cut my $skill_loc = index($szContents, 'if', 767); #'gf' @ 765 if($skill_loc == -1){ die ''; } my ($strength, $energy, $dexterity, $vitality, $statpts, $newskills, $hitpoints, $maxhp, $mana, $maxmana, $stamina, $maxstamina, $level, $experience, $gold, $goldbank) = split(//, '0' x 16); { sub bindec{ my $binary_stream = shift; return oct('0b' . $binary_stream); } #get binary string of pearls. my $binary_stream = ''; for my $byte_loc (reverse(767 .. $skill_loc - 1)){ #b8 is reversed. #B8 is 'C' my ($byte) = unpack('B8', substr($szContents, $byte_loc, 1)); $binary_stream = $binary_stream . $byte; undef $byte; } #XXX strength is 11 for my PlugY mod!!! my @siz_info = qw{ strength: 10 energy: 10 dexterity: 10 vitality: 10 statpts: 10 newskills: 8 hitpoints: 21 maxhp: 21 mana: 21 maxmana: 21 stamina: 21 maxstamina: 21 level: 7 experience: 32 gold: 25 goldbank: 25 }; my ($strength_siz, $energy_siz, $dexterity_siz, $vitality_siz, $statpts_siz, $newskills_siz, $hitpoints_siz, $maxhp_siz, $mana_siz, $maxmana_siz, $stamina_siz, $maxstamina_siz, $level_siz, $experience_siz, $gold_siz, $goldbank_siz) = grep { /^[0-9]+$/ } @siz_info; undef @siz_info; my $binary_stream_location = 0; my $id_offset = 9; while(1){ $binary_stream_location -= $id_offset; my $id = bindec(substr($binary_stream, $binary_stream_location, 9)); #print "ID Found: ", $id, "\n"; if($id == 0){ $binary_stream_location -= $strength_siz; $strength = bindec(substr($binary_stream, $binary_stream_location, $strength_siz)); } elsif($id == 1){ $binary_stream_location -= $energy_siz; $energy = bindec(substr($binary_stream, $binary_stream_location, $energy_siz)); } elsif($id == 2){ $binary_stream_location -= $dexterity_siz; $dexterity = bindec(substr($binary_stream, $binary_stream_location, $dexterity_siz)); } elsif($id == 3){ $binary_stream_location -= $vitality_siz; $vitality = bindec(substr($binary_stream, $binary_stream_location, $vitality_siz)); } elsif($id == 4){ $binary_stream_location -= $statpts_siz; $statpts = bindec(substr($binary_stream, $binary_stream_location, $statpts_siz)); } elsif($id == 5){ $binary_stream_location -= $newskills_siz; $newskills = bindec(substr($binary_stream, $binary_stream_location, $newskills_siz)); } elsif($id == 6){ $binary_stream_location -= $hitpoints_siz; $hitpoints = bindec(substr($binary_stream, $binary_stream_location, $hitpoints_siz)) >> 8; } elsif($id == 7){ $binary_stream_location -= $maxhp_siz; $maxhp = bindec(substr($binary_stream, $binary_stream_location, $maxhp_siz)) >> 8; } elsif($id == 8){ $binary_stream_location -= $mana_siz; $mana = bindec(substr($binary_stream, $binary_stream_location, $mana_siz)) >> 8; } elsif($id == 9){ $binary_stream_location -= $maxmana_siz; $maxmana = bindec(substr($binary_stream, $binary_stream_location, $maxmana_siz)) >> 8; } elsif($id == 10){ $binary_stream_location -= $stamina_siz; $stamina = bindec(substr($binary_stream, $binary_stream_location, $stamina_siz)) >> 8; } elsif($id == 11){ $binary_stream_location -= $maxstamina_siz; $maxstamina = bindec(substr($binary_stream, $binary_stream_location, $maxstamina_siz)) >> 8; } elsif($id == 12){ $binary_stream_location -= $level_siz; $level = bindec(substr($binary_stream, $binary_stream_location, $level_siz)); } elsif($id == 13){ $binary_stream_location -= $experience_siz; $experience = bindec(substr($binary_stream, $binary_stream_location, $experience_siz)); } elsif($id == 14){ $binary_stream_location -= $gold_siz; $gold = bindec(substr($binary_stream, $binary_stream_location, $gold_siz)); } elsif($id == 15){ $binary_stream_location -= $goldbank_siz; $goldbank = bindec(substr($binary_stream, $binary_stream_location, $goldbank_siz)); last; } else{ last; } undef $id; } undef $binary_stream_location; undef $id_offset; } print <