def store_generated_objects(self): snci_section = self.gas_dir.get_or_create_subdir( 'index').get_or_create_gas_file( 'streamer_node_content_index').get_gas().get_or_create_section( 'streamer_node_content_index') all_ioids = [ Hex.parse('0x' + str(attr.value)[5:]) for attr in snci_section.get_attrs() ] # all internal object ids (internal meaning without scid range) streamer_node_content_index = {} object_sections = [] last_ioid = 0 for go_data in self.generated_objects_non_interactive: assert isinstance(go_data, GameObjectData) assert go_data.scid is None ioid = last_ioid + 1 while ioid in all_ioids: # find free oid ioid += 1 last_ioid = ioid go_data.scid = Hex.parse('0x{:03X}{:05X}'.format( self.data.scid_range, ioid)) object_sections.append(go_data.make_gas()) node_guid = go_data.placement.position.node_guid if node_guid not in streamer_node_content_index: streamer_node_content_index[node_guid] = [] streamer_node_content_index[node_guid].append(go_data.scid) objects_dir = self.gas_dir.get_or_create_subdir('objects') objects_dir.get_or_create_gas_file( 'non_interactive').get_gas().items.extend(object_sections) snci_attrs = [] for node_guid, oids in streamer_node_content_index.items(): snci_attrs.extend([Attribute(node_guid, oid) for oid in oids]) snci_section.items.extend(snci_attrs)
def edit_region_mesh_range(region: Region, new_mesh_range: Hex): new_mesh_range_str = str(new_mesh_range) assert new_mesh_range_str.startswith( '0x00000') # only last 3 digits may be used old_mesh_range: Hex = region.get_data().mesh_range if new_mesh_range == old_mesh_range: print('no change in mesh range') return print('edit mesh range: ' + str(old_mesh_range) + ' -> ' + str(new_mesh_range)) region.get_data().mesh_range = new_mesh_range region.save() new_mesh_prefix = new_mesh_range_str[7:] assert len(new_mesh_prefix) == 3, new_mesh_prefix # replace & collect in node_mesh_index node_mesh_index_file = region.gas_dir.get_subdir('index').get_gas_file( 'node_mesh_index') mesh_replacements = list() for node_mesh_attr in node_mesh_index_file.get_gas().get_section( 'node_mesh_index').items: assert isinstance(node_mesh_attr, Attribute) old_hex = Hex.parse(node_mesh_attr.name) new_hex = Hex.parse('0x' + new_mesh_prefix + node_mesh_attr.name[5:]) mesh_replacements.append((old_hex, new_hex)) node_mesh_attr.name = new_hex.to_str_lower() node_mesh_index_file.save() # replace mesh references in terrain nodes replace_hexes_in_file( region.gas_dir.get_subdir('terrain_nodes').get_gas_file('nodes').path, mesh_replacements)
def store_terrain(self): # index mesh_index = self.terrain.get_mesh_index() mesh_index = { Hex.parse('0x{:03X}{:05X}'.format(self.data.mesh_range, mesh_guid)): mesh_name for mesh_guid, mesh_name in mesh_index.items() } self.gas_dir.create_subdir( 'index', { 'node_mesh_index': Gas([ Section('node_mesh_index', [ Attribute(str(mesh_guid), mesh_name) for mesh_guid, mesh_name in mesh_index.items() ]) ]), 'streamer_node_index': Gas([ Section('streamer_node_index', [ Attribute('*', node.guid) for node in self.terrain.nodes ]) ]) }) # terrain_nodes nodes_gas = NodesGas() nodes_gas.ambient_color = self.terrain.ambient_light.terrain_color nodes_gas.ambient_intensity = self.terrain.ambient_light.terrain_intensity nodes_gas.object_ambient_color = self.terrain.ambient_light.object_color nodes_gas.object_ambient_intensity = self.terrain.ambient_light.object_intensity nodes_gas.actor_ambient_color = self.terrain.ambient_light.actor_color nodes_gas.actor_ambient_intensity = self.terrain.ambient_light.actor_intensity nodes_gas.targetnode = self.terrain.target_node.guid snodes = list() for node in self.terrain.nodes: mesh_guid = Terrain.mesh_index_lookup[node.mesh_name] mesh_guid = Hex.parse('0x{:03X}{:05X}'.format( self.data.mesh_range, mesh_guid)) doors = [ Door(door_id, far_node.guid, far_door) for door_id, (far_node, far_door) in node.doors.items() ] nodesection = Hex( node.section if node.section != -1 else 0xffffffff) nodelevel = Hex(node.section if node.section != -1 else 0xffffffff) nodeobject = Hex( node.section if node.section != -1 else 0xffffffff) snode = SNode(node.guid, mesh_guid, node.texture_set, True, False, False, True, nodesection, nodelevel, nodeobject, doors) snodes.append(snode) nodes_gas.nodes = snodes self.gas_dir.create_subdir('terrain_nodes', {'nodes': nodes_gas.write_gas()})
def main(argv): path = argv[0] hexes = [(Hex.parse(hex_hex.split(',')[0]), Hex.parse(hex_hex.split(',')[1])) for hex_hex in argv[1].split(';')] if os.path.isdir(path): replace_hexes_in_dir(path, hexes) elif os.path.isfile(path): replace_hexes_in_file(path, hexes) else: assert False, f'{path} does not exist' return 0
def get_stitch_id(rx: int, rz: int, hv: bool, xz: int): assert 0 <= rx < 100 assert 0 <= rz < 100 assert 0 <= xz < 0x1000 rx = str(rx).zfill(2) rz = str(rz).zfill(2) hv = '0' if hv else '1' stitch_range = f'0x{rx}{rz}{hv}000' return Hex.parse(stitch_range) + xz
def edit_region_ids(map_name, region_name, mesh_range=None, scid_range=None, guid=None): bits = Bits() assert map_name in bits.maps, map_name _map = bits.maps[map_name] regions = _map.get_regions() assert region_name in regions, region_name region = regions[region_name] if mesh_range is not None: edit_region_mesh_range(region, Hex.parse(mesh_range)) region.gas_dir.clear_cache() region.load_data() if scid_range is not None: edit_region_scid_range(region, Hex.parse(scid_range)) region.gas_dir.clear_cache() region.load_data() if guid is not None: edit_region_guid(region, Hex.parse(guid))
def convert_region(region: Region, nmg: NodeMeshGuids): index_dir = region.gas_dir.get_subdir('index') if index_dir.has_gas_file('node_mesh_index'): return nodes_file = region.gas_dir.get_subdir('terrain_nodes').get_gas_file( 'nodes') node_gas = nodes_file.get_gas() nodes_section: Section = node_gas.items[0] node_sections = nodes_section.get_sections() mesh_guid_attrs = [ns.get_attr('mesh_guid') for ns in node_sections] node_mesh_index = {} node_mesh_guids = nmg.get_node_mesh_guids() for mesh_guid_attr in mesh_guid_attrs: mesh_guid = mesh_guid_attr.value.to_str_lower() assert mesh_guid in node_mesh_guids, str( mesh_guid) + ' is not in ' + str(node_mesh_guids) if mesh_guid not in node_mesh_index: node_mesh_index[mesh_guid] = Hex(len(node_mesh_index) + 1) mesh_id = node_mesh_index[mesh_guid] mesh_guid_attr.value = mesh_id nodes_file.save() node_mesh_index_attrs = [ Attribute(mesh_id, node_mesh_guids[mesh_guid]) for mesh_guid, mesh_id in node_mesh_index.items() ] index_dir.create_gas_file( 'node_mesh_index', Gas([Section('node_mesh_index', node_mesh_index_attrs)])).save() region_data = region.get_data() if region_data.mesh_range == 0: if 0 < region_data.scid_range < Hex.parse('0x00001000'): region_data.mesh_range = region_data.scid_range elif 0 < region_data.id < Hex.parse('0x00001000'): region_data.mesh_range = region_data.id if region_data.mesh_range != 0: region.save() print(f'Converted region {region.get_name()} to NMI')
def edit_region_scid_range(region: Region, new_scid_range: Hex): new_scid_range_str = str(new_scid_range) assert new_scid_range_str.startswith( '0x00000') # only last 3 digits may be used old_scid_range: Hex = region.get_data().scid_range if new_scid_range == old_scid_range: print('no change in scid range') return # check that no region already uses the new scid range other_regions: list[Region] = [ r for r in region.map.get_regions().values() if r.get_name() != region.get_name() ] other_regions_using_new_scid_range = [ r for r in other_regions if r.get_data().scid_range == new_scid_range ] assert len( other_regions_using_new_scid_range ) == 0, f'new scid range is already used by {[r.get_name() for r in other_regions_using_new_scid_range]}' # check that target region is the only one with the old scid range other_regions_using_old_scid_range = [ r for r in other_regions if r.get_data().scid_range == old_scid_range ] assert len( other_regions_using_old_scid_range ) == 0, f'old scid range is also used by {[r.get_name() for r in other_regions_using_old_scid_range]}' print('edit scid range: ' + str(old_scid_range) + ' -> ' + new_scid_range_str) region.get_data().scid_range = new_scid_range region.save() new_scid_prefix = new_scid_range_str[7:] assert len(new_scid_prefix) == 3, new_scid_prefix old_scids = region.get_scids() scid_replacements = [ (old_scid, Hex.parse('0x' + new_scid_prefix + str(old_scid)[5:])) for old_scid in old_scids ] # replace in all files of target region replace_hexes_in_dir(region.gas_dir.path, scid_replacements) # replace in referencing files of all regions replace_hexes_in_dir(region.map.gas_dir.path, scid_replacements, 'elevator.gas') replace_hexes_in_dir(region.map.gas_dir.path, scid_replacements, 'interactive.gas') replace_hexes_in_dir(region.map.gas_dir.path, scid_replacements, 'special.gas')
def load_terrain(self): node_mesh_index_file = self.gas_dir.get_subdir('index').get_gas_file( 'node_mesh_index') nmi = { Hex.parse(attr.name): attr.value for attr in node_mesh_index_file.get_gas().get_section( 'node_mesh_index').get_attrs() } nodes_gas_file = self.gas_dir.get_subdir('terrain_nodes').get_gas_file( 'nodes') nodes_gas = NodesGas.load(nodes_gas_file) # ambient light ambient_light = AmbientLight(nodes_gas.ambient_color, nodes_gas.ambient_intensity, nodes_gas.object_ambient_color, nodes_gas.object_ambient_intensity, nodes_gas.actor_ambient_color, nodes_gas.actor_ambient_intensity) # nodes nodes = list() nodes_dict = dict() for snode in nodes_gas.nodes: assert snode.mesh_guid in nmi, 'unknown mesh_guid: ' + str( snode.mesh_guid) mesh_name = nmi[snode.mesh_guid] node = TerrainNode(snode.guid, mesh_name, snode.texsetabbr) node.section = snode.nodesection if snode.nodesection != 0xffffffff else -1 node.level = snode.nodelevel if snode.nodelevel != 0xffffffff else -1 node.object = snode.nodeobject if snode.nodeobject != 0xffffffff else -1 nodes_dict[snode.guid] = node nodes.append(node) for snode in nodes_gas.nodes: node = nodes_dict[snode.guid] for door in snode.doors: far_node = nodes_dict[door.farguid] node.doors[door.id] = (far_node, door.fardoor) target_node = nodes_dict[nodes_gas.targetnode] terrain = Terrain() terrain.nodes = nodes terrain.target_node = target_node terrain.ambient_light = ambient_light self.terrain = terrain