예제 #1
0
파일: stats.py 프로젝트: arkutils/Purlovia
def gather_stat_data(
        dcsc_props: PrimalDinoStatusComponent,
        meta_props: PrimalDinoStatusComponent, is_flyer: bool,
        statIndexes: Tuple[int, ...]) -> List[Optional[List[float]]]:
    statsArray = list()

    iw_values: List[float] = [0] * len(statIndexes)
    for _, ark_index in enumerate(statIndexes):
        can_level = (ark_index == 2) or meta_props.CanLevelUpValue[ark_index]
        dont_use = meta_props.DontUseValue[ark_index]

        # Creates a null value in the JSON for stats that are unused
        if dont_use and not can_level:
            stat_data: Optional[List[float]] = None

        else:
            add_one = 1 if IS_PERCENT_STAT[ark_index] else 0

            # Zero-out stats that can't level
            wild_mult = 1 if can_level else 0

            # Also zero-out domestic stats that can't level, adding exception for flyer speed :(
            dom_mult = 1 if ark_index == 9 and is_flyer else wild_mult

            ETHM = dcsc_props.ExtraTamedHealthMultiplier[
                0].rounded_value if ark_index == 0 else 1

            # Overrides the IW value for Torpor. While this hasn't been seen before, a species may allow torpor
            #   to be leveled in the wild. Unsure how Ark would handle this.
            if ark_index == 2:
                iw_values[
                    ark_index] = dcsc_props.TheMaxTorporIncreasePerBaseLevel[
                        0].rounded_value
            else:
                iw_values[
                    ark_index] = dcsc_props.AmountMaxGainedPerLevelUpValue[
                        ark_index].rounded_value

            stat_data = [
                cd(dcsc_props.MaxStatusValues[ark_index].rounded_value +
                   add_one),
                cd(iw_values[ark_index] * wild_mult),
                cd(dcsc_props.AmountMaxGainedPerLevelUpValueTamed[ark_index].
                   rounded_value * ETHM * dom_mult),
                cf(dcsc_props.TamingMaxStatAdditions[ark_index].rounded_value),
                cf(dcsc_props.TamingMaxStatMultipliers[ark_index].rounded_value
                   ),
            ]

        statsArray.append(stat_data)

    return statsArray
예제 #2
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 = [
            cd(
                stat_value(props, 'MaxStatusValues', ark_index, BASE_VALUES) +
                add_one),
            cd(
                stat_value(props, 'AmountMaxGainedPerLevelUpValue', ark_index,
                           iw_values) * zero_mult),
            cd(
                stat_value(props, 'AmountMaxGainedPerLevelUpValueTamed',
                           ark_index, 0.0) * ETHM * zero_mult),
            cf(stat_value(props, 'TamingMaxStatAdditions', ark_index, 0.0)),
            cf(stat_value(props, 'TamingMaxStatMultipliers', ark_index, 0.0)),
        ]

        # 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
예제 #3
0
def gather_taming_data(
        char_props: PrimalDinoCharacter,
        dcsc_props: PrimalDinoStatusComponent) -> 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 = char_props.bCanBeTamed[0]
    can_knockout = char_props.bCanBeTorpid[0]
    data['nonViolent'] = char_props.bSupportWakingTame[0] and can_tame
    data['violent'] = not char_props.bPreventSleepingTame[
        0] and can_tame and can_knockout

    if can_tame or True:
        data['tamingIneffectiveness'] = cf(
            char_props.TameIneffectivenessByAffinity[0].rounded_value)
        data['affinityNeeded0'] = cf(
            char_props.RequiredTameAffinity[0].rounded_value)
        data['affinityIncreasePL'] = cf(
            char_props.RequiredTameAffinityPerBaseLevel[0].rounded_value)

        torpor_depletion = dcsc_props.KnockedOutTorpidityRecoveryRateMultiplier[0].rounded_value \
            * dcsc_props.RecoveryRateStatusValue[2].rounded_value

        if data['violent']:
            data['torporDepletionPS0'] = cd(-torpor_depletion)
        if data['nonViolent']:
            data['wakeAffinityMult'] = cf(
                char_props.WakingTameFoodAffinityMultiplier[0].rounded_value)
            data['wakeFoodDeplMult'] = cf(
                dcsc_props.WakingTameFoodConsumptionRateMultiplier[0].
                rounded_value)

        data['foodConsumptionBase'] = cf(
            -dcsc_props.BaseFoodConsumptionRate[0].rounded_value)
        data['foodConsumptionMult'] = cf(
            dcsc_props.ProneWaterFoodConsumptionMultiplier[0].rounded_value)

        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
예제 #4
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
예제 #5
0
파일: taming.py 프로젝트: arkutils/Purlovia
def gather_taming_data(char_props: PrimalDinoCharacter, dcsc_props: PrimalDinoStatusComponent,
                       overrides: OverrideSettings) -> Dict[str, Any]:
    data: Dict[str, Any] = dict()

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

    if overrides.taming_method:
        can_tame = overrides.taming_method != TamingMethod.none
        data['nonViolent'] = overrides.taming_method == TamingMethod.awake
        data['violent'] = overrides.taming_method == TamingMethod.knockout
    else:
        can_tame = bool(char_props.bCanBeTamed[0])
        can_knockout = char_props.bCanBeTorpid[0]
        can_basket_tame = char_props.bAllowTrapping[0] and not char_props.bPreventWildTrapping[0] and char_props.bIsTrapTamed[0]
        data['nonViolent'] = (char_props.bSupportWakingTame[0] and can_tame) or can_basket_tame
        data['violent'] = not char_props.bPreventSleepingTame[0] and can_tame and can_knockout

    if can_tame or True:
        data['tamingIneffectiveness'] = cf(char_props.TameIneffectivenessByAffinity[0].rounded_value)
        data['affinityNeeded0'] = cf(char_props.RequiredTameAffinity[0].rounded_value)
        data['affinityIncreasePL'] = cf(char_props.RequiredTameAffinityPerBaseLevel[0].rounded_value)

        torpor_depletion = dcsc_props.KnockedOutTorpidityRecoveryRateMultiplier[0].rounded_value \
            * dcsc_props.RecoveryRateStatusValue[2].rounded_value

        if data['violent']:
            data['torporDepletionPS0'] = cd(-torpor_depletion)
        if data['nonViolent']:
            data['wakeAffinityMult'] = cf(char_props.WakingTameFoodAffinityMultiplier[0].rounded_value)
            data['wakeFoodDeplMult'] = cf(dcsc_props.WakingTameFoodConsumptionRateMultiplier[0].rounded_value)

        data['foodConsumptionBase'] = cf(-dcsc_props.BaseFoodConsumptionRate[0].rounded_value)
        data['foodConsumptionMult'] = cf(dcsc_props.ProneWaterFoodConsumptionMultiplier[0].rounded_value)
        data['babyFoodConsumptionMult'] = cf(dcsc_props.BabyDinoConsumingFoodRateMultiplier[0].rounded_value *
                                             dcsc_props.ExtraBabyDinoConsumingFoodRateMultiplier[0].rounded_value)

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

    return data
예제 #6
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
예제 #7
0
def gather_breeding_data(char_props: PrimalDinoCharacter,
                         loader: AssetLoader) -> Dict[str, Any]:
    data: Dict[str, Any] = dict(gestationTime=0, incubationTime=0)

    gestation_breeding = char_props.bUseBabyGestation[0]
    fert_eggs = char_props.get('FertilizedEggItemsToSpawn', 0, None)
    fert_egg_weights = char_props.get('FertilizedEggWeightsToSpawn', 0, None)

    if gestation_breeding:
        gestation_speed = char_props.BabyGestationSpeed[0].rounded_value
        extra_gestation_speed_m = char_props.ExtraBabyGestationSpeedMultiplier[
            0].rounded_value
        try:
            data['gestationTime'] = cd(1 / gestation_speed /
                                       extra_gestation_speed_m)
        except ZeroDivisionError:
            logger.warning(
                f"Species {char_props.get_source().asset.assetname} tried dividing by zero for its gestationTime"
            )

    elif fert_eggs and fert_eggs.values:
        eggs: List[Tuple[ObjectProperty, float]] = []
        for index, egg in enumerate(fert_eggs.values):
            weight = fert_egg_weights.values[index] if fert_egg_weights else 1
            # Verify the egg is a valid Object and that weight isn't 0
            if str(egg) == 'None' or weight == 0:
                continue

            eggs.append((egg, weight))

        # Sort eggs by highest weighting
        eggs.sort(reverse=True, key=itemgetter(1))

        if eggs:
            # We only provide the highest possibility egg to ASB
            fert_egg_asset = loader.load_related(eggs[0][0])
            assert fert_egg_asset.default_export
            egg_props: PrimalItem = ue.gathering.gather_properties(
                fert_egg_asset.default_export)
            egg_decay = egg_props.EggLoseDurabilityPerSecond[0].rounded_value
            extra_egg_decay_m = egg_props.ExtraEggLoseDurabilityPerSecondMultiplier[
                0].rounded_value

            # 'incubationTime' = 100 / (Egg Lose Durability Per Second × Extra Egg Lose Durability Per Second Multiplier)
            try:
                data['incubationTime'] = cd(100 / egg_decay /
                                            extra_egg_decay_m)
            except ZeroDivisionError:
                logger.warning(
                    f"Species {char_props.get_source().asset.assetname} tried dividing by zero for its incubationTime"
                )
            data['eggTempMin'] = egg_props.EggMinTemperature[0]
            data['eggTempMax'] = egg_props.EggMaxTemperature[0]

    # 'maturationTime' = 1 / (Baby Age Speed × Extra Baby Age Speed Multiplier)
    baby_age_speed = char_props.BabyAgeSpeed[0].rounded_value
    extra_baby_age_speed_m = char_props.ExtraBabyAgeSpeedMultiplier[
        0].rounded_value

    try:
        data['maturationTime'] = cd(1 / baby_age_speed /
                                    extra_baby_age_speed_m)
    except ZeroDivisionError:
        logger.warning(
            f"Species {char_props.get_source().asset.assetname} tried dividing by zero for its maturationTime"
        )
    data['matingCooldownMin'] = char_props.NewFemaleMinTimeBetweenMating[0]
    data['matingCooldownMax'] = char_props.NewFemaleMaxTimeBetweenMating[0]

    return data
예제 #8
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'] = cd((
            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'] = cd((
            100 / egg_decay /
            extra_egg_decay_m) if egg_decay and extra_egg_decay_m else None)
        data['eggTempMin'] = cf(
            stat_value(fert_egg_props, 'EggMinTemperature', 0))
        data['eggTempMax'] = cf(
            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'] = cd((
        1 / baby_age_speed / extra_baby_age_speed_m
    ) if baby_age_speed and extra_baby_age_speed_m else None)
    data['matingCooldownMin'] = cf(
        stat_value(props, 'NewFemaleMinTimeBetweenMating', 0,
                   FEMALE_MINTIMEBETWEENMATING_DEFAULT))
    data['matingCooldownMax'] = cf(
        stat_value(props, 'NewFemaleMaxTimeBetweenMating', 0,
                   FEMALE_MAXTIMEBETWEENMATING_DEFAULT))

    return data