Add buttons to cast skills in Habitica integration (#126350)
This commit is contained in:
parent
bf63b0993d
commit
39c0826f3c
4 changed files with 307 additions and 3 deletions
|
@ -10,13 +10,18 @@ from typing import Any
|
|||
|
||||
from aiohttp import ClientResponseError
|
||||
|
||||
from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.components.button import (
|
||||
DOMAIN as BUTTON_DOMAIN,
|
||||
ButtonEntity,
|
||||
ButtonEntityDescription,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import ServiceValidationError
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import HabiticaConfigEntry
|
||||
from .const import DOMAIN
|
||||
from .const import ASSETS_URL, DOMAIN, HEALER, MAGE, ROGUE, WARRIOR
|
||||
from .coordinator import HabiticaData, HabiticaDataUpdateCoordinator
|
||||
from .entity import HabiticaBase
|
||||
|
||||
|
@ -27,6 +32,8 @@ class HabiticaButtonEntityDescription(ButtonEntityDescription):
|
|||
|
||||
press_fn: Callable[[HabiticaDataUpdateCoordinator], Any]
|
||||
available_fn: Callable[[HabiticaData], bool] | None = None
|
||||
class_needed: str | None = None
|
||||
entity_picture: str | None = None
|
||||
|
||||
|
||||
class HabitipyButtonEntity(StrEnum):
|
||||
|
@ -36,6 +43,18 @@ class HabitipyButtonEntity(StrEnum):
|
|||
BUY_HEALTH_POTION = "buy_health_potion"
|
||||
ALLOCATE_ALL_STAT_POINTS = "allocate_all_stat_points"
|
||||
REVIVE = "revive"
|
||||
MPHEAL = "mpheal"
|
||||
EARTH = "earth"
|
||||
FROST = "frost"
|
||||
DEFENSIVE_STANCE = "defensive_stance"
|
||||
VALOROUS_PRESENCE = "valorous_presence"
|
||||
INTIMIDATE = "intimidate"
|
||||
TOOLS_OF_TRADE = "tools_of_trade"
|
||||
STEALTH = "stealth"
|
||||
HEAL = "heal"
|
||||
PROTECT_AURA = "protect_aura"
|
||||
BRIGHTNESS = "brightness"
|
||||
HEAL_ALL = "heal_all"
|
||||
|
||||
|
||||
BUTTON_DESCRIPTIONS: tuple[HabiticaButtonEntityDescription, ...] = (
|
||||
|
@ -74,6 +93,173 @@ BUTTON_DESCRIPTIONS: tuple[HabiticaButtonEntityDescription, ...] = (
|
|||
)
|
||||
|
||||
|
||||
CLASS_SKILLS: tuple[HabiticaButtonEntityDescription, ...] = (
|
||||
HabiticaButtonEntityDescription(
|
||||
key=HabitipyButtonEntity.MPHEAL,
|
||||
translation_key=HabitipyButtonEntity.MPHEAL,
|
||||
press_fn=lambda coordinator: coordinator.api.user.class_.cast["mpheal"].post(),
|
||||
available_fn=(
|
||||
lambda data: data.user["stats"]["lvl"] >= 12
|
||||
and data.user["stats"]["mp"] >= 30
|
||||
),
|
||||
class_needed=MAGE,
|
||||
entity_picture="shop_mpheal.png",
|
||||
),
|
||||
HabiticaButtonEntityDescription(
|
||||
key=HabitipyButtonEntity.EARTH,
|
||||
translation_key=HabitipyButtonEntity.EARTH,
|
||||
press_fn=lambda coordinator: coordinator.api.user.class_.cast["earth"].post(),
|
||||
available_fn=(
|
||||
lambda data: data.user["stats"]["lvl"] >= 13
|
||||
and data.user["stats"]["mp"] >= 35
|
||||
),
|
||||
class_needed=MAGE,
|
||||
entity_picture="shop_earth.png",
|
||||
),
|
||||
HabiticaButtonEntityDescription(
|
||||
key=HabitipyButtonEntity.FROST,
|
||||
translation_key=HabitipyButtonEntity.FROST,
|
||||
press_fn=(
|
||||
lambda coordinator: coordinator.api.user.class_.cast["frost"].post(
|
||||
targetId=coordinator.config_entry.unique_id
|
||||
)
|
||||
),
|
||||
available_fn=(
|
||||
lambda data: data.user["stats"]["lvl"] >= 14
|
||||
and data.user["stats"]["mp"] >= 40
|
||||
),
|
||||
class_needed=MAGE,
|
||||
entity_picture="shop_frost.png",
|
||||
),
|
||||
HabiticaButtonEntityDescription(
|
||||
key=HabitipyButtonEntity.DEFENSIVE_STANCE,
|
||||
translation_key=HabitipyButtonEntity.DEFENSIVE_STANCE,
|
||||
press_fn=(
|
||||
lambda coordinator: coordinator.api.user.class_.cast[
|
||||
"defensiveStance"
|
||||
].post(targetId=coordinator.config_entry.unique_id)
|
||||
),
|
||||
available_fn=(
|
||||
lambda data: data.user["stats"]["lvl"] >= 12
|
||||
and data.user["stats"]["mp"] >= 25
|
||||
),
|
||||
class_needed=WARRIOR,
|
||||
entity_picture="shop_defensiveStance.png",
|
||||
),
|
||||
HabiticaButtonEntityDescription(
|
||||
key=HabitipyButtonEntity.VALOROUS_PRESENCE,
|
||||
translation_key=HabitipyButtonEntity.VALOROUS_PRESENCE,
|
||||
press_fn=(
|
||||
lambda coordinator: coordinator.api.user.class_.cast[
|
||||
"valorousPresence"
|
||||
].post(targetId=coordinator.config_entry.unique_id)
|
||||
),
|
||||
available_fn=(
|
||||
lambda data: data.user["stats"]["lvl"] >= 13
|
||||
and data.user["stats"]["mp"] >= 20
|
||||
),
|
||||
class_needed=WARRIOR,
|
||||
entity_picture="shop_valorousPresence.png",
|
||||
),
|
||||
HabiticaButtonEntityDescription(
|
||||
key=HabitipyButtonEntity.INTIMIDATE,
|
||||
translation_key=HabitipyButtonEntity.INTIMIDATE,
|
||||
press_fn=(
|
||||
lambda coordinator: coordinator.api.user.class_.cast["intimidate"].post(
|
||||
targetId=coordinator.config_entry.unique_id
|
||||
)
|
||||
),
|
||||
available_fn=(
|
||||
lambda data: data.user["stats"]["lvl"] >= 14
|
||||
and data.user["stats"]["mp"] >= 15
|
||||
),
|
||||
class_needed=WARRIOR,
|
||||
entity_picture="shop_intimidate.png",
|
||||
),
|
||||
HabiticaButtonEntityDescription(
|
||||
key=HabitipyButtonEntity.TOOLS_OF_TRADE,
|
||||
translation_key=HabitipyButtonEntity.TOOLS_OF_TRADE,
|
||||
press_fn=(
|
||||
lambda coordinator: coordinator.api.user.class_.cast["toolsOfTrade"].post()
|
||||
),
|
||||
available_fn=(
|
||||
lambda data: data.user["stats"]["lvl"] >= 13
|
||||
and data.user["stats"]["mp"] >= 25
|
||||
),
|
||||
class_needed=ROGUE,
|
||||
entity_picture="shop_toolsOfTrade.png",
|
||||
),
|
||||
HabiticaButtonEntityDescription(
|
||||
key=HabitipyButtonEntity.STEALTH,
|
||||
translation_key=HabitipyButtonEntity.STEALTH,
|
||||
press_fn=(
|
||||
lambda coordinator: coordinator.api.user.class_.cast["stealth"].post(
|
||||
targetId=coordinator.config_entry.unique_id
|
||||
)
|
||||
),
|
||||
available_fn=(
|
||||
lambda data: data.user["stats"]["lvl"] >= 14
|
||||
and data.user["stats"]["mp"] >= 45
|
||||
),
|
||||
class_needed=ROGUE,
|
||||
entity_picture="shop_stealth.png",
|
||||
),
|
||||
HabiticaButtonEntityDescription(
|
||||
key=HabitipyButtonEntity.HEAL,
|
||||
translation_key=HabitipyButtonEntity.HEAL,
|
||||
press_fn=(
|
||||
lambda coordinator: coordinator.api.user.class_.cast["heal"].post(
|
||||
targetId=coordinator.config_entry.unique_id
|
||||
)
|
||||
),
|
||||
available_fn=(
|
||||
lambda data: data.user["stats"]["lvl"] >= 11
|
||||
and data.user["stats"]["mp"] >= 15
|
||||
),
|
||||
class_needed=HEALER,
|
||||
),
|
||||
HabiticaButtonEntityDescription(
|
||||
key=HabitipyButtonEntity.BRIGHTNESS,
|
||||
translation_key=HabitipyButtonEntity.BRIGHTNESS,
|
||||
press_fn=(
|
||||
lambda coordinator: coordinator.api.user.class_.cast["brightness"].post(
|
||||
targetId=coordinator.config_entry.unique_id
|
||||
)
|
||||
),
|
||||
available_fn=(
|
||||
lambda data: data.user["stats"]["lvl"] >= 12
|
||||
and data.user["stats"]["mp"] >= 15
|
||||
),
|
||||
class_needed=HEALER,
|
||||
entity_picture="shop_brightness.png",
|
||||
),
|
||||
HabiticaButtonEntityDescription(
|
||||
key=HabitipyButtonEntity.PROTECT_AURA,
|
||||
translation_key=HabitipyButtonEntity.PROTECT_AURA,
|
||||
press_fn=(
|
||||
lambda coordinator: coordinator.api.user.class_.cast["protectAura"].post()
|
||||
),
|
||||
available_fn=(
|
||||
lambda data: data.user["stats"]["lvl"] >= 13
|
||||
and data.user["stats"]["mp"] >= 30
|
||||
),
|
||||
class_needed=HEALER,
|
||||
entity_picture="shop_protectAura.png",
|
||||
),
|
||||
HabiticaButtonEntityDescription(
|
||||
key=HabitipyButtonEntity.HEAL_ALL,
|
||||
translation_key=HabitipyButtonEntity.HEAL_ALL,
|
||||
press_fn=lambda coordinator: coordinator.api.user.class_.cast["healAll"].post(),
|
||||
available_fn=(
|
||||
lambda data: data.user["stats"]["lvl"] >= 14
|
||||
and data.user["stats"]["mp"] >= 25
|
||||
),
|
||||
class_needed=HEALER,
|
||||
entity_picture="shop_healAll.png",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
entry: HabiticaConfigEntry,
|
||||
|
@ -82,6 +268,40 @@ async def async_setup_entry(
|
|||
"""Set up buttons from a config entry."""
|
||||
|
||||
coordinator = entry.runtime_data
|
||||
skills_added: set[str] = set()
|
||||
|
||||
@callback
|
||||
def add_entities() -> None:
|
||||
"""Add or remove a skillset based on the player's class."""
|
||||
|
||||
nonlocal skills_added
|
||||
buttons = []
|
||||
entity_registry = er.async_get(hass)
|
||||
|
||||
for description in CLASS_SKILLS:
|
||||
if (
|
||||
coordinator.data.user["stats"]["lvl"] >= 10
|
||||
and coordinator.data.user["flags"]["classSelected"]
|
||||
and not coordinator.data.user["preferences"]["disableClasses"]
|
||||
and description.class_needed == coordinator.data.user["stats"]["class"]
|
||||
):
|
||||
if description.key not in skills_added:
|
||||
buttons.append(HabiticaButton(coordinator, description))
|
||||
skills_added.add(description.key)
|
||||
elif description.key in skills_added:
|
||||
if entity_id := entity_registry.async_get_entity_id(
|
||||
BUTTON_DOMAIN,
|
||||
DOMAIN,
|
||||
f"{coordinator.config_entry.unique_id}_{description.key}",
|
||||
):
|
||||
entity_registry.async_remove(entity_id)
|
||||
skills_added.remove(description.key)
|
||||
|
||||
if buttons:
|
||||
async_add_entities(buttons)
|
||||
|
||||
coordinator.async_add_listener(add_entities)
|
||||
add_entities()
|
||||
|
||||
async_add_entities(
|
||||
HabiticaButton(coordinator, description) for description in BUTTON_DESCRIPTIONS
|
||||
|
@ -123,3 +343,10 @@ class HabiticaButton(HabiticaBase, ButtonEntity):
|
|||
if self.entity_description.available_fn:
|
||||
return self.entity_description.available_fn(self.coordinator.data)
|
||||
return True
|
||||
|
||||
@property
|
||||
def entity_picture(self) -> str | None:
|
||||
"""Return the entity picture to use in the frontend, if any."""
|
||||
if entity_picture := self.entity_description.entity_picture:
|
||||
return f"{ASSETS_URL}{entity_picture}"
|
||||
return None
|
||||
|
|
|
@ -27,4 +27,9 @@ ATTR_SKILL = "skill"
|
|||
ATTR_TASK = "task"
|
||||
SERVICE_CAST_SKILL = "cast_skill"
|
||||
|
||||
WARRIOR = "warrior"
|
||||
ROGUE = "rogue"
|
||||
HEALER = "healer"
|
||||
MAGE = "wizard"
|
||||
|
||||
DEVELOPER_ID = "4c4ca53f-c059-4ffa-966e-9d29dd405daf"
|
||||
|
|
|
@ -20,6 +20,42 @@
|
|||
},
|
||||
"revive": {
|
||||
"default": "mdi:grave-stone"
|
||||
},
|
||||
"mpheal": {
|
||||
"default": "mdi:broadcast"
|
||||
},
|
||||
"earth": {
|
||||
"default": "mdi:landslide"
|
||||
},
|
||||
"frost": {
|
||||
"default": "mdi:snowflake"
|
||||
},
|
||||
"defensive_stance": {
|
||||
"default": "mdi:shield-sword"
|
||||
},
|
||||
"valorous_presence": {
|
||||
"default": "mdi:shield-sun"
|
||||
},
|
||||
"intimidate": {
|
||||
"default": "mdi:emoticon-angry"
|
||||
},
|
||||
"tools_of_trade": {
|
||||
"default": "mdi:domino-mask"
|
||||
},
|
||||
"stealth": {
|
||||
"default": "mdi:ninja"
|
||||
},
|
||||
"heal": {
|
||||
"default": "mdi:aurora"
|
||||
},
|
||||
"brightness": {
|
||||
"default": "mdi:flare"
|
||||
},
|
||||
"protect_aura": {
|
||||
"default": "mdi:shimmer"
|
||||
},
|
||||
"heal_all": {
|
||||
"default": "mdi:hand-heart-outline"
|
||||
}
|
||||
},
|
||||
"sensor": {
|
||||
|
|
|
@ -46,6 +46,42 @@
|
|||
},
|
||||
"revive": {
|
||||
"name": "Revive from death"
|
||||
},
|
||||
"mpheal": {
|
||||
"name": "Ethereal surge"
|
||||
},
|
||||
"earth": {
|
||||
"name": "Earthquake"
|
||||
},
|
||||
"frost": {
|
||||
"name": "Chilling frost"
|
||||
},
|
||||
"defensive_stance": {
|
||||
"name": "Defensive stance"
|
||||
},
|
||||
"valorous_presence": {
|
||||
"name": "Valorous presence"
|
||||
},
|
||||
"intimidate": {
|
||||
"name": "Intimidating gaze"
|
||||
},
|
||||
"tools_of_trade": {
|
||||
"name": "Tools of the trade"
|
||||
},
|
||||
"stealth": {
|
||||
"name": "Stealth"
|
||||
},
|
||||
"heal": {
|
||||
"name": "Healing light"
|
||||
},
|
||||
"brightness": {
|
||||
"name": "Searing brightness"
|
||||
},
|
||||
"protect_aura": {
|
||||
"name": "Protective aura"
|
||||
},
|
||||
"heal_all": {
|
||||
"name": "Blessing"
|
||||
}
|
||||
},
|
||||
"sensor": {
|
||||
|
|
Loading…
Add table
Reference in a new issue