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)
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
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
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
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
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
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
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