def load_from_file(self, f): self.version, self.style_number, self.sample, _, self.route_size, \ self.object_pos_size, self.column_size, self.block_size, \ self.nav_data_size = unpack_file('IBBHIIIII', f) self._read_grid(f) self._read_block_table(f, self.block_size) self._read_object_positions(f, self.object_pos_size) self._read_navigation_data(f, self.nav_data_size) self.style = Style() self.style.load_from_file(open('data/STYLE00%d.G24' % self.style_number)) # The lid attribute in a block stores a relative offset into the lid tiles. # By making it absolute, it becomes easier to work with on the client. lid_tile_offset = self.style.side_size / (64 * 64) for i in range(len(self.block_table)): block = self.block_table[i] if block.lid: block = block._replace(lid=block.lid + lid_tile_offset) self.block_table[i] = block
count = s.sprite_numbers.object for index, sprite in enumerate(s.sprites.sprites[sprite_offset:sprite_offset+count]): x = sprite.x y = sprite.page * 256 + sprite.y sprite_img = color.crop((x, y, x + sprite.width, y + sprite.height)).copy() sprite_img.save('/tmp/object/%03d.png' % index, 'png') def extract_ped_sprites(s, color): sprite_offset = s.sprite_offset['ped'] count = s.sprite_numbers.ped for index, sprite in enumerate(s.sprites.sprites[sprite_offset:sprite_offset+count]): x = sprite.x y = sprite.page * 256 + sprite.y sprite_img = color.crop((x, y, x + sprite.width, y + sprite.height)).copy() sprite_img.save('/tmp/ped/%03d.png' % index, 'png') if __name__ == '__main__': s = Style() s.load_from_file(open('gtadata/STYLE001.G24', 'r')) color = s.sprites.colorize() extract_car_sprites(s, color) extract_object_sprites(s, color) extract_ped_sprites(s, color)
class Map(object): def load_from_file(self, f): self.version, self.style_number, self.sample, _, self.route_size, \ self.object_pos_size, self.column_size, self.block_size, \ self.nav_data_size = unpack_file('IBBHIIIII', f) self._read_grid(f) self._read_block_table(f, self.block_size) self._read_object_positions(f, self.object_pos_size) self._read_navigation_data(f, self.nav_data_size) self.style = Style() self.style.load_from_file(open('data/STYLE00%d.G24' % self.style_number)) # The lid attribute in a block stores a relative offset into the lid tiles. # By making it absolute, it becomes easier to work with on the client. lid_tile_offset = self.style.side_size / (64 * 64) for i in range(len(self.block_table)): block = self.block_table[i] if block.lid: block = block._replace(lid=block.lid + lid_tile_offset) self.block_table[i] = block def _read_grid(self, f): grid_columns = unpack_file('I' * 256 * 256, f) column_iter = iter(unpack_file('H' * (self.column_size / 2), f)) cube_stack_table = {} pos = 0 try: while True: d = column_iter.next() cubes = 6 - d cube_stack_table[pos] = [column_iter.next() for i in range(cubes)] pos += 2 * (1 + cubes) except StopIteration: pass self.grid = [] for column in grid_columns: stack = cube_stack_table[column] self.grid.append(stack) def _read_block_table(self, f, size): block_struct = 'HBBBBBB' self.block_table = [] for i in range(size / calcsize(block_struct)): block = Block(*unpack_file(block_struct, f)) self.block_table.append(block) def _read_navigation_data(self, f, size): nav_struct = 'BBBBB30s' self.districts = [] f.seek(-size, os.SEEK_END) for i in range(size / calcsize(nav_struct)): data = unpack_file(nav_struct, f) self.districts.append(District(*data)) def _read_object_positions(self, f, size): object_pos_struct = 'HHHBBHHH' block_size = calcsize(object_pos_struct) self.object_pos = [] for i in range(size / block_size): data = unpack_file(object_pos_struct, f) self.object_pos.append(ObjectPos(*data)) def export(self): serialize('_build/map.json', self.grid) serialize('_build/blocks.json', [x.data() for x in self.block_table]) serialize('_build/object_pos.json', [(o.x, o.y, o.z, o.type, o.remap >= 128, o.rotation / 1024.0 * 360) for o in self.object_pos]) self.style.export()