rpg_base/character_window/src/abilities/ability_right_side.rs

296 lines
10 KiB
Rust
Raw Normal View History

2025-02-28 07:43:35 +00:00
use std::marker::PhantomData;
use std::sync::{Arc, Weak};
use rpg_components::components::ability_slots::AbilitySlots;
use rpg_components::components::crafting_materials::CraftingMaterials;
use rpg_components::components::inventory::Storable;
use rpg_components::components::statistics::Statistics;
use rpg_components::config::items::ItemSettings;
use rpg_components::items::Rarities;
use crate::*;
2025-03-04 17:40:56 +00:00
use crate::{CharacterWindow, traits::RightSide};
2025-02-28 07:43:35 +00:00
pub struct AbilityPageRightSide<A: Ability + 'static> {
snippet: Arc<GuiSnippet>,
ability_index: usize,
ability_marker: PhantomData<A>,
}
impl<A: Ability + 'static> AbilityPageRightSide<A> {
const ABILITY_BUTTON_NAMES: [&'static str; 4] = [
"first_ability",
"second_ability",
"third_ability",
"fourth_ability",
];
2025-03-05 09:31:16 +00:00
pub fn new(world: &mut World, hero: Entity, reference: &Weak<CharacterWindow>) -> Result<Self> {
2025-02-28 07:43:35 +00:00
let snippet = GuiSnippet::from_str(
2025-03-05 09:31:16 +00:00
world,
2025-02-28 07:43:35 +00:00
include_str!("../../resources/abilities/right_side.xml"),
)?;
2025-03-05 09:31:16 +00:00
let mut resources = world.resources.multi_mut();
let gui_handler = resources.get::<GuiHandler>();
let engine_settings = resources.get::<EngineSettings>();
let context = resources.get::<Context>();
2025-02-28 07:43:35 +00:00
2025-03-05 09:31:16 +00:00
let color_settings = resources
.get::<ItemSettings>()
.rarity_color_settings
.clone();
Self::rarity_icon_background(gui_handler, &snippet, "common", color_settings.common)?;
Self::rarity_icon_background(gui_handler, &snippet, "uncommon", color_settings.uncommon)?;
Self::rarity_icon_background(gui_handler, &snippet, "magical", color_settings.magical)?;
Self::rarity_icon_background(gui_handler, &snippet, "rare", color_settings.rare)?;
Self::rarity_icon_background(gui_handler, &snippet, "epic", color_settings.epic)?;
Self::rarity_icon_background(gui_handler, &snippet, "legendary", color_settings.legendary)?;
2025-02-28 07:43:35 +00:00
for (index, name) in Self::ABILITY_BUTTON_NAMES.iter().enumerate() {
let button: Arc<Button> = snippet.element(name)?;
2025-03-05 09:31:16 +00:00
button.set_info_icon(
gui_handler,
&engine_settings.controller_icon(context, ControllerButton::RightStick)?,
)?;
2025-02-28 07:43:35 +00:00
button.set_callback({
2025-03-05 09:31:16 +00:00
let reference = reference.clone();
move |world: &mut World| {
2025-02-28 07:43:35 +00:00
if let Some(menu) = reference.upgrade() {
let mut tabs = menu.tabs_mut();
let abilities = tabs.abilities::<A>();
abilities.right_side.ability_index = index;
2025-03-05 09:31:16 +00:00
abilities.update_page(world)?;
2025-02-28 07:43:35 +00:00
}
Ok(())
}
});
button.set_select_callback({
let reference = reference.clone();
let weak_button = Arc::downgrade(&button);
2025-03-05 09:31:16 +00:00
move |world, selected| {
2025-02-28 07:43:35 +00:00
if let Some(menu) = reference.upgrade() {
if selected {
2025-03-05 09:31:16 +00:00
let entity = unsafe { remove_life_time(world.entity(hero)?) };
let abilities = entity.get_component::<AbilitySlots<A>>()?;
2025-02-28 07:43:35 +00:00
2025-03-05 09:31:16 +00:00
if let Some(book) = abilities.book(index) {
let button = weak_button.upgrade().unwrap();
let button_pos = button.position_extent();
2025-02-28 07:43:35 +00:00
2025-03-05 09:31:16 +00:00
let target_x = button_pos.0 + button_pos.2 as i32;
let target_y = button_pos.1;
2025-02-28 07:43:35 +00:00
2025-03-05 09:31:16 +00:00
let statistics = entity.get_component::<Statistics>()?;
2025-02-28 07:43:35 +00:00
2025-03-05 09:31:16 +00:00
let gui =
book.create_tooltip(world, statistics, (target_x, target_y))?;
gui.enable(world)?;
gui.perform_single_check(
world.resources.get_mut::<GuiHandler>(),
button_pos.0,
button_pos.1,
)?;
2025-02-28 07:43:35 +00:00
2025-03-05 09:31:16 +00:00
menu.add_tooltip("active_ability", gui);
}
2025-02-28 07:43:35 +00:00
} else {
2025-03-06 16:30:50 +00:00
menu.remove_tooltip(world, "active_ability")?;
2025-02-28 07:43:35 +00:00
}
}
Ok(())
}
});
button.set_custom_callback({
let reference = reference.clone();
2025-03-05 09:31:16 +00:00
move |world, button| match button {
2025-02-28 07:43:35 +00:00
ControllerButton::Y => {
2025-03-05 09:31:16 +00:00
let entity = world.entity_mut(hero)?;
let mut multi_mut = entity.multi_mut();
2025-02-28 07:43:35 +00:00
2025-03-05 09:31:16 +00:00
let abilities = multi_mut.get::<AbilitySlots<A>>()?;
2025-02-28 07:43:35 +00:00
2025-03-05 09:31:16 +00:00
if let Some(ability) = abilities.book_mut(index) {
let materials = multi_mut.get::<CraftingMaterials>()?;
2025-02-28 07:43:35 +00:00
2025-03-05 09:31:16 +00:00
ability.upgrade(materials);
2025-02-28 07:43:35 +00:00
2025-03-05 09:31:16 +00:00
if let Some(menu) = reference.upgrade() {
menu.tabs_mut()
.abilities::<A>()
.right_side
.refresh(world, hero)?;
2025-02-28 07:43:35 +00:00
}
2025-03-05 09:31:16 +00:00
}
2025-02-28 07:43:35 +00:00
Ok(true)
}
_ => Ok(false),
}
})
}
Ok(Self {
snippet,
ability_index: 0,
ability_marker: PhantomData,
})
}
pub fn selected_ability(&self) -> usize {
self.ability_index
}
2025-03-05 09:31:16 +00:00
fn rarity_icon_background(
gui_handler: &mut GuiHandler,
gui: &GuiSnippet,
element: &str,
color: Color,
) -> Result<()> {
2025-02-28 07:43:35 +00:00
let icon: Arc<Icon> = gui.element(element)?;
2025-03-05 09:31:16 +00:00
icon.set_background(
gui_handler,
FillTypeInfo::Element(
ElementDescriptor::new(color, Color::Black, 2),
DisplayableFillType::Square,
),
)
2025-02-28 07:43:35 +00:00
}
2025-03-05 09:31:16 +00:00
fn update_crafting_count(
&self,
gui_handler: &mut GuiHandler,
element: &str,
value: u32,
) -> Result<()> {
2025-02-28 07:43:35 +00:00
let icon: Arc<Icon> = self.snippet.element(element)?;
2025-03-05 09:31:16 +00:00
icon.set_text(gui_handler, value)?;
2025-02-28 07:43:35 +00:00
Ok(())
}
2025-03-05 09:31:16 +00:00
fn update_ability_icon(
&self,
gui_handler: &mut GuiHandler,
element: &str,
image: Option<Arc<Image>>,
) -> Result<()> {
2025-02-28 07:43:35 +00:00
let button: Arc<Button> = self.snippet.element(element)?;
match image {
Some(image) => {
2025-03-05 09:31:16 +00:00
button.set_icon(gui_handler, &image)?;
2025-02-28 07:43:35 +00:00
}
None => {
2025-03-05 09:31:16 +00:00
button.clear_icon(gui_handler)?;
2025-02-28 07:43:35 +00:00
}
}
Ok(())
}
2025-03-05 09:31:16 +00:00
fn update_active_ability(&self, world: &mut World, abilities: &AbilitySlots<A>) -> Result<()> {
2025-02-28 07:43:35 +00:00
let grid: Arc<Grid> = self.snippet.element("ability_content")?;
let (_, rows) = grid.dimensions();
for y in 0..rows {
2025-03-05 09:31:16 +00:00
grid.detach(world, 0, y)?;
2025-02-28 07:43:35 +00:00
}
if let Some(ability) = abilities.book(self.ability_index) {
for (index, addon) in ability.addons().iter().enumerate() {
match addon.as_ref() {
Some(addon) => {
let addon_type_snippet = GuiSnippet::from_str(
2025-03-05 09:31:16 +00:00
world,
2025-02-28 07:43:35 +00:00
include_str!("../../resources/abilities/addon_type_snippet.xml"),
)?;
let addon_icon: Arc<Icon> = addon_type_snippet.element("addon_icon")?;
let addon_type: Arc<Label> = addon_type_snippet.element("addon_type")?;
let addon_value: Arc<Label> = addon_type_snippet.element("addon_value")?;
2025-03-05 09:31:16 +00:00
let gui_handler = world.resources.get_mut::<GuiHandler>();
addon_icon.set_icon(gui_handler, &addon.icon())?;
addon_type.set_text(gui_handler, &format!("{}", addon.addon_type()))?;
addon_value.set_text(gui_handler, &addon.addon_type().val_as_str())?;
2025-02-28 07:43:35 +00:00
2025-03-05 09:31:16 +00:00
grid.attach(world, addon_type_snippet, 0, index, 1, 1)?;
2025-02-28 07:43:35 +00:00
}
None => {
let empty_addon = GuiSnippet::from_str(
2025-03-05 09:31:16 +00:00
world,
2025-02-28 07:43:35 +00:00
include_str!("../../resources/abilities/empty_addon_snippet.xml"),
)?;
2025-03-05 09:31:16 +00:00
grid.attach(world, empty_addon, 0, index, 1, 1)?;
2025-02-28 07:43:35 +00:00
}
}
}
}
Ok(())
}
2025-03-05 09:31:16 +00:00
pub fn next_ability(&mut self, world: &mut World, hero: Entity) -> Result<()> {
2025-02-28 07:43:35 +00:00
self.ability_index = (self.ability_index + 1) % 4;
2025-03-05 09:31:16 +00:00
self.refresh(world, hero)
2025-02-28 07:43:35 +00:00
}
}
impl<A: Ability + 'static> RightSide for AbilityPageRightSide<A> {
2025-03-05 09:31:16 +00:00
fn refresh(&mut self, world: &mut World, hero: Entity) -> Result<()> {
let entity = unsafe { remove_life_time(world.entity(hero)?) };
let crafting = entity.get_component::<CraftingMaterials>()?;
let gui_handler = world.resources.get_mut::<GuiHandler>();
self.update_crafting_count(gui_handler, "common", crafting.count(Rarities::Common))?;
self.update_crafting_count(gui_handler, "uncommon", crafting.count(Rarities::Uncommon))?;
self.update_crafting_count(gui_handler, "magical", crafting.count(Rarities::Magical))?;
self.update_crafting_count(gui_handler, "rare", crafting.count(Rarities::Rare))?;
self.update_crafting_count(gui_handler, "epic", crafting.count(Rarities::Epic))?;
self.update_crafting_count(
gui_handler,
"legendary",
crafting.count(Rarities::Legendary),
)?;
2025-02-28 07:43:35 +00:00
2025-03-05 09:31:16 +00:00
let abilities = entity.get_component::<AbilitySlots<A>>()?;
2025-02-28 07:43:35 +00:00
2025-03-05 09:31:16 +00:00
for (index, name) in Self::ABILITY_BUTTON_NAMES.iter().enumerate() {
self.update_ability_icon(
gui_handler,
name,
abilities.book(index).map(|book| book.icon()),
)?;
}
2025-02-28 07:43:35 +00:00
2025-03-05 09:31:16 +00:00
self.update_active_ability(world, abilities)?;
2025-02-28 07:43:35 +00:00
2025-03-05 09:31:16 +00:00
Ok(())
2025-02-28 07:43:35 +00:00
}
fn base(&self) -> &Arc<GuiSnippet> {
&self.snippet
}
}