|
@ -1,12 +1,14 @@ |
|
|
use std::convert::TryInto;
|
|
|
use std::convert::TryInto;
|
|
|
use futures::future::join_all;
|
|
|
use futures::future::join_all;
|
|
|
use thiserror::Error;
|
|
|
use thiserror::Error;
|
|
|
|
|
|
use anyhow::Context;
|
|
|
use rand::SeedableRng;
|
|
|
use rand::SeedableRng;
|
|
|
use rand::distributions::{WeightedIndex, Distribution};
|
|
|
use rand::distributions::{WeightedIndex, Distribution};
|
|
|
use crate::entity::gateway::{EntityGateway, GatewayError};
|
|
|
use crate::entity::gateway::{EntityGateway, GatewayError};
|
|
|
use crate::entity::character::CharacterEntity;
|
|
|
|
|
|
|
|
|
use crate::entity::character::{CharacterEntity, TechLevel};
|
|
|
use crate::entity::item::mag::{MagCell, MagCellError};
|
|
|
use crate::entity::item::mag::{MagCell, MagCellError};
|
|
|
use crate::entity::item::tool::{Tool, ToolType};
|
|
|
use crate::entity::item::tool::{Tool, ToolType};
|
|
|
|
|
|
use crate::entity::item::tech::{TechniqueDisk, Technique};
|
|
|
use crate::entity::item::{ItemDetail, ItemEntityId};
|
|
|
use crate::entity::item::{ItemDetail, ItemEntityId};
|
|
|
use crate::ship::items::state::{ItemStateProxy, ItemStateError};
|
|
|
use crate::ship::items::state::{ItemStateProxy, ItemStateError};
|
|
|
use crate::ship::items::inventory::{InventoryItem, InventoryItemDetail};
|
|
|
use crate::ship::items::inventory::{InventoryItem, InventoryItemDetail};
|
|
@ -18,7 +20,7 @@ pub enum ApplyItemError { |
|
|
NoCharacter,
|
|
|
NoCharacter,
|
|
|
#[error("item not equipped")]
|
|
|
#[error("item not equipped")]
|
|
|
ItemNotEquipped,
|
|
|
ItemNotEquipped,
|
|
|
#[error("invalid item")]
|
|
|
|
|
|
|
|
|
#[error("could not use item invalid item")]
|
|
|
InvalidItem,
|
|
|
InvalidItem,
|
|
|
#[error("gateway error {0}")]
|
|
|
#[error("gateway error {0}")]
|
|
|
GatewayError(#[from] GatewayError),
|
|
|
GatewayError(#[from] GatewayError),
|
|
@ -307,6 +309,21 @@ where |
|
|
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async fn apply_tech<'a, EG>(item_state: &mut ItemStateProxy,
|
|
|
|
|
|
entity_gateway: &mut EG,
|
|
|
|
|
|
character: &mut CharacterEntity,
|
|
|
|
|
|
_entity_id: ItemEntityId,
|
|
|
|
|
|
tech: TechniqueDisk)
|
|
|
|
|
|
-> Result<Vec<ApplyItemAction>, anyhow::Error>
|
|
|
|
|
|
where
|
|
|
|
|
|
EG: EntityGateway + ?Sized,
|
|
|
|
|
|
{
|
|
|
|
|
|
// TODO: make sure the class can learn that specific tech
|
|
|
|
|
|
character.techs.set_tech(tech.tech, TechLevel(tech.level as u8));
|
|
|
|
|
|
entity_gateway.save_character(character).await.unwrap();
|
|
|
|
|
|
Ok(vec![ApplyItemAction::UpdateCharacter(Box::new(character.clone()))])
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
pub async fn apply_item<'a, EG>(item_state: &mut ItemStateProxy,
|
|
|
pub async fn apply_item<'a, EG>(item_state: &mut ItemStateProxy,
|
|
|
entity_gateway: &mut EG,
|
|
|
entity_gateway: &mut EG,
|
|
@ -320,7 +337,11 @@ where |
|
|
InventoryItemDetail::Individual(individual_item) => {
|
|
|
InventoryItemDetail::Individual(individual_item) => {
|
|
|
match individual_item.item {
|
|
|
match individual_item.item {
|
|
|
ItemDetail::Tool(tool) => apply_tool(item_state, entity_gateway, character, individual_item.entity_id, tool.tool).await,
|
|
|
ItemDetail::Tool(tool) => apply_tool(item_state, entity_gateway, character, individual_item.entity_id, tool.tool).await,
|
|
|
_ => Err(ApplyItemError::InvalidItem.into())
|
|
|
|
|
|
|
|
|
ItemDetail::TechniqueDisk(tech) => apply_tech(item_state, entity_gateway, character, individual_item.entity_id, tech).await,
|
|
|
|
|
|
_ => Err(anyhow::Error::from(ApplyItemError::InvalidItem))
|
|
|
|
|
|
.with_context(|| {
|
|
|
|
|
|
format!("item {:?}", individual_item)
|
|
|
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
},
|
|
|
InventoryItemDetail::Stacked(stacked_item) => {
|
|
|
InventoryItemDetail::Stacked(stacked_item) => {
|
|
|