Module genshin.models.honkai.battlesuit

Honkai battlesuit model.

Classes

class Battlesuit (**data: Any)

Represents a battlesuit without equipment or level.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Expand source code
class Battlesuit(APIModel, Unique):
    """Represents a battlesuit without equipment or level."""

    id: int
    name: str
    rarity: int = Aliased("star")
    closeup_icon_background: str = Aliased("avatar_background_path")
    tall_icon: str = Aliased("figure_path")
    banner_art: str = Aliased("image_path")

    @pydantic.field_validator("tall_icon")
    def __autocomplete_figpath(cls, tall_icon: str, info: pydantic.ValidationInfo) -> str:
        """figure_path is empty for gamemode endpoints, and cannot be inferred from other fields."""
        if tall_icon:
            # might as well just update the BATTLESUIT_IDENTIFIERS if we have the data
            if info.data["id"] not in BATTLESUIT_IDENTIFIERS:
                _LOGGER.debug("Updating BATTLESUIT_IDENTIFIERS with %s", tall_icon)
                BATTLESUIT_IDENTIFIERS[info.data["id"]] = tall_icon.split("/")[-1].split(".")[0]

            return tall_icon

        suit_identifier = BATTLESUIT_IDENTIFIERS.get(info.data["id"])
        return ICON_BASE + f"AvatarTachie/{suit_identifier or 'Unknown'}.png"

    @property
    def character(self) -> str:
        match = re.match(r".*/(\w+C\d+).png", self.tall_icon)
        char_raw = match.group(1) if match else ""

        if "Twin" in char_raw:
            # Rozaliya and Liliya share the same identifier
            return {"TwinC1": "Liliya", "TwinC2": "Rozaliya"}[char_raw]

        # fix mislocalized names
        char_name_raw = char_raw.rsplit("C", 1)[0]
        if char_name_raw == "Fuka":
            return "Fu Hua"

        elif char_name_raw == "Lisushang":
            return "Li Sushang"

        return char_name_raw

    @property
    def rank(self) -> str:
        """Display character rarity with letters ranging from A to SSS, as is done in-game."""
        return ("A", "B", "S", "SS", "SSS")[self.rarity - 1]

    @property
    def _type_cn(self) -> str:
        match = re.match(r".*/Attr(\w+?)(?:Small)?.png", self.closeup_icon_background)
        return match[1] if match else "ShengWu"  # random default just so images keep working

    @property
    def type(self) -> str:
        return BATTLESUIT_TYPES[self._type_cn]

    @property
    def closeup_icon(self) -> str:
        return f"{ICON_BASE}AvatarCardIcons/{60000 + self.id}.png"

    @property
    def icon(self) -> str:
        return f"{ICON_BASE}AvatarIcon/{self.id}.png"

    @property
    def icon_background(self) -> str:
        return f"{ICON_BASE}AvatarIcon/Attr{self._type_cn}.png"

    @property
    def image(self) -> str:
        return f"{ICON_BASE}AvatarCardFigures/{60000 + self.id}.png"

    @property
    def cropped_icon(self) -> str:
        return f"{self.image[:-4]}@1.png"

    @property
    def banner(self) -> str:
        return f"{self.image[:-4]}@2.png"

Ancestors

Subclasses

Class variables

var banner_art : str
var closeup_icon_background : str
var id : int
var model_computed_fields
var model_config : pydantic.config.ConfigDict
var model_fields
var name : str
var rarity : int
var tall_icon : str

Instance variables

prop banner : str
Expand source code
@property
def banner(self) -> str:
    return f"{self.image[:-4]}@2.png"
prop character : str
Expand source code
@property
def character(self) -> str:
    match = re.match(r".*/(\w+C\d+).png", self.tall_icon)
    char_raw = match.group(1) if match else ""

    if "Twin" in char_raw:
        # Rozaliya and Liliya share the same identifier
        return {"TwinC1": "Liliya", "TwinC2": "Rozaliya"}[char_raw]

    # fix mislocalized names
    char_name_raw = char_raw.rsplit("C", 1)[0]
    if char_name_raw == "Fuka":
        return "Fu Hua"

    elif char_name_raw == "Lisushang":
        return "Li Sushang"

    return char_name_raw
prop closeup_icon : str
Expand source code
@property
def closeup_icon(self) -> str:
    return f"{ICON_BASE}AvatarCardIcons/{60000 + self.id}.png"
prop cropped_icon : str
Expand source code
@property
def cropped_icon(self) -> str:
    return f"{self.image[:-4]}@1.png"
prop icon : str
Expand source code
@property
def icon(self) -> str:
    return f"{ICON_BASE}AvatarIcon/{self.id}.png"
prop icon_background : str
Expand source code
@property
def icon_background(self) -> str:
    return f"{ICON_BASE}AvatarIcon/Attr{self._type_cn}.png"
prop image : str
Expand source code
@property
def image(self) -> str:
    return f"{ICON_BASE}AvatarCardFigures/{60000 + self.id}.png"
prop rank : str

Display character rarity with letters ranging from A to SSS, as is done in-game.

Expand source code
@property
def rank(self) -> str:
    """Display character rarity with letters ranging from A to SSS, as is done in-game."""
    return ("A", "B", "S", "SS", "SSS")[self.rarity - 1]
prop type : str
Expand source code
@property
def type(self) -> str:
    return BATTLESUIT_TYPES[self._type_cn]