Exemplo n.º 1
0
def is_item_base_class(item: PrimalItem) -> bool:
    item_name = item.get('DescriptiveNameBase', 0, None)
    icon_texture = item.get('ItemIcon', 0, None)
    icon_material = item.get('ItemIconMaterialParent', 0, None)

    if not item_name or (not icon_texture and not icon_material):
        return True
    return False
Exemplo n.º 2
0
def _get_pretty_item_type(item: PrimalItem) -> str:
    itemType = item.get('MyItemType', 0, None)
    value = itemType.get_enum_value_name()
    if value == 'MiscConsumable':
        consumableType = item.get('MyConsumableType', 0, None)
        return value + '/' + consumableType.get_enum_value_name()
    elif value == 'Equipment':
        equipmentType = item.get('MyEquipmentType', 0, None)
        return value + '/' + equipmentType.get_enum_value_name()
    return value
Exemplo n.º 3
0
def convert_egg_values(item: PrimalItem) -> Dict[str, Any]:
    v = dict()

    dino_class = item.get('EggDinoClassToSpawn', 0, None)
    if dino_class:
        v['dinoClass'] = dino_class
        v['temperature'] = (item.EggMinTemperature[0], item.EggMaxTemperature[0])

    hud_mic_ref = item.get('ItemIconMaterialParent', 0, None)
    if hud_mic_ref:
        hud_mic = item.get_source().asset.loader.load_related(hud_mic_ref)
        hud_mic = hud_mic.default_export
        hud_colors = gather_hud_color_data(hud_mic)
        if hud_colors:
            v['hudColorisation'] = hud_colors

    return v
Exemplo n.º 4
0
def convert_egg_values(item: PrimalItem) -> Optional[EggData]:
    dino_class = item.get('EggDinoClassToSpawn', 0, None)
    if not dino_class or not dino_class.value or not dino_class.value.value:
        return None

    return EggData(
        dinoClass=dino_class.value.value.format_for_json(),
        temperature=MinMaxRange(min=item.EggMinTemperature[0],
                                max=item.EggMaxTemperature[0]),
    )
Exemplo n.º 5
0
def convert_egg_values(item: PrimalItem) -> Dict[str, Any]:
    v = dict()

    dino_class = item.get('EggDinoClassToSpawn', 0, None)
    if dino_class:
        v['dinoClass'] = dino_class
        v['temperature'] = (item.EggMinTemperature[0], item.EggMaxTemperature[0])

    hud_mic_ref = item.get('ItemIconMaterialParent', 0, None)
    if hud_mic_ref and hud_mic_ref.value and hud_mic_ref.value.value:
        try:
            hud_mic = item.get_source().asset.loader.load_related(hud_mic_ref)
            hud_mic = hud_mic.default_export
            hud_colors = gather_hud_color_data(hud_mic)
            if hud_colors:
                v['hudColorisation'] = hud_colors
        except AssetLoadException:
            logger.warning(f'Failure while gathering color data from {hud_mic_ref.value.value.fullname}', exc_info=True)

    return v
Exemplo n.º 6
0
def convert_crafting_values(item: PrimalItem) -> Dict[str, Any]:
    if item.bCraftDontActuallyGiveItem[0]:
        product_count: Union[int, IntProperty] = 0
    else:
        if item.CraftingGivesItemQuantityOverride[0].value >= 1:
            product_count = item.CraftingGiveItemCount[0]
        else:
            product_count = item.ItemQuantity[0]

    v: Dict[str, Any] = dict(crafting=dict(
        xp=item.BaseCraftingXP[0],
        bpCraftTime=item.BlueprintTimeToCraft[0],
        minLevelReq=item.CraftingMinLevelRequirement[0],
        productCount=product_count,
        skillQualityMult=(item.CraftingSkillQualityMultiplierMin[0],
                          item.CraftingSkillQualityMultiplierMax[0]),
    ))

    recipe = item.get('BaseCraftingResourceRequirements', 0, None)
    if recipe and recipe.values:
        v['crafting']['recipe'] = [
            v for v in (convert_recipe_entry(entry.as_dict())
                        for entry in recipe.values) if v
        ]

    if item.bAllowRepair[0]:
        v['repair'] = dict(
            xp=item.BaseRepairingXP[0],
            time=item.TimeForFullRepair[0],
            resourceMult=item.RepairResourceRequirementMultiplier[0],
        )
        if item.bOverrideRepairingRequirements[0]:
            recipe = item.get('OverrideRepairingRequirements', 0, None)
            if recipe and recipe.values:
                v['repair']['recipe'] = [
                    v for v in (convert_recipe_entry(entry.as_dict())
                                for entry in recipe.values) if v
                ]

    return v
Exemplo n.º 7
0
def get_item_name(item: PrimalItem) -> Optional[str]:
    item_name = item.get('DescriptiveNameBase', fallback=None)
    if not item_name:
        return None

    out = str(item_name)

    # The game adds the Skin suffix to the item's name if bIsItemSkin is true. This only happens when the name is
    # not overridden by any other dynamic feature, like scripts or the rarity system (that preseeds quality and
    # other stats), and it's probably safer for us to export the CDO name in these cases.
    if item.bIsItemSkin[0] and not item.bUseBPGetItemName[0] and not item.bUseItemStats[0]:
        out += ' Skin'

    return out
Exemplo n.º 8
0
    def extract_core(self, _: Path):
        '''Perform sanity tests on core items.'''

        # Count species by prefix (/Game/<part> or /Game/Mods/<id>)
        counter: Counter = Counter()
        for clsname in find_sub_classes(PrimalItem.get_ue_type()):
            if not clsname.startswith('/Game'):
                continue

            parts = clsname.split('/')
            if clsname.startswith('/Game/Mods/'):
                modid = self.manager.loader.get_mod_id(clsname)
                assert modid
                parts[3] = modid
                parts = parts[:4]
            else:
                parts = parts[:3]

            counter.update(['/'.join(parts)])

        # Check counts against configured limits
        overrides = get_overrides()
        reports = list()
        for path, min_count in overrides.sanity_checks.min_items.items():
            count = counter.get(path, 0)
            logger.debug('%s = %d (need %d)', path, count, min_count)
            if count < min_count:
                reports.append((path, count, min_count))

        # If anything failed, report and turn off Git push
        if not reports:
            return None

        # Disable git push to hopefully avoid damaging commits
        self.manager.config.git.SkipPush = False

        # Put together a report message
        header = "Items count sanity check failed! (git push disabled):\n"
        lines: List[str] = []
        for path, count, min_count in reports:
            lines.append(f"    {path} expected {min_count}, found {count}\n")

        # Log it
        logger.error(''.join([header] + lines))

        # Send it to Discord
        send_to_discord(log=lines,
                        header='Purlovia failed the items sanity check:')
Exemplo n.º 9
0
 def get_ue_type(self) -> str:
     return PrimalItem.get_ue_type()
Exemplo n.º 10
0
def gather_item_stat(item: PrimalItem, index: Stat) -> Dict[str, Any]:
    leaf_export = item.get_source()
    ark_index = index.value
    return gather_inherited_struct_fields(leaf_export, 'ItemStatInfos', DEFAULTS, ark_index)
Exemplo n.º 11
0
def convert_crafting_values(
    item: PrimalItem,
    has_durability: bool = False
) -> Tuple[Optional[CraftingData], Optional[RepairData]]:
    recipe = item.get('BaseCraftingResourceRequirements', 0, None)
    if not recipe:
        return (None, None)

    # Crafted item number
    if item.bCraftDontActuallyGiveItem[0]:
        product_count: Union[int, IntProperty] = 0
    elif item.CraftingGiveItemCount[0] >= 1:
        product_count = item.CraftingGiveItemCount[0]
    elif item.CraftingGivesItemQuantityOverride[0] >= 1:
        product_count = item.CraftingGivesItemQuantityOverride[0]
    else:
        product_count = item.ItemQuantity[0]

    crafting = CraftingData(
        xp=item.BaseCraftingXP[0],
        time=item.BlueprintTimeToCraft[0],
        levelReq=item.CraftingMinLevelRequirement[0],
        productCount=int(product_count),
        skillQualityMult=MinMaxRange(
            min=item.CraftingSkillQualityMultiplierMin[0],
            max=item.CraftingSkillQualityMultiplierMax[0]),
        recipe=list(convert_recipe_entries(recipe.values)),
    )

    # Do not export crafting info if recipe consists only of nulls.
    if not crafting.recipe:
        return (None, None)

    # Durability repair info
    repair = None
    if item.bAllowRepair[0] and has_durability:
        repair = RepairData(
            xp=item.BaseRepairingXP[0],
            time=item.TimeForFullRepair[0],
            recipe=[],
        )

        if item.bOverrideRepairingRequirements[0]:
            recipe = item.get('OverrideRepairingRequirements', 0, None)
            if not recipe or not recipe.values:
                # Override to no ingredients, skip repair.
                repair = None
            else:
                # Convert the repair requirements list.
                repair.recipe = list(convert_recipe_entries(recipe.values))

                # Do not export repair info if the overrides lead to no valid ingredients
                if not repair.recipe:
                    repair = None
        else:
            # Copy crafting ingredients and scale their quantities by the repair multiplier.
            qty_mult = item.RepairResourceRequirementMultiplier[0]
            if qty_mult != 1.0:
                for ingredient in crafting.recipe:
                    ingredient_copy = ingredient.copy()
                    ingredient_copy.qty = clean_float(ingredient_copy.qty *
                                                      qty_mult)
                    repair.recipe.append(ingredient_copy)

    return (crafting, repair)
Exemplo n.º 12
0
def collect_data(asset: UAsset) -> Tuple[str, Any]:
    if args.default and args.export is not None:
        print("Cannot specify an export with --default", file=sys.stderr)
        sys.exit(1)

    if args.ovi:
        if not args.export and not args.default:
            # Grab the default export since we need a starting point for the proxy.
            args.default = True
        export = find_export(asset)
        assert export
        assert export.fullname

        if not inherits_from(export, PrimalItem.get_ue_type()):
            print(f"Export {export.name} is not a subclass of PrimalItem.", file=sys.stderr)
            sys.exit(1)

        proxy: UEProxyStructure = gather_properties(export)
        item = cast(PrimalItem, proxy)

        if 'ItemIconMaterialParent' not in item:
            print("Item does not use an icon shader", file=sys.stderr)
            sys.exit(1)

        name = get_item_name(item) or export.name
        data: Dict[str, Any] = dict(
            Format='2.0',
            Name=name,
            BlueprintPath=export.fullname,
        )

        assert asset.loader
        mat_instance = asset.loader.load_related(item.ItemIconMaterialParent[0]).default_export
        assert mat_instance
        mat_properties = mat_instance.properties.as_dict()

        # Convert all parameters from the material instance.
        parameters = dict()
        if 'ScalarParameterValues' in mat_properties:
            for param in mat_properties['ScalarParameterValues'][0].values:
                param_info = param.as_dict()
                param_name = sanitise_output(param_info['ParameterName'])
                parameters[param_name] = param_info['ParameterValue']
        if 'VectorParameterValues' in mat_properties:
            for param in mat_properties['VectorParameterValues'][0].values:
                param_info = param.as_dict()
                param_name = sanitise_output(param_info['ParameterName'])
                parameters[param_name] = param_info['ParameterValue'].values[0]
        if 'TextureParameterValues' in mat_properties:
            for param in mat_properties['TextureParameterValues'][0].values:
                param_info = param.as_dict()
                param_name = sanitise_output(param_info['ParameterName'])
                parameters[param_name] = param_info['ParameterValue']

        if parameters:
            data['2DMaterial'] = dict(Parent=mat_properties['Parent'][0], **parameters)
        else:
            # Export only the parent material as the instance has no parameters.
            data['2DMaterial'] = mat_properties['Parent'][0]

        data = sanitise_output(data)
        filename = create_filename(export.fullname)

    elif args.default or args.export:
        export = find_export(asset)
        assert export
        assert export.fullname
        data = sanitise_output(export.properties)
        filename = create_filename(export.fullname)

    else:
        # Full asset extraction
        data = sanitise_output(asset)
        assert asset.assetname
        filename = create_filename(asset.assetname)

    return (filename, data)