def get_creatable_game_entity(line: GenieGameEntityGroup) -> None: """ Creates the CreatableGameEntity object for a unit/building line. In comparison to the AoC version, ths replaces some unit class IDs and removes garrison placement modes. :param line: Unit/Building line. :type line: ...dataformat.converter_object.ConverterObjectGroup """ if isinstance(line, GenieVillagerGroup): current_unit = line.variants[0].line[0] else: current_unit = line.line[0] current_unit_id = line.get_head_unit_id() dataset = line.data name_lookup_dict = internal_name_lookups.get_entity_lookups( dataset.game_version) game_entity_name = name_lookup_dict[current_unit_id][0] obj_ref = f"{game_entity_name}.CreatableGameEntity" obj_name = f"{game_entity_name}Creatable" creatable_raw_api_object = RawAPIObject(obj_ref, obj_name, dataset.nyan_api_objects) creatable_raw_api_object.add_raw_parent( "engine.util.create.CreatableGameEntity") # Get train location of line train_location_id = line.get_train_location_id() if isinstance(line, GenieBuildingLineGroup): train_location = dataset.unit_lines[train_location_id] train_location_name = name_lookup_dict[train_location_id][0] else: train_location = dataset.building_lines[train_location_id] train_location_name = name_lookup_dict[train_location_id][0] # Add object to the train location's Create ability creatable_location = ForwardRef(train_location, f"{train_location_name}.Create") creatable_raw_api_object.set_location(creatable_location) # Game Entity game_entity_forward_ref = ForwardRef(line, game_entity_name) creatable_raw_api_object.add_raw_member( "game_entity", game_entity_forward_ref, "engine.util.create.CreatableGameEntity") # TODO: Variants variants_set = [] creatable_raw_api_object.add_raw_member( "variants", variants_set, "engine.util.create.CreatableGameEntity") # Cost (construction) cost_name = f"{game_entity_name}.CreatableGameEntity.{game_entity_name}Cost" cost_raw_api_object = RawAPIObject(cost_name, f"{game_entity_name}Cost", dataset.nyan_api_objects) cost_raw_api_object.add_raw_parent( "engine.util.cost.type.ResourceCost") creatable_forward_ref = ForwardRef(line, obj_ref) cost_raw_api_object.set_location(creatable_forward_ref) payment_mode = dataset.nyan_api_objects[ "engine.util.payment_mode.type.Advance"] cost_raw_api_object.add_raw_member("payment_mode", payment_mode, "engine.util.cost.Cost") if isinstance(line, GenieBuildingLineGroup) or line.get_class_id() in ( 2, 13, 20, 21, 22): # Cost (repair) for buildings cost_repair_name = (f"{game_entity_name}.CreatableGameEntity." f"{game_entity_name}RepairCost") cost_repair_raw_api_object = RawAPIObject( cost_repair_name, f"{game_entity_name}RepairCost", dataset.nyan_api_objects) cost_repair_raw_api_object.add_raw_parent( "engine.util.cost.type.ResourceCost") creatable_forward_ref = ForwardRef(line, obj_ref) cost_repair_raw_api_object.set_location(creatable_forward_ref) payment_repair_mode = dataset.nyan_api_objects[ "engine.util.payment_mode.type.Adaptive"] cost_repair_raw_api_object.add_raw_member("payment_mode", payment_repair_mode, "engine.util.cost.Cost") line.add_raw_api_object(cost_repair_raw_api_object) cost_amounts = [] cost_repair_amounts = [] for resource_amount in current_unit["resource_cost"].value: resource_id = resource_amount["type_id"].value resource = None resource_name = "" if resource_id == -1: # Not a valid resource continue if resource_id == 0: resource = dataset.pregen_nyan_objects[ "util.resource.types.Food"].get_nyan_object() resource_name = "Food" elif resource_id == 1: resource = dataset.pregen_nyan_objects[ "util.resource.types.Wood"].get_nyan_object() resource_name = "Wood" elif resource_id == 2: resource = dataset.pregen_nyan_objects[ "util.resource.types.Stone"].get_nyan_object() resource_name = "Stone" elif resource_id == 3: resource = dataset.pregen_nyan_objects[ "util.resource.types.Gold"].get_nyan_object() resource_name = "Gold" else: # Other resource ids are handled differently continue # Skip resources that are only expected to be there if not resource_amount["enabled"].value: continue amount = resource_amount["amount"].value cost_amount_name = f"{cost_name}.{resource_name}Amount" cost_amount = RawAPIObject(cost_amount_name, f"{resource_name}Amount", dataset.nyan_api_objects) cost_amount.add_raw_parent("engine.util.resource.ResourceAmount") cost_forward_ref = ForwardRef(line, cost_name) cost_amount.set_location(cost_forward_ref) cost_amount.add_raw_member("type", resource, "engine.util.resource.ResourceAmount") cost_amount.add_raw_member("amount", amount, "engine.util.resource.ResourceAmount") cost_amount_forward_ref = ForwardRef(line, cost_amount_name) cost_amounts.append(cost_amount_forward_ref) line.add_raw_api_object(cost_amount) if isinstance(line, GenieBuildingLineGroup) or\ line.get_class_id() in (2, 13, 20, 21, 22): # Cost for repairing = half of the construction cost cost_amount_name = f"{cost_repair_name}.{resource_name}Amount" cost_amount = RawAPIObject(cost_amount_name, f"{resource_name}Amount", dataset.nyan_api_objects) cost_amount.add_raw_parent( "engine.util.resource.ResourceAmount") cost_forward_ref = ForwardRef(line, cost_repair_name) cost_amount.set_location(cost_forward_ref) cost_amount.add_raw_member( "type", resource, "engine.util.resource.ResourceAmount") cost_amount.add_raw_member( "amount", amount / 2, "engine.util.resource.ResourceAmount") cost_amount_forward_ref = ForwardRef(line, cost_amount_name) cost_repair_amounts.append(cost_amount_forward_ref) line.add_raw_api_object(cost_amount) cost_raw_api_object.add_raw_member( "amount", cost_amounts, "engine.util.cost.type.ResourceCost") if isinstance(line, GenieBuildingLineGroup) or line.get_class_id() in ( 2, 13, 20, 21, 22): cost_repair_raw_api_object.add_raw_member( "amount", cost_repair_amounts, "engine.util.cost.type.ResourceCost") cost_forward_ref = ForwardRef(line, cost_name) creatable_raw_api_object.add_raw_member( "cost", cost_forward_ref, "engine.util.create.CreatableGameEntity") # Creation time if isinstance(line, GenieUnitLineGroup): creation_time = current_unit["creation_time"].value else: # Buildings are created immediately creation_time = 0 creatable_raw_api_object.add_raw_member( "creation_time", creation_time, "engine.util.create.CreatableGameEntity") # Creation sound creation_sound_id = current_unit["train_sound_id"].value # Create sound object obj_name = f"{game_entity_name}.CreatableGameEntity.Sound" sound_raw_api_object = RawAPIObject(obj_name, "CreationSound", dataset.nyan_api_objects) sound_raw_api_object.add_raw_parent("engine.util.sound.Sound") sound_location = ForwardRef(line, obj_ref) sound_raw_api_object.set_location(sound_location) # Search for the sound if it exists creation_sounds = [] if creation_sound_id > -1: # Creation sound should be civ agnostic genie_sound = dataset.genie_sounds[creation_sound_id] file_id = genie_sound.get_sounds(civ_id=-1)[0] if file_id in dataset.combined_sounds: creation_sound = dataset.combined_sounds[file_id] creation_sound.add_reference(sound_raw_api_object) else: creation_sound = CombinedSound( creation_sound_id, file_id, f"creation_sound_{creation_sound_id}", dataset) dataset.combined_sounds.update({file_id: creation_sound}) creation_sound.add_reference(sound_raw_api_object) creation_sounds.append(creation_sound) sound_raw_api_object.add_raw_member("play_delay", 0, "engine.util.sound.Sound") sound_raw_api_object.add_raw_member("sounds", creation_sounds, "engine.util.sound.Sound") sound_forward_ref = ForwardRef(line, obj_name) creatable_raw_api_object.add_raw_member( "creation_sounds", [sound_forward_ref], "engine.util.create.CreatableGameEntity") line.add_raw_api_object(sound_raw_api_object) # Condition unlock_conditions = [] enabling_research_id = line.get_enabling_research_id() if enabling_research_id > -1: unlock_conditions.extend( AoCAuxiliarySubprocessor.get_condition(line, obj_ref, enabling_research_id)) creatable_raw_api_object.add_raw_member( "condition", unlock_conditions, "engine.util.create.CreatableGameEntity") # Placement modes placement_modes = [] if isinstance(line, GenieBuildingLineGroup): # Buildings are placed on the map # Place mode obj_name = f"{game_entity_name}.CreatableGameEntity.Place" place_raw_api_object = RawAPIObject(obj_name, "Place", dataset.nyan_api_objects) place_raw_api_object.add_raw_parent( "engine.util.placement_mode.type.Place") place_location = ForwardRef( line, f"{game_entity_name}.CreatableGameEntity") place_raw_api_object.set_location(place_location) # Tile snap distance (uses 1.0 for grid placement) place_raw_api_object.add_raw_member( "tile_snap_distance", 1.0, "engine.util.placement_mode.type.Place") # Clearance size clearance_size_x = current_unit["clearance_size_x"].value clearance_size_y = current_unit["clearance_size_y"].value place_raw_api_object.add_raw_member( "clearance_size_x", clearance_size_x, "engine.util.placement_mode.type.Place") place_raw_api_object.add_raw_member( "clearance_size_y", clearance_size_y, "engine.util.placement_mode.type.Place") # Allow rotation place_raw_api_object.add_raw_member( "allow_rotation", True, "engine.util.placement_mode.type.Place") # Max elevation difference elevation_mode = current_unit["elevation_mode"].value if elevation_mode == 2: max_elevation_difference = 0 elif elevation_mode == 3: max_elevation_difference = 1 else: max_elevation_difference = MemberSpecialValue.NYAN_INF place_raw_api_object.add_raw_member( "max_elevation_difference", max_elevation_difference, "engine.util.placement_mode.type.Place") line.add_raw_api_object(place_raw_api_object) place_forward_ref = ForwardRef(line, obj_name) placement_modes.append(place_forward_ref) else: placement_modes.append( dataset. nyan_api_objects["engine.util.placement_mode.type.Eject"]) creatable_raw_api_object.add_raw_member( "placement_modes", placement_modes, "engine.util.create.CreatableGameEntity") line.add_raw_api_object(creatable_raw_api_object) line.add_raw_api_object(cost_raw_api_object)
def get_creatable_game_entity(line: GenieGameEntityGroup) -> None: """ Creates the CreatableGameEntity object for a unit/building line. :param line: Unit/Building line. :type line: ...dataformat.converter_object.ConverterObjectGroup """ if isinstance(line, GenieVillagerGroup): current_unit = line.variants[0].line[0] else: current_unit = line.line[0] current_unit_id = line.get_head_unit_id() dataset = line.data name_lookup_dict = internal_name_lookups.get_entity_lookups( dataset.game_version) civ_lookup_dict = internal_name_lookups.get_civ_lookups( dataset.game_version) game_entity_name = name_lookup_dict[current_unit_id][0] obj_ref = f"{game_entity_name}.CreatableGameEntity" obj_name = f"{game_entity_name}Creatable" creatable_raw_api_object = RawAPIObject(obj_ref, obj_name, dataset.nyan_api_objects) creatable_raw_api_object.add_raw_parent( "engine.util.create.CreatableGameEntity") # Get train location of line train_location_id = line.get_train_location_id() if isinstance(line, GenieBuildingLineGroup): train_location = dataset.unit_lines[train_location_id] train_location_name = name_lookup_dict[train_location_id][0] else: train_location = dataset.building_lines[train_location_id] train_location_name = name_lookup_dict[train_location_id][0] # Location of the object depends on whether it'a a unique unit or a normal unit if line.is_unique(): # Add object to the Civ object enabling_research_id = line.get_enabling_research_id() enabling_research = dataset.genie_techs[enabling_research_id] enabling_civ_id = enabling_research["civilization_id"].get_value() civ = dataset.civ_groups[enabling_civ_id] civ_name = civ_lookup_dict[enabling_civ_id][0] creatable_location = ForwardRef(civ, civ_name) else: # Add object to the train location's Create ability creatable_location = ForwardRef(train_location, f"{train_location_name}.Create") creatable_raw_api_object.set_location(creatable_location) # Game Entity game_entity_forward_ref = ForwardRef(line, game_entity_name) creatable_raw_api_object.add_raw_member( "game_entity", game_entity_forward_ref, "engine.util.create.CreatableGameEntity") # TODO: Variants variants_set = [] creatable_raw_api_object.add_raw_member( "variants", variants_set, "engine.util.create.CreatableGameEntity") # Cost (construction) cost_name = f"{game_entity_name}.CreatableGameEntity.{game_entity_name}Cost" cost_raw_api_object = RawAPIObject(cost_name, f"{game_entity_name}Cost", dataset.nyan_api_objects) cost_raw_api_object.add_raw_parent( "engine.util.cost.type.ResourceCost") creatable_forward_ref = ForwardRef(line, obj_ref) cost_raw_api_object.set_location(creatable_forward_ref) payment_mode = dataset.nyan_api_objects[ "engine.util.payment_mode.type.Advance"] cost_raw_api_object.add_raw_member("payment_mode", payment_mode, "engine.util.cost.Cost") if line.is_repairable(): # Cost (repair) for buildings cost_repair_name = "%s.CreatableGameEntity.%sRepairCost" % ( game_entity_name, game_entity_name) cost_repair_raw_api_object = RawAPIObject( cost_repair_name, f"{game_entity_name}RepairCost", dataset.nyan_api_objects) cost_repair_raw_api_object.add_raw_parent( "engine.util.cost.type.ResourceCost") creatable_forward_ref = ForwardRef(line, obj_ref) cost_repair_raw_api_object.set_location(creatable_forward_ref) payment_repair_mode = dataset.nyan_api_objects[ "engine.util.payment_mode.type.Adaptive"] cost_repair_raw_api_object.add_raw_member("payment_mode", payment_repair_mode, "engine.util.cost.Cost") line.add_raw_api_object(cost_repair_raw_api_object) cost_amounts = [] cost_repair_amounts = [] for resource_amount in current_unit["resource_cost"].get_value(): resource_id = resource_amount["type_id"].get_value() resource = None resource_name = "" if resource_id == -1: # Not a valid resource continue if resource_id == 0: resource = dataset.pregen_nyan_objects[ "util.resource.types.Food"].get_nyan_object() resource_name = "Food" elif resource_id == 1: resource = dataset.pregen_nyan_objects[ "util.resource.types.Carbon"].get_nyan_object() resource_name = "Carbon" elif resource_id == 2: resource = dataset.pregen_nyan_objects[ "util.resource.types.Ore"].get_nyan_object() resource_name = "Ore" elif resource_id == 3: resource = dataset.pregen_nyan_objects[ "util.resource.types.Nova"].get_nyan_object() resource_name = "Nova" else: # Other resource ids are handled differently continue # Skip resources that are only expected to be there if not resource_amount["enabled"].get_value(): continue amount = resource_amount["amount"].get_value() cost_amount_name = f"{cost_name}.{resource_name}Amount" cost_amount = RawAPIObject(cost_amount_name, f"{resource_name}Amount", dataset.nyan_api_objects) cost_amount.add_raw_parent("engine.util.resource.ResourceAmount") cost_forward_ref = ForwardRef(line, cost_name) cost_amount.set_location(cost_forward_ref) cost_amount.add_raw_member("type", resource, "engine.util.resource.ResourceAmount") cost_amount.add_raw_member("amount", amount, "engine.util.resource.ResourceAmount") cost_amount_forward_ref = ForwardRef(line, cost_amount_name) cost_amounts.append(cost_amount_forward_ref) line.add_raw_api_object(cost_amount) if line.is_repairable(): # Cost for repairing = half of the construction cost cost_amount_name = f"{cost_repair_name}.{resource_name}Amount" cost_amount = RawAPIObject(cost_amount_name, f"{resource_name}Amount", dataset.nyan_api_objects) cost_amount.add_raw_parent( "engine.util.resource.ResourceAmount") cost_forward_ref = ForwardRef(line, cost_repair_name) cost_amount.set_location(cost_forward_ref) cost_amount.add_raw_member( "type", resource, "engine.util.resource.ResourceAmount") cost_amount.add_raw_member( "amount", amount / 2, "engine.util.resource.ResourceAmount") cost_amount_forward_ref = ForwardRef(line, cost_amount_name) cost_repair_amounts.append(cost_amount_forward_ref) line.add_raw_api_object(cost_amount) cost_raw_api_object.add_raw_member( "amount", cost_amounts, "engine.util.cost.type.ResourceCost") if line.is_repairable(): cost_repair_raw_api_object.add_raw_member( "amount", cost_repair_amounts, "engine.util.cost.type.ResourceCost") cost_forward_ref = ForwardRef(line, cost_name) creatable_raw_api_object.add_raw_member( "cost", cost_forward_ref, "engine.util.create.CreatableGameEntity") # Creation time if isinstance(line, GenieUnitLineGroup): creation_time = current_unit["creation_time"].get_value() else: # Buildings are created immediately creation_time = 0 creatable_raw_api_object.add_raw_member( "creation_time", creation_time, "engine.util.create.CreatableGameEntity") # Creation sound creation_sound_id = current_unit["train_sound_id"].get_value() # Create sound object obj_name = f"{game_entity_name}.CreatableGameEntity.Sound" sound_raw_api_object = RawAPIObject(obj_name, "CreationSound", dataset.nyan_api_objects) sound_raw_api_object.add_raw_parent("engine.util.sound.Sound") sound_location = ForwardRef(line, obj_ref) sound_raw_api_object.set_location(sound_location) # Search for the sound if it exists creation_sounds = [] if creation_sound_id > -1: genie_sound = dataset.genie_sounds[creation_sound_id] file_ids = genie_sound.get_sounds(civ_id=-1) if file_ids: file_id = genie_sound.get_sounds(civ_id=-1)[0] if file_id in dataset.combined_sounds: creation_sound = dataset.combined_sounds[file_id] creation_sound.add_reference(sound_raw_api_object) else: creation_sound = CombinedSound( creation_sound_id, file_id, f"creation_sound_{creation_sound_id}", dataset) dataset.combined_sounds.update({file_id: creation_sound}) creation_sound.add_reference(sound_raw_api_object) creation_sounds.append(creation_sound) sound_raw_api_object.add_raw_member("play_delay", 0, "engine.util.sound.Sound") sound_raw_api_object.add_raw_member("sounds", creation_sounds, "engine.util.sound.Sound") sound_forward_ref = ForwardRef(line, obj_name) creatable_raw_api_object.add_raw_member( "creation_sounds", [sound_forward_ref], "engine.util.create.CreatableGameEntity") line.add_raw_api_object(sound_raw_api_object) # Condition unlock_conditions = [] enabling_research_id = line.get_enabling_research_id() if enabling_research_id > -1: unlock_conditions.extend( AoCAuxiliarySubprocessor.get_condition(line, obj_ref, enabling_research_id)) creatable_raw_api_object.add_raw_member( "condition", unlock_conditions, "engine.util.create.CreatableGameEntity") # Placement modes placement_modes = [] if isinstance(line, GenieBuildingLineGroup): # Buildings are placed on the map # Place mode obj_name = f"{game_entity_name}.CreatableGameEntity.Place" place_raw_api_object = RawAPIObject(obj_name, "Place", dataset.nyan_api_objects) place_raw_api_object.add_raw_parent( "engine.util.placement_mode.type.Place") place_location = ForwardRef( line, f"{game_entity_name}.CreatableGameEntity") place_raw_api_object.set_location(place_location) # Tile snap distance (uses 1.0 for grid placement) place_raw_api_object.add_raw_member( "tile_snap_distance", 1.0, "engine.util.placement_mode.type.Place") # Clearance size clearance_size_x = current_unit["clearance_size_x"].get_value() clearance_size_y = current_unit["clearance_size_y"].get_value() place_raw_api_object.add_raw_member( "clearance_size_x", clearance_size_x, "engine.util.placement_mode.type.Place") place_raw_api_object.add_raw_member( "clearance_size_y", clearance_size_y, "engine.util.placement_mode.type.Place") # Allow rotation place_raw_api_object.add_raw_member( "allow_rotation", True, "engine.util.placement_mode.type.Place") # Max elevation difference elevation_mode = current_unit["elevation_mode"].get_value() if elevation_mode == 2: max_elevation_difference = 0 elif elevation_mode == 3: max_elevation_difference = 1 else: max_elevation_difference = MemberSpecialValue.NYAN_INF place_raw_api_object.add_raw_member( "max_elevation_difference", max_elevation_difference, "engine.util.placement_mode.type.Place") line.add_raw_api_object(place_raw_api_object) place_forward_ref = ForwardRef(line, obj_name) placement_modes.append(place_forward_ref) if line.get_class_id() == 39: # Gates obj_name = f"{game_entity_name}.CreatableGameEntity.Replace" replace_raw_api_object = RawAPIObject(obj_name, "Replace", dataset.nyan_api_objects) replace_raw_api_object.add_raw_parent( "engine.util.placement_mode.type.Replace") replace_location = ForwardRef( line, f"{game_entity_name}.CreatableGameEntity") replace_raw_api_object.set_location(replace_location) # Game entities (only stone wall) wall_line_id = 117 wall_line = dataset.building_lines[wall_line_id] wall_name = name_lookup_dict[117][0] game_entities = [ForwardRef(wall_line, wall_name)] replace_raw_api_object.add_raw_member( "game_entities", game_entities, "engine.util.placement_mode.type.Replace") line.add_raw_api_object(replace_raw_api_object) replace_forward_ref = ForwardRef(line, obj_name) placement_modes.append(replace_forward_ref) else: placement_modes.append( dataset. nyan_api_objects["engine.util.placement_mode.type.Eject"]) # OwnStorage mode obj_name = f"{game_entity_name}.CreatableGameEntity.OwnStorage" own_storage_raw_api_object = RawAPIObject(obj_name, "OwnStorage", dataset.nyan_api_objects) own_storage_raw_api_object.add_raw_parent( "engine.util.placement_mode.type.OwnStorage") own_storage_location = ForwardRef( line, f"{game_entity_name}.CreatableGameEntity") own_storage_raw_api_object.set_location(own_storage_location) # Container container_forward_ref = ForwardRef( train_location, "%s.Storage.%sContainer" % (train_location_name, train_location_name)) own_storage_raw_api_object.add_raw_member( "container", container_forward_ref, "engine.util.placement_mode.type.OwnStorage") line.add_raw_api_object(own_storage_raw_api_object) own_storage_forward_ref = ForwardRef(line, obj_name) placement_modes.append(own_storage_forward_ref) creatable_raw_api_object.add_raw_member( "placement_modes", placement_modes, "engine.util.create.CreatableGameEntity") line.add_raw_api_object(creatable_raw_api_object) line.add_raw_api_object(cost_raw_api_object)