rpg_base/character_window/src/abilities/content.rs

307 lines
9.6 KiB
Rust
Raw Normal View History

2025-02-28 07:43:35 +00:00
use std::sync::{Arc, Weak};
use rpg_components::components::ability_slots::AbilitySlots;
use rpg_components::components::inventory::{Inventory, Storable};
use rpg_components::components::statistics::Statistics;
use rpg_components::items::ability_addon::AbilityAddon;
use rpg_components::items::ability_book::AbilityBook;
use crate::*;
use crate::{
content::{Content, ContentUpdate},
CharacterWindow,
};
use super::AbilityPage;
impl<A: Ability + 'static> Content<A, AbilityAddon> {
fn show_addon_tooltip(
engine: &Arc<Engine>,
hero: Entity,
addon_index: usize,
reference: &Weak<CharacterWindow>,
(x, y, w, _h): (i32, i32, u32, u32),
) -> Result<()> {
engine.on_scene(|scene| {
let entity = scene.entity(hero)?;
let inventory = entity.get_component::<Inventory<A>>()?;
let target_x = x + w as i32;
let target_y = y;
let addon = inventory.addon_at(addon_index);
let gui = addon.create_tooltip(engine.gui_handler(), (target_x, target_y))?;
gui.enable()?;
gui.perform_single_check(x, y)?;
let window = reference.upgrade().unwrap();
window.add_tooltip(format!("addon_{addon_index}"), gui);
Ok(())
})
}
fn insert_addon(
engine: &Arc<Engine>,
hero: Entity,
addon_index: usize,
ability_page: &AbilityPage<A>,
) -> Result<()> {
engine.on_scene_mut(|scene| {
let entity = scene.entity_mut(hero)?;
let mut multi_mut = entity.multi_mut();
let inventory = multi_mut.get::<Inventory<A>>()?;
let abilities = multi_mut.get::<AbilitySlots<A>>()?;
if let Some(book) = abilities.book_mut(ability_page.right_side.selected_ability()) {
if book.has_free_addon_slots() {
book.addons_mut()
.insert_addon(inventory.remove_addon(addon_index));
}
}
Ok(())
})
}
}
impl<A: Ability + 'static> ContentUpdate for Content<A, AbilityAddon> {
fn update(&mut self, engine: &Arc<Engine>, hero: Entity) -> Result<()> {
let reference = self.reference.clone();
self.update_base(engine, |button, t, index| {
button.set_icon(&t.icon())?;
button.set_custom_callback({
let engine = engine.clone();
let reference = reference.clone();
move |controller_button| {
if let ControllerButton::X = controller_button {
CharacterWindow::salvage_from_inventory::<A, _, _>(
&engine,
hero,
|inventory| inventory.remove_addon(index),
)?;
if let Some(menu) = reference.upgrade() {
let mut tabs = menu.tabs_mut();
let abilities = tabs.abilities::<A>();
abilities.update_page()?;
}
return Ok(true);
}
Ok(false)
}
});
button.set_callback({
let engine = engine.clone();
let reference = reference.clone();
move || {
if let Some(menu) = reference.upgrade() {
let mut tabs = menu.tabs_mut();
let abilities = tabs.abilities();
Self::insert_addon(&engine, hero, index, abilities)?;
abilities.update_page()?;
}
Ok(())
}
});
button.set_select_callback({
let weak_button = Arc::downgrade(&button);
let engine = engine.clone();
let reference = reference.clone();
move |selected| {
if selected {
let button_pos = weak_button.upgrade().unwrap().position_extent();
Self::show_addon_tooltip(&engine, hero, index, &reference, button_pos)?;
} else {
let window = reference.upgrade().unwrap();
window.remove_tooltip(format!("addon_{index}"));
}
Ok(())
}
});
Ok(())
})
}
fn select(&self) -> Result<()> {
self.select()
}
}
impl<A: Ability + 'static> Content<A, AbilityBook<A>> {
fn equip_book(
engine: &Arc<Engine>,
hero: Entity,
book_index: usize,
ability_page: &AbilityPage<A>,
) -> Result<()> {
engine.on_scene_mut(|scene| {
let entity = scene.entity_mut(hero)?;
let mut multi_mut = entity.multi_mut();
let inventory = multi_mut.get::<Inventory<A>>()?;
let abilitiy_slots = multi_mut.get::<AbilitySlots<A>>()?;
if let Some(old_book) = abilitiy_slots.insert_book(
inventory.remove_book(book_index),
ability_page.right_side.selected_ability(),
) {
inventory.insert_book(old_book, book_index);
}
Ok(())
})
}
fn show_book_tooltip(
engine: &Arc<Engine>,
hero: Entity,
book_index: usize,
reference: &Weak<CharacterWindow>,
(x, y, w, _h): (i32, i32, u32, u32),
) -> Result<()> {
engine.on_scene(|scene| {
let entity = scene.entity(hero)?;
let inventory = entity.get_component::<Inventory<A>>()?;
let statistics = entity.get_component::<Statistics>()?;
let target_x = x + w as i32;
let target_y = y;
let book = inventory.book_at(book_index);
let gui =
book.create_tooltip(engine.gui_handler(), statistics, (target_x, target_y))?;
gui.enable()?;
let window = reference.upgrade().unwrap();
let abilities = entity.get_component::<AbilitySlots<A>>()?;
match abilities.book(window.tabs().abilities::<A>().right_side.selected_ability()) {
Some(selected_book) => {
let button_pos = gui.position_extent();
let target_x = button_pos.0 + button_pos.2 as i32 + 2;
let target_y = button_pos.1;
let compare_gui = selected_book.create_tooltip(
engine.gui_handler(),
statistics,
(target_x, target_y),
)?;
compare_gui.enable()?;
gui.perform_double_check(&compare_gui, x, 2)?;
window.add_tooltip("active_book", compare_gui);
}
None => {
gui.perform_single_check(x, y)?;
}
}
window.add_tooltip(format!("book_{book_index}"), gui);
Ok(())
})
}
}
impl<A: Ability + 'static> ContentUpdate for Content<A, AbilityBook<A>> {
fn update(&mut self, engine: &Arc<Engine>, hero: Entity) -> Result<()> {
let reference = self.reference.clone();
self.update_base(engine, |button, t, index| {
button.set_icon(&t.icon())?;
button.set_custom_callback({
let engine = engine.clone();
let reference = reference.clone();
move |controller_button| {
if let ControllerButton::X = controller_button {
CharacterWindow::salvage_from_inventory::<A, _, _>(
&engine,
hero,
|inventory| inventory.remove_book(index),
)?;
if let Some(menu) = reference.upgrade() {
let mut tabs = menu.tabs_mut();
let abilities = tabs.abilities::<A>();
abilities.update_page()?;
}
return Ok(true);
}
Ok(false)
}
});
button.set_callback({
let engine = engine.clone();
let reference = reference.clone();
move || {
if let Some(menu) = reference.upgrade() {
let mut tabs = menu.tabs_mut();
let abilities = tabs.abilities();
Self::equip_book(&engine, hero, index, abilities)?;
abilities.update_page()?;
}
Ok(())
}
});
button.set_select_callback({
let weak_button = Arc::downgrade(&button);
let engine = engine.clone();
let reference = reference.clone();
move |selected| {
if selected {
let button_pos = weak_button.upgrade().unwrap().position_extent();
Self::show_book_tooltip(&engine, hero, index, &reference, button_pos)?;
} else {
let window = reference.upgrade().unwrap();
window.remove_tooltip(format!("book_{index}"));
window.remove_tooltip("active_book");
}
Ok(())
}
});
Ok(())
})
}
fn select(&self) -> Result<()> {
self.select()
}
}