Beispiel #1
0
def gather_pgd_colors(props: PriorityPropDict, loader: AssetLoader,
                      require_override=True) -> Tuple[Optional[Sequence[ColorEntry]], Optional[Sequence[ColorEntry]]]:
    '''Gather color and dye definitions from a PrimalGameData asset.'''
    colors: Optional[List[ColorEntry]] = list()
    dyes: Optional[List[ColorEntry]] = list()

    # Collect the color definitions
    color_def_overrides = props['ColorDefinitions'][0]
    if require_override and len(color_def_overrides) == 1:
        colors = None
    else:
        color_defs = color_def_overrides[-1].values
        colors = list()
        for definition in ((entry.as_dict() for entry in color_defs)):
            name = definition.get('ColorName', None) or '~~unset~~'
            value = definition.get('ColorValue', None)
            color = value.values[0].as_tuple() if value else None
            colors.append((str(name), color))

    # Collect the dye definitions
    dye_def_overrides = props['MasterDyeList'][0]
    if require_override and len(dye_def_overrides) == 1:
        dyes = None
    else:
        dye_defs = props['MasterDyeList'][0][-1].values
        dyes = list()
        for dye_asset in (loader.load_related(entry) for entry in dye_defs):
            dye_props = gather_properties(dye_asset)
            name = stat_value(dye_props, 'DescriptiveNameBase', 0, None) or '~~unset~~'
            value = dye_props['DyeColor'][0][-1]
            color = value.values[0].as_tuple() if value else None
            dyes.append((str(name), color))

    return (colors, dyes)
Beispiel #2
0
def gather_immobilization_data(props: PriorityPropDict,
                               loader: AssetLoader) -> List[str]:
    # Tag is used to identify immobilization targets and compatible saddles
    # tag = stat_value(props, 'CustomTag', 0, None) or f'<unknown tag for {asset.default_class.name}'

    # Drag weight is used for immobilization calculation and arena entry
    # dragWeight = stat_value(props, 'DragWeight', 0, None)

    items = ensure_immobilization_itemdata(loader)
    immobilizedBy: List[Any] = []
    if stat_value(props, 'bPreventImmobilization', 0, False):
        return immobilizedBy
    if stat_value(props, 'bIsWaterDino', 0, False):
        return immobilizedBy
    weight = stat_value(props, 'DragWeight', 0, 35)
    mass = stat_value(props, 'Mass', 0, 100.0)
    is_boss = stat_value(props, 'bIsBossDino', 0, False)
    tag = stat_value(props, 'CustomTag', 0, None)
    ignore_traps = stat_value(props, 'bIgnoreAllImmobilizationTraps', 0, False)
    for item in items:
        if item.is_trap and ignore_traps:
            continue
        if item.minWeight > weight or item.maxWeight <= weight:
            continue
        if item.minMass > mass or item.maxMass <= mass:
            continue
        if is_boss:
            continue
        if tag in item.ignoreTags:  # pylint: disable=unsupported-membership-test
            continue
        immobilizedBy.append(item.name)

    return immobilizedBy
Beispiel #3
0
def gather_stat_data(props, statIndexes):
    statsArray = list()

    # Create a temporary set of Iw defaults, overriding torpor with TheMaxTorporIncreasePerBaseLevel or 0.06
    iw_values = list(IW_VALUES)
    iw_values[2] = stat_value(props, 'TheMaxTorporIncreasePerBaseLevel', 0,
                              0.06)

    for _, ark_index in enumerate(statIndexes):
        can_level = (ark_index == 2) or stat_value(
            props, 'CanLevelUpValue', ark_index, CANLEVELUP_VALUES)
        add_one = 1 if IS_PERCENT_STAT[ark_index] else 0
        zero_mult = 1 if can_level else 0
        ETHM = stat_value(props, 'ExtraTamedHealthMultiplier', ark_index,
                          EXTRA_MULTS_VALUES)

        stat_data = [
            stat_value(props, 'MaxStatusValues', ark_index, BASE_VALUES) +
            add_one,
            stat_value(props, 'AmountMaxGainedPerLevelUpValue', ark_index,
                       iw_values) * zero_mult,
            stat_value(props, 'AmountMaxGainedPerLevelUpValueTamed', ark_index,
                       0.0) * ETHM * zero_mult,
            stat_value(props, 'TamingMaxStatAdditions', ark_index, 0.0),
            stat_value(props, 'TamingMaxStatMultipliers', ark_index, 0.0),
        ]

        # Round to 6dp like existing values creator
        stat_data = [round(value, 6) for value in stat_data]

        # Creates a null value in the JSON for stats that are unused
        dont_use = stat_value(props, 'DontUseValue', ark_index,
                              DONTUSESTAT_VALUES)
        if dont_use and not can_level:
            stat_data = None

        statsArray.append(stat_data)

    return statsArray
Beispiel #4
0
def values_for_species(asset: UAsset,
                       props: PriorityPropDict,
                       proxy: PrimalDinoCharacter,
                       allFields=False,
                       fullStats=True,
                       includeColor=True,
                       includeBreeding=True,
                       includeImmobilize=True,
                       includeDamageMults=True,
                       includeTaming=True):
    assert asset.loader

    # Having no name or tag is an indication that this is an intermediate class, not a spawnable species
    name = stat_value(props, 'DescriptiveName', 0, None) or stat_value(
        props, 'DinoNameTag', 0, None)
    if not name:
        logger.debug(
            f"Species {asset.assetname} has no DescriptiveName or DinoNameTag - skipping"
        )
        return

    # Also consider anything that doesn't override any base status value as non-spawnable
    if not any(
            stat_value(props, 'MaxStatusValues', n, None) is not None
            for n in ARK_STAT_INDEXES):
        logger.debug(
            f"Species {asset.assetname} has no overridden stats - skipping")
        return

    assert asset.assetname and asset.default_export and asset.default_class and asset.default_class.fullname

    modid: str = asset.loader.get_mod_id(asset.assetname)
    overrides = get_overrides_for_species(asset.assetname, modid)

    if get_overrides_for_species(asset.assetname, modid).skip_export:
        return

    bp: str = asset.default_class.fullname
    if bp.endswith('_C'):
        bp = bp[:-2]

    # Replace names to match ASB's hardcoding of specific species
    name = overrides.descriptive_name or name

    # Variant information
    variants = get_variants_from_assetname(
        asset.assetname, overrides) | get_variants_from_species(proxy)
    if variants:
        if should_skip_from_variants(variants, overrides):
            return
        name = adjust_name_from_variants(name, variants, overrides)

    species = dict(name=name, blueprintPath=bp)
    if variants:
        species['variants'] = tuple(sorted(variants))

    # Stat data
    statsField = 'fullStatsRaw' if fullStats else 'statsRaw'
    statIndexes = ARK_STAT_INDEXES if fullStats else ASB_STAT_INDEXES
    species[statsField] = gather_stat_data(props, statIndexes)

    # Set imprint multipliers
    stat_imprint_mults: List[float] = list()
    for ark_index in statIndexes:
        imprint_mult = stat_value(props, 'DinoMaxStatAddMultiplierImprinting',
                                  ark_index, IMPRINT_VALUES)
        stat_imprint_mults.append(imprint_mult)
    if stat_imprint_mults != list(IMPRINT_VALUES):
        species['statImprintMult'] = stat_imprint_mults

    if includeImmobilize:
        # ImmobilizedBy format data
        immobilization_data = None
        try:
            immobilization_data = gather_immobilization_data(
                props, asset.loader)
        except (AssetNotFound, ModNotFound) as ex:
            logger.warning(
                f'Failure while gathering immobilization data for {asset.assetname}:\n\t{ex}'
            )
        if immobilization_data is not None:
            species['immobilizedBy'] = immobilization_data

    if includeBreeding:
        # Breeding data
        if stat_value(props, 'bCanHaveBaby', 0,
                      False):  # TODO: Consider always including this data
            breeding_data = None
            try:
                breeding_data = gather_breeding_data(props, asset.loader)
            except (AssetNotFound, ModNotFound) as ex:
                logger.warning(
                    f'Failure while gathering breeding data for {asset.assetname}:\n\t{ex}'
                )
            if breeding_data:
                species['breeding'] = breeding_data

    if includeColor:
        # Color data
        if stat_value(props, 'bUseColorization', False):
            colors = None
            try:
                colors = gather_color_data(asset, props, overrides)
            except (AssetNotFound, ModNotFound) as ex:
                logger.warning(
                    f'Failure while gathering color data for {asset.assetname}:\n\t{ex}'
                )
            if colors is not None:
                species['colors'] = colors

    if includeTaming:
        # Taming data
        if stat_value(
                props, 'bCanBeTamed', True
        ) or True:  # ASB currently requires all species to have taming data
            taming = None
            try:
                taming = gather_taming_data(props)
            except (AssetNotFound, ModNotFound) as ex:
                logger.warning(
                    f'Failure while gathering taming data for {asset.assetname}:\n\t{ex}'
                )
            if taming:
                species['taming'] = taming

    if includeDamageMults:
        # Bone damage multipliers
        dmg_mults = None
        try:
            dmg_mults = gather_damage_mults(props)
        except (AssetNotFound, ModNotFound) as ex:
            logger.warning(
                f'Failure while gathering bone damage data for {asset.assetname}:\n\t{ex}'
            )
        if dmg_mults:
            species['boneDamageAdjusters'] = dmg_mults

    # Misc data
    noSpeedImprint = (stat_value(props, 'DinoMaxStatAddMultiplierImprinting',
                                 9, IMPRINT_VALUES) == 0)
    usesOxyWild = stat_value(props, 'bCanSuffocate', 0, True)
    usesOxyTamed = stat_value(props, 'bCanSuffocateIfTamed', 0, usesOxyWild)
    forceOxy = stat_value(props, 'bForceGainOxygen', 0, False)
    doesntUseOxygen = not (usesOxyTamed or forceOxy)
    ETBHM = stat_value(props, 'ExtraTamedBaseHealthMultiplier', 0, 1)
    TBHM = stat_value(props, 'TamedBaseHealthMultiplier', 0, 1) * ETBHM

    displayed_stats: int = 0

    for i in statIndexes:
        use_stat = not stat_value(props, 'DontUseValue', i, DONTUSESTAT_VALUES)
        if use_stat and not (i == 3 and doesntUseOxygen):
            displayed_stats |= (1 << i)

    if allFields or TBHM != 1: species['TamedBaseHealthMultiplier'] = cd(TBHM)
    if allFields or noSpeedImprint:
        species['NoImprintingForSpeed'] = noSpeedImprint
    if allFields or doesntUseOxygen:
        species['doesNotUseOxygen'] = doesntUseOxygen
    if allFields or displayed_stats:
        species['displayedStats'] = displayed_stats

    return species
Beispiel #5
0
def gather_breeding_data(props, loader: AssetLoader) -> Dict[str, Any]:
    data: Dict[str, Any] = dict(gestationTime=0, incubationTime=0)

    gestation_breeding = stat_value(props, 'bUseBabyGestation', 0, False)
    has_eggs = False

    if props['FertilizedEggItemsToSpawn'][0] and props[
            'FertilizedEggItemsToSpawn'][0][-1].values:
        # eggs = list(filter(lambda v: v and str(v) != 'None', props['FertilizedEggItemsToSpawn'][0][-1].values))
        eggs = [
            egg for egg in props['FertilizedEggItemsToSpawn'][0][-1].values
            if str(egg) != 'None'
        ]
        has_eggs = bool(eggs)

    if gestation_breeding:
        gestation_speed = stat_value(props, 'BabyGestationSpeed', 0,
                                     BABYGESTATIONSPEED_DEFAULT)
        extra_gestation_speed_m = stat_value(
            props, 'ExtraBabyGestationSpeedMultiplier', 0, 1.0)

        # TODO: Verify if these should really default to 1 - seems odd
        gestation_speed = gestation_speed or 1
        extra_gestation_speed_m = extra_gestation_speed_m or 1
        # 'gestationTime' = 1 / (Baby Gestation Speed × Extra Baby Gestation Speed Multiplier)
        data['gestationTime'] = (
            1 / gestation_speed / extra_gestation_speed_m
        ) if gestation_speed and extra_gestation_speed_m else None

    elif has_eggs:
        fert_egg_asset = loader.load_related(eggs[0])
        fert_egg_props = ark.mod.gather_properties(fert_egg_asset)
        egg_decay = stat_value(fert_egg_props, 'EggLoseDurabilityPerSecond', 0,
                               1)
        extra_egg_decay_m = stat_value(
            fert_egg_props, 'ExtraEggLoseDurabilityPerSecondMultiplier', 0, 1)

        # 'incubationTime' = 100 / (Egg Lose Durability Per Second × Extra Egg Lose Durability Per Second Multiplier)
        data['incubationTime'] = (
            100 / egg_decay /
            extra_egg_decay_m) if egg_decay and extra_egg_decay_m else None
        data['eggTempMin'] = stat_value(fert_egg_props, 'EggMinTemperature', 0)
        data['eggTempMax'] = stat_value(fert_egg_props, 'EggMaxTemperature', 0)

    # 'maturationTime' = 1 / (Baby Age Speed × Extra Baby Age Speed Multiplier)
    baby_age_speed = stat_value(props, 'BabyAgeSpeed', 0, 1)
    extra_baby_age_speed_m = stat_value(props, 'ExtraBabyAgeSpeedMultiplier',
                                        0, 1)

    data['maturationTime'] = (
        1 / baby_age_speed / extra_baby_age_speed_m
    ) if baby_age_speed and extra_baby_age_speed_m else None
    data['matingCooldownMin'] = stat_value(
        props, 'NewFemaleMinTimeBetweenMating', 0,
        FEMALE_MINTIMEBETWEENMATING_DEFAULT)
    data['matingCooldownMax'] = stat_value(
        props, 'NewFemaleMaxTimeBetweenMating', 0,
        FEMALE_MAXTIMEBETWEENMATING_DEFAULT)

    return data
Beispiel #6
0
def gather_color_data(asset: UAsset, props: PriorityPropDict, overrides: OverrideSettings):
    '''Gather color region definitions for a species.'''
    assert asset and asset.loader and asset.assetname
    loader: AssetLoader = asset.loader

    settings = overrides.color_regions

    colors: List[Dict] = list()
    male_colorset = props['RandomColorSetsMale'][0][-1]
    female_colorset = props['RandomColorSetsFemale'][0][-1]

    male_colorset_props: Optional[PriorityPropDict] = None
    female_colorset_props: Optional[PriorityPropDict] = None

    # Choose which color set to use
    if male_colorset and male_colorset.value and male_colorset.value.value:
        try:
            male_colorset_props = ark.mod.gather_properties(loader.load_related(male_colorset))
        except AssetNotFound as ex:
            logger.warning(f'Unable to load male colorset for {asset.assetname}:\n\t{ex}')
    if female_colorset and female_colorset.value and female_colorset.value.value:
        try:
            female_colorset_props = ark.mod.gather_properties(loader.load_related(female_colorset))
        except AssetNotFound as ex:
            logger.warning(f'Unable to load female colorset for {asset.assetname}:\n\t{ex}')

    # TODO: Incorporate both male and female colorsets, as well as if multiple colorsets are listed
    colorset_props = male_colorset_props or female_colorset_props
    if not colorset_props:
        return None

    if stat_value(props, 'bIsCorrupted', 0, False):
        return colors

    # Export a list of color names for each region
    for i in range(NUM_REGIONS):
        prevent_region = stat_value(props, 'PreventColorizationRegions', i, 0)
        color: Dict[str, Any] = dict()
        color_names: Set[str] = set()

        if prevent_region:
            color['name'] = None
        elif i not in colorset_props['ColorSetDefinitions']:
            color['name'] = None
        else:
            color_set_defs: Dict[str, UEBase] = colorset_props['ColorSetDefinitions'][i][-1].as_dict()

            if 'ColorEntryNames' in color_set_defs:
                for color_name in color_set_defs['ColorEntryNames'].values:
                    color_names.add(str(color_name))

            region_name: Optional[str] = str(color_set_defs.get('RegionName', settings.default_name)).strip()

            if region_name and any_regexes_match(settings.nullify_name_regexes, region_name):
                # Null-out this region if it matches NULLABLE_REGION_COLORS exactly
                if not color_names or color_names == NULLABLE_REGION_COLORS:
                    region_name = None
                    color_names.clear()

            if region_name and any_regexes_match(settings.useless_name_regexes, region_name):
                # Region name is useless, replace with the default_name
                region_name = settings.default_name

            if region_name and i in settings.region_names:
                # There's a specific override for this region
                region_name = settings.region_names[i]

            if region_name and settings.capitalize:
                region_name = region_name[0].upper() + region_name[1:]

            if not region_name:
                color = None  # type: ignore
            else:
                color['name'] = region_name
                if region_name and color_names:
                    color['colors'] = sorted(color_names)

        colors.append(color)

    return colors
Beispiel #7
0
if str(character_props['bUseColorization'][0][-1]) is 'False':
    print('No Color Regions Used')
else:
    male_colorset_asset = loader.load_related(character_props['RandomColorSetsMale'][0][-1])
    male_colorset_props = ark.mod.gather_properties(male_colorset_asset)

    # Female Colorset
    # female_colorset_asset = loader.load_related(character_props['RandomColorSetsFemale'][0][-1])
    # female_colorset_props = ark.mod.gather_properties(female_colorset_asset)

    # Reference from ASB's values.json file
    # "colors":[{"name":"Body Main","colorIds":[25,28,8,51,52,30,36,38,48,50,56]}
    # {"name":null,"colorIds":[]}
    colors = []
    for i, region in enumerate(default_color_regions):
        prevent_region = stat_value(character_props, 'PreventColorizationRegions', i, region)
        color: Dict[str, Any] = dict()
        color_ids: List[int] = []

        if prevent_region:
            color['name'] = 'null'
        else:
            color_set_defs = create_dict(male_colorset_props['ColorSetDefinitions'][i][-1])

            try:
                color['name'] = str(color_set_defs['RegionName'])
            except:
                color['name'] = 'No Name Available'

            for color_name in color_set_defs['ColorEntryNames'].values:
                color_id = [c_def[0] for c_def in color_defs].index(str(color_name)) + 1
Beispiel #8
0
def gather_taming_data(props) -> Dict[str, Any]:
    data: Dict[str, Any] = dict()

    # Currently unable to gather the foods list
    eats: Optional[List[str]] = None
    favorite_kibble: Optional[str] = None
    special_food_values: Optional[List[Dict[str, Dict[str, List[int]]]]] = None

    can_tame = stat_value(props, 'bCanBeTamed', 0, True)
    can_knockout = stat_value(props, 'bCanBeTorpid', 0, True)
    data['nonViolent'] = stat_value(props, 'bSupportWakingTame', 0,
                                    False) and can_tame
    data['violent'] = not stat_value(props, 'bPreventSleepingTame', 0,
                                     False) and can_tame and can_knockout

    if can_tame or True:
        data['tamingIneffectiveness'] = cf(
            stat_value(props, 'TameIneffectivenessByAffinity', 0, 20.0))
        data['affinityNeeded0'] = cf(
            stat_value(props, 'RequiredTameAffinity', 0, 100))
        data['affinityIncreasePL'] = cf(
            stat_value(props, 'RequiredTameAffinityPerBaseLevel', 0, 5.0))

        torpor_depletion = stat_value(props, 'KnockedOutTorpidityRecoveryRateMultiplier', 0, 3.0) \
            * stat_value(props, 'RecoveryRateStatusValue', 2, 0.00)

        if data['violent']:
            data['torporDepletionPS0'] = cd(-torpor_depletion)
        if data['nonViolent']:
            data['wakeAffinityMult'] = cf(
                stat_value(props, 'WakingTameFoodAffinityMultiplier', 0, 1.6))
            data['wakeFoodDeplMult'] = cf(
                stat_value(props, 'WakingTameFoodConsumptionRateMultiplier', 0,
                           2.0))

        data['foodConsumptionBase'] = cf(
            -stat_value(props, 'BaseFoodConsumptionRate', 0, -0.025000))  # pylint: disable=invalid-unary-operand-type
        data['foodConsumptionMult'] = cf(
            stat_value(props, 'ProneWaterFoodConsumptionMultiplier', 0, 1.00))

        if eats is not None:
            data['eats'] = eats
        if favorite_kibble is not None:
            data['favoriteKibble'] = favorite_kibble
        if special_food_values is not None:
            data['specialFoodValues'] = special_food_values

    return data