rpg_base/character_window/src/abilities/content.rs

293 lines
9.3 KiB
Rust

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::{
CharacterWindow,
content::{Content, ContentUpdate},
};
use super::AbilityPage;
impl<A: Ability + 'static> Content<A, AbilityAddon> {
fn show_addon_tooltip(
world: &mut World,
hero: Entity,
addon_index: usize,
reference: &Weak<CharacterWindow>,
(x, y, w, _h): (i32, i32, u32, u32),
) -> Result<()> {
let entity = unsafe { remove_life_time(world.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(world, (target_x, target_y))?;
gui.enable(world)?;
gui.perform_single_check(world.resources.get_mut::<GuiHandler>(), x, y)?;
let window = reference.upgrade().unwrap();
window.add_tooltip(format!("addon_{addon_index}"), gui);
Ok(())
}
fn insert_addon(
world: &mut World,
hero: Entity,
addon_index: usize,
ability_page: &AbilityPage<A>,
) -> Result<()> {
let entity = world.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, world: &mut World, hero: Entity) -> Result<()> {
let reference = self.reference.clone();
self.update_base(world, |world, button, t, index| {
button.set_icon(world.resources.get_mut::<GuiHandler>(), &t.icon())?;
button.set_custom_callback({
let reference = reference.clone();
move |world, controller_button| {
if let ControllerButton::X = controller_button {
CharacterWindow::salvage_from_inventory::<A, _, _>(
world,
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(world)?;
}
return Ok(true);
}
Ok(false)
}
});
button.set_callback({
let reference = reference.clone();
move |world| {
if let Some(menu) = reference.upgrade() {
let mut tabs = menu.tabs_mut();
let abilities = tabs.abilities();
Self::insert_addon(world, hero, index, abilities)?;
abilities.update_page(world)?;
}
Ok(())
}
});
button.set_select_callback({
let weak_button = Arc::downgrade(&button);
let reference = reference.clone();
move |world, selected| {
if selected {
let button_pos = weak_button.upgrade().unwrap().position_extent();
Self::show_addon_tooltip(world, hero, index, &reference, button_pos)?;
} else {
let window = reference.upgrade().unwrap();
window.remove_tooltip(world, format!("addon_{index}"))?;
}
Ok(())
}
});
Ok(())
})
}
fn select(&self, world: &mut World) -> Result<()> {
self.select(world.resources.get_mut::<GuiHandler>())
}
}
impl<A: Ability + 'static> Content<A, AbilityBook<A>> {
fn equip_book(
world: &mut World,
hero: Entity,
book_index: usize,
ability_page: &AbilityPage<A>,
) -> Result<()> {
let entity = world.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(
world: &mut World,
hero: Entity,
book_index: usize,
reference: &Weak<CharacterWindow>,
(x, y, w, _h): (i32, i32, u32, u32),
) -> Result<()> {
let entity = unsafe { remove_life_time(world.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(world, statistics, (target_x, target_y))?;
gui.enable(world)?;
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(world, statistics, (target_x, target_y))?;
compare_gui.enable(world)?;
gui.perform_double_check(
&compare_gui,
world.resources.get_mut::<GuiHandler>(),
x,
2,
)?;
window.add_tooltip("active_book", compare_gui);
}
None => {
gui.perform_single_check(world.resources.get_mut::<GuiHandler>(), 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, world: &mut World, hero: Entity) -> Result<()> {
let reference = self.reference.clone();
self.update_base(world, |world, button, t, index| {
button.set_icon(world.resources.get_mut::<GuiHandler>(), &t.icon())?;
button.set_custom_callback({
let reference = reference.clone();
move |world, controller_button| {
if let ControllerButton::X = controller_button {
CharacterWindow::salvage_from_inventory::<A, _, _>(
world,
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(world)?;
}
return Ok(true);
}
Ok(false)
}
});
button.set_callback({
let reference = reference.clone();
move |world| {
if let Some(menu) = reference.upgrade() {
let mut tabs = menu.tabs_mut();
let abilities = tabs.abilities();
Self::equip_book(world, hero, index, abilities)?;
abilities.update_page(world)?;
}
Ok(())
}
});
button.set_select_callback({
let weak_button = Arc::downgrade(&button);
let reference = reference.clone();
move |world, selected| {
if selected {
let button_pos = weak_button.upgrade().unwrap().position_extent();
Self::show_book_tooltip(world, hero, index, &reference, button_pos)?;
} else {
let window = reference.upgrade().unwrap();
window.remove_tooltip(world, format!("book_{index}"))?;
window.remove_tooltip(world, "active_book")?;
}
Ok(())
}
});
Ok(())
})
}
fn select(&self, world: &mut World) -> Result<()> {
self.select(world.resources.get_mut::<GuiHandler>())
}
}