Merge pull request 'mag feeding!' (#207) from mag_feeding into master
This commit is contained in:
commit
b0be92cb50
@ -28,4 +28,5 @@ derive_more = { version = "0.99.3", features = ["display"]}
|
||||
thiserror = "1.0.15"
|
||||
ages-prs = "0.1"
|
||||
async-trait = "0.1.31"
|
||||
lazy_static = "1.4.0"
|
||||
|
||||
|
@ -6,96 +6,124 @@ feed_table = 1
|
||||
|
||||
[Mitra]
|
||||
feed_table = 3
|
||||
photon_blast = "Pilla"
|
||||
|
||||
[Surya]
|
||||
feed_table = 3
|
||||
photon_blast = "Leilla"
|
||||
|
||||
[Vayu]
|
||||
feed_table = 4
|
||||
photon_blast = "MyllaYoulla"
|
||||
|
||||
[Varaha]
|
||||
feed_table = 4
|
||||
photon_blast = "Leilla"
|
||||
|
||||
[Kama]
|
||||
feed_table = 4
|
||||
photon_blast = "Pilla"
|
||||
|
||||
[Ushasu]
|
||||
feed_table = 4
|
||||
photon_blast = "Leilla"
|
||||
|
||||
[Apsaras]
|
||||
feed_table = 4
|
||||
photon_blast = "Estlla"
|
||||
|
||||
[Kumara]
|
||||
feed_table = 4
|
||||
photon_blast = "Leilla"
|
||||
|
||||
[Kaitabha]
|
||||
feed_table = 4
|
||||
photon_blast = "MyllaYoulla"
|
||||
|
||||
[Tapas]
|
||||
feed_table = 3
|
||||
photon_blast = "MyllaYoulla"
|
||||
|
||||
[Bhirava]
|
||||
feed_table = 4
|
||||
photon_blast = "Pilla"
|
||||
|
||||
[Kalki]
|
||||
feed_table = 1
|
||||
photon_blast = "Estlla"
|
||||
|
||||
[Rudra]
|
||||
feed_table = 2
|
||||
photon_blast = "Leilla"
|
||||
|
||||
[Marutah]
|
||||
feed_table = 2
|
||||
photon_blast = "Pilla"
|
||||
|
||||
[Yaksa]
|
||||
feed_table = 5
|
||||
photon_blast = "Leilla"
|
||||
|
||||
[Sita]
|
||||
feed_table = 5
|
||||
photon_blast = "Pilla"
|
||||
|
||||
[Garuda]
|
||||
feed_table = 5
|
||||
photon_blast = "Pilla"
|
||||
|
||||
[Nandin]
|
||||
feed_table = 5
|
||||
photon_blast = "Estlla"
|
||||
|
||||
[Ashvinau]
|
||||
feed_table = 2
|
||||
photon_blast = "Pilla"
|
||||
|
||||
[Ribhava]
|
||||
feed_table = 5
|
||||
|
||||
[Soma]
|
||||
feed_table = 5
|
||||
photon_blast = "Estlla"
|
||||
|
||||
[Ila]
|
||||
feed_table = 5
|
||||
photon_blast = "MyllaYoulla"
|
||||
|
||||
[Durga]
|
||||
feed_table = 5
|
||||
photon_blast = "Estlla"
|
||||
|
||||
[Vritra]
|
||||
feed_table = 1
|
||||
photon_blast = "Golla"
|
||||
|
||||
[Namuci]
|
||||
feed_table = 2
|
||||
photon_blast = "MyllaYoulla"
|
||||
|
||||
[Sumba]
|
||||
feed_table = 2
|
||||
photon_blast = "Leilla"
|
||||
|
||||
[Naga]
|
||||
feed_table = 6
|
||||
photon_blast = "MyllaYoulla"
|
||||
|
||||
[Pitri]
|
||||
feed_table = 7
|
||||
|
||||
[Kabanda]
|
||||
feed_table = 6
|
||||
photon_blast = "MyllaYoulla"
|
||||
|
||||
[Ravana]
|
||||
feed_table = 6
|
||||
|
||||
[Marica]
|
||||
feed_table = 6
|
||||
photon_blast = "Pilla"
|
||||
|
||||
[Soniti]
|
||||
feed_table = 7
|
||||
@ -105,15 +133,19 @@ feed_table = 7
|
||||
|
||||
[Andhaka]
|
||||
feed_table = 6
|
||||
photon_blast = "Estlla"
|
||||
|
||||
[Bana]
|
||||
feed_table = 6
|
||||
photon_blast = "Estlla"
|
||||
|
||||
[Naraka]
|
||||
feed_table = 6
|
||||
photon_blast = "Leilla"
|
||||
|
||||
[Madhu]
|
||||
feed_table = 6
|
||||
photon_blast = "MyllaYoulla"
|
||||
|
||||
[Churel]
|
||||
feed_table = 7
|
||||
|
@ -7,7 +7,7 @@ use libpso::character::character::{DEFAULT_PALETTE_CONFIG, DEFAULT_TECH_MENU};
|
||||
use crate::entity::item::tech::Technique;
|
||||
use crate::entity::account::UserAccountId;
|
||||
|
||||
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||
pub enum CharacterClass {
|
||||
HUmar,
|
||||
HUnewearl,
|
||||
@ -64,7 +64,7 @@ impl Into<u8> for CharacterClass {
|
||||
}
|
||||
|
||||
|
||||
#[derive(Copy, Clone, Hash, PartialEq, Eq, derive_more::Display)]
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, derive_more::Display)]
|
||||
pub enum SectionID {
|
||||
Viridia,
|
||||
Greenill,
|
||||
|
@ -60,6 +60,18 @@ pub trait EntityGateway: Send + Sync + Clone {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
async fn feed_mag(&mut self, _mag_item_id: &ItemEntityId, _tool_item_id: &ItemEntityId) {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
async fn change_mag_owner(&mut self, _mag_item_id: &ItemEntityId, _character: &CharacterEntity) {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
async fn use_mag_cell(&mut self, _mag_item_id: &ItemEntityId, _mag_cell_id: &ItemEntityId) {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
async fn get_items_by_character(&self, _char: &CharacterEntity) -> Vec<ItemEntity> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::convert::TryInto;
|
||||
|
||||
use crate::entity::account::*;
|
||||
use crate::entity::character::*;
|
||||
@ -13,6 +14,7 @@ pub struct InMemoryGateway {
|
||||
user_settings: Arc<Mutex<BTreeMap<UserSettingsId, UserSettingsEntity>>>,
|
||||
characters: Arc<Mutex<BTreeMap<CharacterEntityId, CharacterEntity>>>,
|
||||
items: Arc<Mutex<BTreeMap<ItemEntityId, ItemEntity>>>,
|
||||
mag_modifiers: Arc<Mutex<BTreeMap<ItemEntityId, Vec<mag::MagModifier>>>>,
|
||||
}
|
||||
|
||||
impl InMemoryGateway {
|
||||
@ -22,6 +24,7 @@ impl InMemoryGateway {
|
||||
user_settings: Arc::new(Mutex::new(BTreeMap::new())),
|
||||
characters: Arc::new(Mutex::new(BTreeMap::new())),
|
||||
items: Arc::new(Mutex::new(BTreeMap::new())),
|
||||
mag_modifiers: Arc::new(Mutex::new(BTreeMap::new())),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -165,6 +168,29 @@ impl EntityGateway for InMemoryGateway {
|
||||
});
|
||||
}
|
||||
|
||||
async fn feed_mag(&mut self, mag_item_id: &ItemEntityId, tool_item_id: &ItemEntityId) {
|
||||
self.mag_modifiers.lock().unwrap()
|
||||
.entry(*mag_item_id)
|
||||
.or_insert(Vec::new())
|
||||
.push(mag::MagModifier::FeedMag {
|
||||
food: *tool_item_id
|
||||
});
|
||||
}
|
||||
|
||||
async fn change_mag_owner(&mut self, mag_item_id: &ItemEntityId, character: &CharacterEntity) {
|
||||
self.mag_modifiers.lock().unwrap()
|
||||
.entry(*mag_item_id)
|
||||
.or_insert(Vec::new())
|
||||
.push(mag::MagModifier::OwnerChange(character.char_class, character.section_id));
|
||||
}
|
||||
|
||||
async fn use_mag_cell(&mut self, mag_item_id: &ItemEntityId, mag_cell_id: &ItemEntityId) {
|
||||
self.mag_modifiers.lock().unwrap()
|
||||
.entry(*mag_item_id)
|
||||
.or_insert(Vec::new())
|
||||
.push(mag::MagModifier::MagCell(mag_cell_id.clone()));
|
||||
}
|
||||
|
||||
async fn get_items_by_character(&self, character: &CharacterEntity) -> Vec<ItemEntity> {
|
||||
let items = self.items.lock().unwrap();
|
||||
items
|
||||
@ -179,6 +205,41 @@ impl EntityGateway for InMemoryGateway {
|
||||
.map(|(_, k)| {
|
||||
k.clone()
|
||||
})
|
||||
.map(|mut item| {
|
||||
item.item = match item.item {
|
||||
ItemDetail::Mag(mut mag) => {
|
||||
self.mag_modifiers.lock().unwrap().get(&item.id).map(|mag_modifiers| {
|
||||
for mag_modifier in mag_modifiers.iter() {
|
||||
match mag_modifier {
|
||||
mag::MagModifier::FeedMag {food} => {
|
||||
items.get(&food).map(|mag_feed| {
|
||||
match mag_feed.item {
|
||||
ItemDetail::Tool(mag_feed) => mag.feed(mag_feed.tool),
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
},
|
||||
mag::MagModifier::OwnerChange(class, section_id) => {
|
||||
mag.change_owner(*class, *section_id)
|
||||
},
|
||||
mag::MagModifier::MagCell(mag_cell_id) => {
|
||||
items.get(&mag_cell_id).map(|mag_cell| {
|
||||
match mag_cell.item {
|
||||
ItemDetail::Tool(mag_cell) => mag.apply_mag_cell(mag_cell.tool.try_into().unwrap()),
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
});
|
||||
ItemDetail::Mag(mag)
|
||||
}
|
||||
_ => item.item
|
||||
};
|
||||
item
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,62 @@
|
||||
use std::collections::HashMap;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use crate::entity::item::tool::ToolType;
|
||||
use crate::entity::character::{CharacterClass, SectionID};
|
||||
use crate::entity::item::ItemEntityId;
|
||||
use std::io::Read;
|
||||
|
||||
use std::cmp::Ordering::{Less, Greater, Equal};
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct MagStats {
|
||||
feed_table: usize,
|
||||
photon_blast: Option<PhotonBlast>
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct MagFeedTable {
|
||||
def: i16,
|
||||
pow: i16,
|
||||
dex: i16,
|
||||
mnd: i16,
|
||||
iq: i8,
|
||||
syn: i8,
|
||||
}
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref MAG_STATS: HashMap<MagType, MagStats> = {
|
||||
let mut f = std::fs::File::open("data/item_stats/mag_stats.toml").unwrap();
|
||||
let mut s = String::new();
|
||||
f.read_to_string(&mut s).unwrap();
|
||||
|
||||
let mag_stats: HashMap<String, MagStats> = toml::from_str(&s).unwrap();
|
||||
mag_stats.into_iter()
|
||||
.map(|(name, stats)| {
|
||||
(name.parse().unwrap(), stats)
|
||||
})
|
||||
.collect::<HashMap<MagType, MagStats>>()
|
||||
};
|
||||
|
||||
static ref MAG_FEEDING_TABLES: Vec<HashMap<ToolType, MagFeedTable>> = {
|
||||
let mut f = std::fs::File::open("data/item_stats/mag_feed_table.toml").unwrap();
|
||||
let mut s = String::new();
|
||||
f.read_to_string(&mut s).unwrap();
|
||||
|
||||
let mut feed: HashMap<String, Vec<HashMap<String, MagFeedTable>>> = toml::from_str(&s).unwrap();
|
||||
let feed = feed.remove("feedtable".into()).unwrap();
|
||||
feed.into_iter()
|
||||
.map(|table| {
|
||||
table.into_iter()
|
||||
.map(|(tool, stats)| {
|
||||
(tool.parse().unwrap(), stats)
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.collect::<Vec<HashMap<ToolType, MagFeedTable>>>()
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum ItemParseError {
|
||||
@ -250,6 +307,206 @@ impl MagType {
|
||||
_ => Err(ItemParseError::InvalidMagType),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn can_evolve(&self) -> bool {
|
||||
match self {
|
||||
MagType::Mag => true,
|
||||
MagType::Varuna => true,
|
||||
MagType::Mitra => true,
|
||||
MagType::Surya => true,
|
||||
MagType::Vayu => true,
|
||||
MagType::Varaha => true,
|
||||
MagType::Kama => true,
|
||||
MagType::Ushasu => true,
|
||||
MagType::Apsaras => true,
|
||||
MagType::Kumara => true,
|
||||
MagType::Kaitabha => true,
|
||||
MagType::Tapas => true,
|
||||
MagType::Bhirava => true,
|
||||
MagType::Kalki => true,
|
||||
MagType::Rudra => true,
|
||||
MagType::Marutah => true,
|
||||
MagType::Yaksa => true,
|
||||
MagType::Sita => true,
|
||||
MagType::Garuda => true,
|
||||
MagType::Nandin => true,
|
||||
MagType::Ashvinau => true,
|
||||
MagType::Ribhava => true,
|
||||
MagType::Soma => true,
|
||||
MagType::Ila => true,
|
||||
MagType::Durga => true,
|
||||
MagType::Vritra => true,
|
||||
MagType::Namuci => true,
|
||||
MagType::Sumba => true,
|
||||
MagType::Naga => true,
|
||||
MagType::Pitri => true,
|
||||
MagType::Kabanda => true,
|
||||
MagType::Ravana => true,
|
||||
MagType::Marica => true,
|
||||
MagType::Soniti => true,
|
||||
MagType::Preta => true,
|
||||
MagType::Andhaka => true,
|
||||
MagType::Bana => true,
|
||||
MagType::Naraka => true,
|
||||
MagType::Madhu => true,
|
||||
MagType::Churel => false,
|
||||
MagType::Robochao => false,
|
||||
MagType::OpaOpa => false,
|
||||
MagType::Pian => false,
|
||||
MagType::Chao => false,
|
||||
MagType::ChuChu => false,
|
||||
MagType::KapuKapu => false,
|
||||
MagType::AngelsWing => false,
|
||||
MagType::DevilsWing => false,
|
||||
MagType::Elenor => false,
|
||||
MagType::MarkIII => false,
|
||||
MagType::MasterSystem => false,
|
||||
MagType::Genesis => false,
|
||||
MagType::SegaSaturn => false,
|
||||
MagType::Dreamcast => false,
|
||||
MagType::Hamburger => false,
|
||||
MagType::PanzersTail => false,
|
||||
MagType::DevilsTail => false,
|
||||
MagType::Deva => false,
|
||||
MagType::Rati => false,
|
||||
MagType::Savitri => false,
|
||||
MagType::Rukmin => false,
|
||||
MagType::Pushan => false,
|
||||
MagType::Diwari => false,
|
||||
MagType::Sato => false,
|
||||
MagType::Bhima => false,
|
||||
MagType::Nidra => false,
|
||||
MagType::GeungSi => false,
|
||||
MagType::Tellusis => false,
|
||||
MagType::StrikerUnit => false,
|
||||
MagType::Pioneer => false,
|
||||
MagType::Puyo => false,
|
||||
MagType::Moro => false,
|
||||
MagType::Rappy => false,
|
||||
MagType::Yahoo => false,
|
||||
MagType::GaelGiel => false,
|
||||
MagType::Agastya => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum MagCell {
|
||||
CellOfMag502,
|
||||
CellOfMag213,
|
||||
PartsOfRobochao,
|
||||
HeartOfOpaOpa,
|
||||
HeartOfPian,
|
||||
HeartOfChao,
|
||||
HeartOfAngel,
|
||||
HeartOfDevil,
|
||||
KitOfHamburger,
|
||||
PanthersSpirit,
|
||||
KitOfMark3,
|
||||
KitOfMasterSystem,
|
||||
KitOfGenesis,
|
||||
KitOfSegaSaturn,
|
||||
KitOfDreamcast,
|
||||
Tablet,
|
||||
DragonScale,
|
||||
HeavenStrikerCoat,
|
||||
PioneerParts,
|
||||
AmitiesMemo,
|
||||
HeartOfMorolian,
|
||||
RappysBeak,
|
||||
YahoosEngine,
|
||||
DPhotonCore,
|
||||
LibertaKit,
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<ToolType> for MagCell {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(tool: ToolType) -> Result<MagCell, ()> {
|
||||
match tool {
|
||||
ToolType::CellOfMag502 => Ok(MagCell::CellOfMag502),
|
||||
ToolType::CellOfMag213 => Ok(MagCell::CellOfMag213),
|
||||
ToolType::PartsOfRobochao => Ok(MagCell::PartsOfRobochao),
|
||||
ToolType::HeartOfOpaOpa => Ok(MagCell::HeartOfOpaOpa),
|
||||
ToolType::HeartOfPian => Ok(MagCell::HeartOfPian),
|
||||
ToolType::HeartOfChao => Ok(MagCell::HeartOfChao),
|
||||
ToolType::HeartOfAngel => Ok(MagCell::HeartOfAngel),
|
||||
ToolType::HeartOfDevil => Ok(MagCell::HeartOfDevil),
|
||||
ToolType::KitOfHamburger => Ok(MagCell::KitOfHamburger),
|
||||
ToolType::PanthersSpirit => Ok(MagCell::PanthersSpirit),
|
||||
ToolType::KitOfMark3 => Ok(MagCell::KitOfMark3),
|
||||
ToolType::KitOfMasterSystem => Ok(MagCell::KitOfMasterSystem),
|
||||
ToolType::KitOfGenesis => Ok(MagCell::KitOfGenesis),
|
||||
ToolType::KitOfSegaSaturn => Ok(MagCell::KitOfSegaSaturn),
|
||||
ToolType::KitOfDreamcast => Ok(MagCell::KitOfDreamcast),
|
||||
ToolType::Tablet => Ok(MagCell::Tablet),
|
||||
ToolType::DragonScale => Ok(MagCell::DragonScale),
|
||||
ToolType::HeavenStrikerCoat => Ok(MagCell::HeavenStrikerCoat),
|
||||
ToolType::PioneerParts => Ok(MagCell::PioneerParts),
|
||||
ToolType::AmitiesMemo => Ok(MagCell::AmitiesMemo),
|
||||
ToolType::HeartOfMorolian => Ok(MagCell::HeartOfMorolian),
|
||||
ToolType::RappysBeak => Ok(MagCell::RappysBeak),
|
||||
ToolType::YahoosEngine => Ok(MagCell::YahoosEngine),
|
||||
ToolType::DPhotonCore => Ok(MagCell::DPhotonCore),
|
||||
ToolType::LibertaKit => Ok(MagCell::LibertaKit),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum MagAttribute {
|
||||
//Def,
|
||||
Pow,
|
||||
Dex,
|
||||
Mind,
|
||||
}
|
||||
|
||||
// one day I hope to be cool enough to figure how to enforce that each magattribute in sequence must be unique
|
||||
// (to not need the _ in the match)
|
||||
enum MagAttributeOrdering {
|
||||
Sequence(MagAttribute, MagAttribute, MagAttribute),
|
||||
Primary(MagAttribute),
|
||||
MultiPrimary
|
||||
}
|
||||
|
||||
impl MagAttributeOrdering {
|
||||
fn new(pow: u16, dex: u16, mnd: u16) -> MagAttributeOrdering {
|
||||
let primary = if pow > dex && pow > mnd {
|
||||
MagAttribute::Pow
|
||||
}
|
||||
else if dex > pow && dex > mnd{
|
||||
MagAttribute::Dex
|
||||
}
|
||||
else if mnd > pow && mnd > dex {
|
||||
MagAttribute::Mind
|
||||
}
|
||||
else {
|
||||
return MagAttributeOrdering::MultiPrimary
|
||||
};
|
||||
|
||||
match primary {
|
||||
MagAttribute::Pow => {
|
||||
match dex.cmp(&mnd) {
|
||||
Greater => MagAttributeOrdering::Sequence(primary, MagAttribute::Dex, MagAttribute::Mind),
|
||||
Equal => MagAttributeOrdering::Primary(primary),
|
||||
Less => MagAttributeOrdering::Sequence(primary, MagAttribute::Mind, MagAttribute::Dex),
|
||||
}
|
||||
},
|
||||
MagAttribute::Dex => {
|
||||
match pow.cmp(&mnd) {
|
||||
Greater => MagAttributeOrdering::Sequence(primary, MagAttribute::Pow, MagAttribute::Mind),
|
||||
Equal => MagAttributeOrdering::Primary(primary),
|
||||
Less => MagAttributeOrdering::Sequence(primary, MagAttribute::Mind, MagAttribute::Pow),
|
||||
}
|
||||
},
|
||||
MagAttribute::Mind => {
|
||||
match pow.cmp(&dex) {
|
||||
Greater => MagAttributeOrdering::Sequence(primary, MagAttribute::Pow, MagAttribute::Dex),
|
||||
Equal => MagAttributeOrdering::Primary(primary),
|
||||
Less => MagAttributeOrdering::Sequence(primary, MagAttribute::Dex, MagAttribute::Pow),
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
@ -257,11 +514,12 @@ pub enum MagModifier {
|
||||
FeedMag{
|
||||
food: ItemEntityId,
|
||||
},
|
||||
BankMag,
|
||||
BankMag, // when putting a mag in the bank it truncates the values which has applications when raising degenerate mags
|
||||
MagCell(ItemEntityId),
|
||||
OwnerChange(CharacterClass, SectionID)
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Deserialize, enum_utils::FromStr)]
|
||||
pub enum PhotonBlast {
|
||||
Farlla,
|
||||
Estlla,
|
||||
@ -274,19 +532,38 @@ pub enum PhotonBlast {
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Mag {
|
||||
pub mag: MagType,
|
||||
pub def: u16,
|
||||
pub pow: u16,
|
||||
pub dex: u16,
|
||||
pub mnd: u16,
|
||||
def: u16,
|
||||
pow: u16,
|
||||
dex: u16,
|
||||
mnd: u16,
|
||||
pub synchro: u8,
|
||||
pub iq: u8,
|
||||
pub photon_blast: [Option<PhotonBlast>; 3],
|
||||
iq: u8,
|
||||
photon_blast: [Option<PhotonBlast>; 3],
|
||||
pub color: u8,
|
||||
pub modifiers: Vec<MagModifier>,
|
||||
//modifiers: Vec<MagModifier>,
|
||||
pub class: CharacterClass,
|
||||
pub id: SectionID,
|
||||
}
|
||||
|
||||
|
||||
impl Mag {
|
||||
pub fn baby_mag(skin: u16) -> Mag {
|
||||
Mag {
|
||||
mag: MagType::Mag,
|
||||
def: 500,
|
||||
pow: 0,
|
||||
dex: 0,
|
||||
mnd: 0,
|
||||
synchro: 20,
|
||||
iq: 0,
|
||||
photon_blast: [None; 3],
|
||||
color: (skin % 18) as u8,
|
||||
//modifiers: Vec::new(),
|
||||
class: CharacterClass::HUmar,
|
||||
id: SectionID::Viridia,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_bytes(&self) -> [u8; 16] {
|
||||
let mut result = [0; 16];
|
||||
result[0..3].copy_from_slice(&self.mag.value());
|
||||
@ -355,7 +632,7 @@ impl Mag {
|
||||
}
|
||||
|
||||
pub fn from_bytes(data: [u8; 16]) -> Result<Mag, ItemParseError> {
|
||||
let m = MagType::parse_type([data[0], data[1], data[2]]);
|
||||
let m = MagType::parse_type([data[0], data[1], data[2]]);
|
||||
if m.is_ok() {
|
||||
let mut def = u16::from_le_bytes([data[4], data[5]]);
|
||||
let mut pow = u16::from_le_bytes([data[6], data[7]]);
|
||||
@ -382,11 +659,516 @@ impl Mag {
|
||||
iq: iq,
|
||||
photon_blast: [None, None, None], // TODO: actually get PBs from bytes
|
||||
color: data[15] % 18,
|
||||
modifiers: Vec::new(),
|
||||
//modifiers: Vec::new(),
|
||||
class: CharacterClass::HUmar,
|
||||
id: SectionID::Viridia,
|
||||
})
|
||||
}
|
||||
else {
|
||||
Err(ItemParseError::InvalidMagBytes) // TODO: error handling if wrong bytes are given
|
||||
}
|
||||
}
|
||||
|
||||
pub fn def(&self) -> u16 {
|
||||
self.def/100
|
||||
}
|
||||
|
||||
pub fn pow(&self) -> u16 {
|
||||
self.pow/100
|
||||
}
|
||||
|
||||
pub fn dex(&self) -> u16 {
|
||||
self.dex/100
|
||||
}
|
||||
|
||||
pub fn mind(&self) -> u16 {
|
||||
self.mnd/100
|
||||
}
|
||||
|
||||
pub fn level(&self) -> u16 {
|
||||
self.def() + self.pow() + self.dex() + self.mind()
|
||||
}
|
||||
|
||||
fn change_mag_type(&mut self, previous_level: u16) {
|
||||
if !self.mag.can_evolve() {
|
||||
return
|
||||
}
|
||||
|
||||
if self.level() >= 10 && previous_level < 10 {
|
||||
match self.class {
|
||||
CharacterClass::HUmar | CharacterClass::HUnewearl | CharacterClass::HUcast | CharacterClass::HUcaseal => {
|
||||
self.mag = MagType::Varuna
|
||||
},
|
||||
CharacterClass::RAmar | CharacterClass::RAmarl | CharacterClass::RAcast | CharacterClass::RAcaseal => {
|
||||
self.mag = MagType::Kalki
|
||||
},
|
||||
CharacterClass::FOmar | CharacterClass::FOmarl | CharacterClass::FOnewm | CharacterClass::FOnewearl => {
|
||||
self.mag = MagType::Vritra
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if self.level() >= 35 && previous_level < 35 {
|
||||
match self.mag {
|
||||
MagType::Varuna => {
|
||||
if self.pow > self.dex && self.pow > self.mnd {
|
||||
self.mag = MagType::Rudra
|
||||
}
|
||||
else if self.dex > self.pow && self.dex > self.mnd {
|
||||
self.mag = MagType::Marutah
|
||||
}
|
||||
else if self.mnd > self.pow && self.mnd > self.dex {
|
||||
self.mag = MagType::Vayu
|
||||
}
|
||||
else {
|
||||
self.mag = MagType::Rudra
|
||||
}
|
||||
},
|
||||
MagType::Kalki => {
|
||||
if self.pow > self.dex && self.pow > self.mnd {
|
||||
self.mag = MagType::Surya
|
||||
}
|
||||
else if self.dex > self.pow && self.dex > self.mnd {
|
||||
self.mag = MagType::Mitra
|
||||
}
|
||||
else if self.mnd > self.pow && self.mnd > self.dex {
|
||||
self.mag = MagType::Tapas
|
||||
}
|
||||
else {
|
||||
self.mag = MagType::Mitra
|
||||
}
|
||||
},
|
||||
MagType::Vritra => {
|
||||
if self.pow > self.dex && self.pow > self.mnd {
|
||||
self.mag = MagType::Sumba
|
||||
}
|
||||
else if self.dex > self.pow && self.dex > self.mnd {
|
||||
self.mag = MagType::Ashvinau
|
||||
}
|
||||
else if self.mnd > self.pow && self.mnd > self.dex {
|
||||
self.mag = MagType::Namuci
|
||||
}
|
||||
else {
|
||||
self.mag = MagType::Namuci
|
||||
}
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
if self.level() >= 50 && self.level() % 5 == 0 {
|
||||
let mag_attr_ordering = MagAttributeOrdering::new(self.pow, self.dex, self.mnd);
|
||||
self.mag = match self.id {
|
||||
SectionID::Viridia | SectionID::Skyly | SectionID::Purplenum | SectionID::Redria | SectionID::Yellowboze => {
|
||||
match self.class {
|
||||
CharacterClass::HUmar | CharacterClass::HUnewearl | CharacterClass::HUcast | CharacterClass::HUcaseal => {
|
||||
match mag_attr_ordering {
|
||||
MagAttributeOrdering::Primary(MagAttribute::Pow) => MagType::Varaha,
|
||||
MagAttributeOrdering::Primary(MagAttribute::Dex) => MagType::Nandin,
|
||||
MagAttributeOrdering::Primary(MagAttribute::Mind) => MagType::Kabanda,
|
||||
MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Dex, MagAttribute::Mind) => MagType::Varaha,
|
||||
MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Mind, MagAttribute::Dex) => MagType::Bhirava,
|
||||
MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Pow, MagAttribute::Mind) => MagType::Ila,
|
||||
MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Mind, MagAttribute::Pow) => MagType::Nandin,
|
||||
MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Pow, MagAttribute::Dex) => MagType::Kabanda,
|
||||
MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Dex, MagAttribute::Pow) => MagType::Ushasu,
|
||||
MagAttributeOrdering::MultiPrimary => {
|
||||
if self.dex >= self.mnd {
|
||||
MagType::Varaha
|
||||
}
|
||||
else {
|
||||
MagType::Bhirava
|
||||
}
|
||||
},
|
||||
_ => unreachable!()
|
||||
}
|
||||
},
|
||||
CharacterClass::RAmar | CharacterClass::RAmarl | CharacterClass::RAcast | CharacterClass::RAcaseal => {
|
||||
match mag_attr_ordering {
|
||||
MagAttributeOrdering::Primary(MagAttribute::Pow) => MagType::Kama,
|
||||
MagAttributeOrdering::Primary(MagAttribute::Dex) => MagType::Kama,
|
||||
MagAttributeOrdering::Primary(MagAttribute::Mind) => MagType::Varaha,
|
||||
MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Dex, MagAttribute::Mind) => MagType::Kama,
|
||||
MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Mind, MagAttribute::Dex) => MagType::Bhirava,
|
||||
MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Pow, MagAttribute::Mind) => MagType::Bhirava,
|
||||
MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Mind, MagAttribute::Pow) => MagType::Kama,
|
||||
MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Pow, MagAttribute::Dex) => MagType::Varaha,
|
||||
MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Dex, MagAttribute::Pow) => MagType::Apsaras,
|
||||
MagAttributeOrdering::MultiPrimary => {
|
||||
if self.mnd >= self.pow {
|
||||
MagType::Kama
|
||||
}
|
||||
else {
|
||||
MagType::Bhirava
|
||||
}
|
||||
}
|
||||
_ => unreachable!()
|
||||
}
|
||||
},
|
||||
CharacterClass::FOmar | CharacterClass::FOmarl | CharacterClass::FOnewm | CharacterClass::FOnewearl => {
|
||||
match (mag_attr_ordering, self.def() >= 45) {
|
||||
(MagAttributeOrdering::Primary(MagAttribute::Pow), true) => MagType::Andhaka,
|
||||
(MagAttributeOrdering::Primary(MagAttribute::Dex), true) => MagType::Bana,
|
||||
(MagAttributeOrdering::Primary(MagAttribute::Mind), true) => MagType::Bana,
|
||||
(MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Dex, MagAttribute::Mind), true) => MagType::Andhaka,
|
||||
(MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Mind, MagAttribute::Dex), true) => MagType::Andhaka,
|
||||
(MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Pow, MagAttribute::Mind), true) => MagType::Bana,
|
||||
(MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Mind, MagAttribute::Pow), true) => MagType::Bana,
|
||||
(MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Pow, MagAttribute::Dex), true) => MagType::Bana,
|
||||
(MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Dex, MagAttribute::Pow), true) => MagType::Bana,
|
||||
(MagAttributeOrdering::MultiPrimary, true) => MagType::Bana,
|
||||
(MagAttributeOrdering::Primary(MagAttribute::Pow), false) => MagType::Naraka,
|
||||
(MagAttributeOrdering::Primary(MagAttribute::Dex), false) => MagType::Sita,
|
||||
(MagAttributeOrdering::Primary(MagAttribute::Mind), false) => MagType::Naga,
|
||||
(MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Dex, MagAttribute::Mind), false) => MagType::Naraka,
|
||||
(MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Mind, MagAttribute::Dex), false) => MagType::Ravana,
|
||||
(MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Pow, MagAttribute::Mind), false) => MagType::Ribhava,
|
||||
(MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Mind, MagAttribute::Pow), false) => MagType::Sita,
|
||||
(MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Pow, MagAttribute::Dex), false) => MagType::Naga,
|
||||
(MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Dex, MagAttribute::Pow), false) => MagType::Kabanda,
|
||||
(MagAttributeOrdering::MultiPrimary, false) => {
|
||||
if self.pow >= self.dex {
|
||||
MagType::Naga
|
||||
}
|
||||
else {
|
||||
MagType::Kabanda
|
||||
}
|
||||
}
|
||||
_ => unreachable!()
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
SectionID::Greenill | SectionID::Bluefull | SectionID::Pinkal | SectionID::Oran | SectionID::Whitill => {
|
||||
match self.class {
|
||||
CharacterClass::HUmar | CharacterClass::HUnewearl | CharacterClass::HUcast | CharacterClass::HUcaseal => {
|
||||
match mag_attr_ordering {
|
||||
MagAttributeOrdering::Primary(MagAttribute::Pow) => MagType::Kama,
|
||||
MagAttributeOrdering::Primary(MagAttribute::Dex) => MagType::Yaksa,
|
||||
MagAttributeOrdering::Primary(MagAttribute::Mind) => MagType::Bana,
|
||||
MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Dex, MagAttribute::Mind) => MagType::Kama,
|
||||
MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Mind, MagAttribute::Dex) => MagType::Apsaras,
|
||||
MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Pow, MagAttribute::Mind) => MagType::Garuda,
|
||||
MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Mind, MagAttribute::Pow) => MagType::Yaksa,
|
||||
MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Pow, MagAttribute::Dex) => MagType::Bana,
|
||||
MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Dex, MagAttribute::Pow) => MagType::Soma,
|
||||
MagAttributeOrdering::MultiPrimary => {
|
||||
if self.dex >= self.mnd {
|
||||
MagType::Kama
|
||||
}
|
||||
else {
|
||||
MagType::Apsaras
|
||||
}
|
||||
}
|
||||
_ => unreachable!()
|
||||
}
|
||||
},
|
||||
CharacterClass::RAmar | CharacterClass::RAmarl | CharacterClass::RAcast | CharacterClass::RAcaseal => {
|
||||
match mag_attr_ordering {
|
||||
MagAttributeOrdering::Primary(MagAttribute::Pow) => MagType::Madhu,
|
||||
MagAttributeOrdering::Primary(MagAttribute::Dex) => MagType::Varaha,
|
||||
MagAttributeOrdering::Primary(MagAttribute::Mind) => MagType::Kabanda,
|
||||
MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Dex, MagAttribute::Mind) => MagType::Madhu,
|
||||
MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Mind, MagAttribute::Dex) => MagType::Kaitabha,
|
||||
MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Pow, MagAttribute::Mind) => MagType::Kaitabha,
|
||||
MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Mind, MagAttribute::Pow) => MagType::Varaha,
|
||||
MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Pow, MagAttribute::Dex) => MagType::Kabanda,
|
||||
MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Dex, MagAttribute::Pow) => MagType::Durga,
|
||||
MagAttributeOrdering::MultiPrimary => {
|
||||
if self.pow > self.mnd {
|
||||
MagType::Kaitabha
|
||||
}
|
||||
else {
|
||||
MagType::Varaha
|
||||
}
|
||||
}
|
||||
_ => unreachable!()
|
||||
}
|
||||
},
|
||||
CharacterClass::FOmar | CharacterClass::FOmarl | CharacterClass::FOnewm | CharacterClass::FOnewearl => {
|
||||
match (mag_attr_ordering, self.def() >= 45) {
|
||||
(MagAttributeOrdering::Primary(MagAttribute::Pow), true) => MagType::Andhaka,
|
||||
(MagAttributeOrdering::Primary(MagAttribute::Dex), true) => MagType::Bana,
|
||||
(MagAttributeOrdering::Primary(MagAttribute::Mind), true) => MagType::Bana,
|
||||
(MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Dex, MagAttribute::Mind), true) => MagType::Andhaka,
|
||||
(MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Mind, MagAttribute::Dex), true) => MagType::Andhaka,
|
||||
(MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Pow, MagAttribute::Mind), true) => MagType::Bana,
|
||||
(MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Mind, MagAttribute::Pow), true) => MagType::Bana,
|
||||
(MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Pow, MagAttribute::Dex), true) => MagType::Bana,
|
||||
(MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Dex, MagAttribute::Pow), true) => MagType::Bana,
|
||||
(MagAttributeOrdering::MultiPrimary, true) => MagType::Bana,
|
||||
(MagAttributeOrdering::Primary(MagAttribute::Pow), false) => MagType::Marica,
|
||||
(MagAttributeOrdering::Primary(MagAttribute::Dex), false) => MagType::Bhirava,
|
||||
(MagAttributeOrdering::Primary(MagAttribute::Mind), false) => MagType::Kumara,
|
||||
(MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Dex, MagAttribute::Mind), false) => MagType::Marica,
|
||||
(MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Mind, MagAttribute::Dex), false) => MagType::Naga,
|
||||
(MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Pow, MagAttribute::Mind), false) => MagType::Garuda,
|
||||
(MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Mind, MagAttribute::Pow), false) => MagType::Bhirava,
|
||||
(MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Pow, MagAttribute::Dex), false) => MagType::Kumara,
|
||||
(MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Dex, MagAttribute::Pow), false) => MagType::Ila,
|
||||
(MagAttributeOrdering::MultiPrimary, false) => {
|
||||
if self.pow >= self.dex {
|
||||
MagType::Kumara
|
||||
}
|
||||
else {
|
||||
MagType::Ila
|
||||
}
|
||||
}
|
||||
_ => unreachable!()
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if self.level() >= 100 && self.level() % 5 == 0 {
|
||||
match self.id {
|
||||
SectionID::Skyly | SectionID::Pinkal | SectionID::Yellowboze => {
|
||||
if self.def() + self.pow() == self.dex() + self.mind() {
|
||||
self.mag = match self.class {
|
||||
CharacterClass::HUmar | CharacterClass::HUcast => {
|
||||
MagType::Rati
|
||||
},
|
||||
CharacterClass::HUnewearl | CharacterClass::HUcaseal => {
|
||||
MagType::Savitri
|
||||
},
|
||||
CharacterClass::RAmar | CharacterClass::RAcast => {
|
||||
MagType::Pushan
|
||||
},
|
||||
CharacterClass::RAmarl | CharacterClass::RAcaseal => {
|
||||
MagType::Diwari
|
||||
},
|
||||
CharacterClass::FOmar | CharacterClass::FOnewm => {
|
||||
MagType::Nidra
|
||||
},
|
||||
CharacterClass::FOmarl | CharacterClass::FOnewearl => {
|
||||
MagType::Bhima
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
SectionID::Viridia | SectionID::Bluefull | SectionID::Redria | SectionID::Whitill => {
|
||||
if self.def() + self.dex() == self.pow() + self.mind() {
|
||||
self.mag = match self.class {
|
||||
CharacterClass::HUmar | CharacterClass::HUcast => {
|
||||
MagType::Deva
|
||||
},
|
||||
CharacterClass::HUnewearl | CharacterClass::HUcaseal => {
|
||||
MagType::Savitri
|
||||
},
|
||||
CharacterClass::RAmar | CharacterClass::RAcast => {
|
||||
MagType::Pushan
|
||||
},
|
||||
CharacterClass::RAmarl | CharacterClass::RAcaseal => {
|
||||
MagType::Rukmin
|
||||
},
|
||||
CharacterClass::FOmar | CharacterClass::FOnewm => {
|
||||
MagType::Nidra
|
||||
},
|
||||
CharacterClass::FOmarl | CharacterClass::FOnewearl => {
|
||||
MagType::Sato // best mag
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
SectionID::Greenill | SectionID::Purplenum | SectionID::Oran => {
|
||||
if self.def() + self.mind() == self.pow() + self.dex() {
|
||||
self.mag = match self.class {
|
||||
CharacterClass::HUmar | CharacterClass::HUcast => {
|
||||
MagType::Rati
|
||||
},
|
||||
CharacterClass::HUnewearl | CharacterClass::HUcaseal => {
|
||||
MagType::Savitri
|
||||
},
|
||||
CharacterClass::RAmar | CharacterClass::RAcast => {
|
||||
MagType::Pushan
|
||||
},
|
||||
CharacterClass::RAmarl | CharacterClass::RAcaseal => {
|
||||
MagType::Rukmin
|
||||
},
|
||||
CharacterClass::FOmar | CharacterClass::FOnewm => {
|
||||
MagType::Nidra
|
||||
},
|
||||
CharacterClass::FOmarl | CharacterClass::FOnewearl => {
|
||||
MagType::Bhima
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn assign_photon_blast(&mut self) {
|
||||
MAG_STATS.get(&self.mag).map(|stats| {
|
||||
stats.photon_blast.map(|photon_blast| {
|
||||
if !self.photon_blast.contains(&Some(photon_blast)) {
|
||||
self.photon_blast.iter_mut().find(|k| k.is_none()).map(|pb_slot| {
|
||||
*pb_slot = Some(photon_blast)
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
pub fn feed(&mut self, tool: ToolType) {
|
||||
let previous_level = self.level();
|
||||
MAG_STATS.get(&self.mag).map(|stats| {
|
||||
MAG_FEEDING_TABLES.get(stats.feed_table).map(|feeding_table| {
|
||||
feeding_table.get(&tool).map(|feed_stats| {
|
||||
self.def = std::cmp::max(std::cmp::max((self.def as i16) + feed_stats.def, 0) as u16, self.def()*100);
|
||||
self.pow = std::cmp::max(std::cmp::max((self.pow as i16) + feed_stats.pow, 0) as u16, self.pow()*100);
|
||||
self.dex = std::cmp::max(std::cmp::max((self.dex as i16) + feed_stats.dex, 0) as u16, self.dex()*100);
|
||||
self.mnd = std::cmp::max(std::cmp::max((self.mnd as i16) + feed_stats.mnd, 0) as u16, self.mind()*100);
|
||||
self.iq = std::cmp::min(((self.iq as i16) + feed_stats.iq as i16) as u8, 200);
|
||||
self.synchro = std::cmp::min(((self.synchro as i8) + feed_stats.syn) as u8, 120);
|
||||
})
|
||||
})
|
||||
});
|
||||
//if previous_level != self.level() {
|
||||
self.change_mag_type(previous_level);
|
||||
self.assign_photon_blast();
|
||||
//}
|
||||
}
|
||||
|
||||
pub fn change_owner(&mut self, class: CharacterClass, id: SectionID) {
|
||||
self.class = class;
|
||||
self.id = id;
|
||||
}
|
||||
|
||||
pub fn bank(&mut self) {
|
||||
// what is the truncation logic anyway
|
||||
}
|
||||
|
||||
// TODO: this needs more checks on validity
|
||||
pub fn apply_mag_cell(&mut self, mag_cell: MagCell) {
|
||||
self.mag = match mag_cell {
|
||||
MagCell::CellOfMag502 => {
|
||||
match self.id {
|
||||
SectionID::Viridia | SectionID::Skyly | SectionID::Purplenum | SectionID::Redria | SectionID::Yellowboze => {
|
||||
MagType::Soniti
|
||||
},
|
||||
SectionID::Greenill | SectionID::Bluefull | SectionID::Pinkal | SectionID::Oran | SectionID::Whitill => {
|
||||
MagType::Pitri
|
||||
}
|
||||
}
|
||||
}
|
||||
MagCell::CellOfMag213 => {
|
||||
match self.id {
|
||||
SectionID::Viridia | SectionID::Skyly | SectionID::Purplenum | SectionID::Redria | SectionID::Yellowboze => {
|
||||
MagType::Churel
|
||||
},
|
||||
SectionID::Greenill | SectionID::Bluefull | SectionID::Pinkal | SectionID::Oran | SectionID::Whitill => {
|
||||
MagType::Preta
|
||||
}
|
||||
}
|
||||
},
|
||||
MagCell::PartsOfRobochao => MagType::Robochao,
|
||||
MagCell::HeartOfOpaOpa => MagType::OpaOpa,
|
||||
MagCell::HeartOfPian => MagType::Pian,
|
||||
MagCell::HeartOfChao => MagType::Chao,
|
||||
MagCell::HeartOfAngel => MagType::AngelsWing,
|
||||
MagCell::HeartOfDevil => if self.mag == MagType::DevilsWing {
|
||||
MagType::DevilsTail
|
||||
}
|
||||
else {
|
||||
MagType::DevilsWing
|
||||
},
|
||||
MagCell::KitOfHamburger => MagType::Hamburger,
|
||||
MagCell::PanthersSpirit => MagType::PanzersTail,
|
||||
MagCell::KitOfMark3 => MagType::MarkIII,
|
||||
MagCell::KitOfMasterSystem => MagType::MasterSystem,
|
||||
MagCell::KitOfGenesis => MagType::Genesis,
|
||||
MagCell::KitOfSegaSaturn => MagType::SegaSaturn,
|
||||
MagCell::KitOfDreamcast => MagType::Dreamcast,
|
||||
MagCell::Tablet => MagType::GeungSi,
|
||||
MagCell::DragonScale => MagType::Tellusis,
|
||||
MagCell::HeavenStrikerCoat => MagType::StrikerUnit,
|
||||
MagCell::PioneerParts => MagType::Pioneer,
|
||||
MagCell::AmitiesMemo => MagType::Puyo,
|
||||
MagCell::HeartOfMorolian => MagType::Moro,
|
||||
MagCell::RappysBeak => MagType::Rappy,
|
||||
MagCell::YahoosEngine => MagType::Yahoo,
|
||||
MagCell::DPhotonCore => MagType::GaelGiel,
|
||||
MagCell::LibertaKit => MagType::Agastya,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use std::io::Read;
|
||||
|
||||
#[test]
|
||||
fn test_load_mag_stats() {
|
||||
let mut f = std::fs::File::open("data/item_stats/mag_stats.toml").unwrap();
|
||||
let mut s = String::new();
|
||||
f.read_to_string(&mut s).unwrap();
|
||||
|
||||
let mags: HashMap<String, MagStats> = toml::from_str(&s).unwrap();
|
||||
let _mags = mags.into_iter()
|
||||
.map(|(name, stats)| {
|
||||
(name.parse().unwrap(), stats)
|
||||
})
|
||||
.collect::<HashMap<MagType, MagStats>>();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_load_mag_feed_table() {
|
||||
let mut f = std::fs::File::open("data/item_stats/mag_feed_table.toml").unwrap();
|
||||
let mut s = String::new();
|
||||
f.read_to_string(&mut s).unwrap();
|
||||
|
||||
let mut feed: HashMap<String, Vec<HashMap<String, MagFeedTable>>> = toml::from_str(&s).unwrap();
|
||||
let feed = feed.remove("feedtable".into()).unwrap();
|
||||
let _feed = feed.into_iter()
|
||||
.map(|table| {
|
||||
table.into_iter()
|
||||
.map(|(tool, stats)| {
|
||||
(tool.parse().unwrap(), stats)
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.collect::<Vec<HashMap<ToolType, MagFeedTable>>>();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_raise_a_sato() {
|
||||
let mut mag = Mag::baby_mag(0);
|
||||
mag.change_owner(CharacterClass::RAcaseal, SectionID::Whitill);
|
||||
for _ in 0..137 {
|
||||
mag.feed(ToolType::Antidote);
|
||||
}
|
||||
for _ in 0..75 {
|
||||
mag.feed(ToolType::Antiparalysis);
|
||||
}
|
||||
mag.change_owner(CharacterClass::FOmarl, SectionID::Whitill);
|
||||
for _ in 0..51 {
|
||||
mag.feed(ToolType::Antiparalysis);
|
||||
}
|
||||
for _ in 0..284 {
|
||||
mag.feed(ToolType::Dimate);
|
||||
}
|
||||
assert!(mag == Mag {
|
||||
mag: MagType::Sato,
|
||||
def: 507,
|
||||
pow: 5019,
|
||||
dex: 4505,
|
||||
mnd: 0,
|
||||
synchro: 120,
|
||||
iq: 200,
|
||||
photon_blast: [Some(PhotonBlast::Estlla), Some(PhotonBlast::Pilla), Some(PhotonBlast::MyllaYoulla)],
|
||||
color: 0,
|
||||
class: CharacterClass::FOmarl,
|
||||
id: SectionID::Whitill,
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mag_does_not_level_down() {
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,9 @@ pub enum ItemLocation {
|
||||
z: f32,
|
||||
},
|
||||
Consumed,
|
||||
FedToMag {
|
||||
mag: ItemEntityId,
|
||||
}
|
||||
/*Destroyed {
|
||||
// marks an item that has been consumed in some way
|
||||
},
|
||||
|
@ -251,6 +251,42 @@ impl ToolType {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_mag_cell(&self) -> bool {
|
||||
match self {
|
||||
ToolType::CellOfMag502 => true,
|
||||
ToolType::CellOfMag213 => true,
|
||||
ToolType::PartsOfRobochao => true,
|
||||
ToolType::HeartOfOpaOpa => true,
|
||||
ToolType::HeartOfPian => true,
|
||||
ToolType::HeartOfChao => true,
|
||||
ToolType::HeartOfAngel => true,
|
||||
ToolType::HeartOfDevil => true,
|
||||
ToolType::KitOfHamburger => true,
|
||||
ToolType::PanthersSpirit => true,
|
||||
ToolType::KitOfMark3 => true,
|
||||
ToolType::KitOfMasterSystem => true,
|
||||
ToolType::KitOfGenesis => true,
|
||||
ToolType::KitOfSegaSaturn => true,
|
||||
ToolType::KitOfDreamcast => true,
|
||||
ToolType::Tablet => true,
|
||||
ToolType::DragonScale => true,
|
||||
ToolType::HeavenStrikerCoat => true,
|
||||
ToolType::PioneerParts => true,
|
||||
ToolType::AmitiesMemo => true,
|
||||
ToolType::HeartOfMorolian => true,
|
||||
ToolType::RappysBeak => true,
|
||||
ToolType::YahoosEngine => true,
|
||||
ToolType::DPhotonCore => true,
|
||||
ToolType::LibertaKit => true,
|
||||
ToolType::CellOfMag0503 => true,
|
||||
ToolType::CellOfMag0504 => true,
|
||||
ToolType::CellOfMag0505 => true,
|
||||
ToolType::CellOfMag0506 => true,
|
||||
ToolType::CellOfMag0507 => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn value(&self) -> [u8; 3] {
|
||||
match self {
|
||||
ToolType::Monomate => [0x03, 0x00, 0x00],
|
||||
|
@ -3,6 +3,8 @@
|
||||
#![feature(maybe_uninit_extra)]
|
||||
#![feature(const_in_array_repeat_expressions)]
|
||||
#![feature(drain_filter)]
|
||||
#![feature(or_patterns)]
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -224,21 +224,11 @@ async fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAc
|
||||
equipped: true,
|
||||
}}).await;
|
||||
|
||||
let mut mag = Mag::baby_mag(character.appearance.skin);
|
||||
mag.change_owner(character.char_class, character.section_id);
|
||||
entity_gateway.create_item(
|
||||
NewItemEntity {
|
||||
item: ItemDetail::Mag(
|
||||
Mag {
|
||||
mag: MagType::Mag,
|
||||
def: 500,
|
||||
pow: 0,
|
||||
dex: 0,
|
||||
mnd: 0,
|
||||
synchro: 20,
|
||||
iq: 0,
|
||||
photon_blast: [None; 3],
|
||||
color: (character.appearance.skin % 18) as u8,
|
||||
modifiers: Vec::new(),
|
||||
}),
|
||||
item: ItemDetail::Mag(mag),
|
||||
location: ItemLocation::Inventory {
|
||||
character_id: character.id,
|
||||
slot: 2,
|
||||
|
@ -136,18 +136,7 @@ impl RareDropTable {
|
||||
})
|
||||
},
|
||||
RareDropItem::Mag(mag) => {
|
||||
ItemDropType::Mag(Mag {
|
||||
mag: mag,
|
||||
def: 500,
|
||||
pow: 0,
|
||||
dex: 0,
|
||||
mnd: 0,
|
||||
iq: 0,
|
||||
synchro: 20,
|
||||
photon_blast: [None; 3],
|
||||
color: rng.gen_range(0, 18),
|
||||
modifiers: Vec::new(),
|
||||
})
|
||||
ItemDropType::Mag(Mag::baby_mag(rng.gen_range(0, 18)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ use thiserror::Error;
|
||||
use libpso::character::character;//::InventoryItem;
|
||||
use crate::entity::item::{ItemEntityId, ItemDetail, ItemType};
|
||||
use crate::entity::item::tool::Tool;
|
||||
use crate::entity::item::mag::Mag;
|
||||
use crate::ship::items::{ClientItemId, BankItem, BankItemHandle};
|
||||
use crate::ship::items::floor::{IndividualFloorItem, StackedFloorItem};
|
||||
|
||||
@ -20,6 +21,22 @@ pub struct IndividualInventoryItem {
|
||||
pub equipped: bool,
|
||||
}
|
||||
|
||||
impl IndividualInventoryItem {
|
||||
pub fn mag(&self) -> Option<&Mag> {
|
||||
match self.item {
|
||||
ItemDetail::Mag(ref mag) => Some(mag),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mag_mut(&mut self) -> Option<&mut Mag> {
|
||||
match self.item {
|
||||
ItemDetail::Mag(ref mut mag) => Some(mag),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct StackedInventoryItem {
|
||||
pub entity_ids: Vec<ItemEntityId>,
|
||||
@ -57,6 +74,17 @@ pub enum InventoryItemAddToError {
|
||||
}
|
||||
|
||||
impl InventoryItem {
|
||||
pub fn entity_ids(&self) -> Vec<ItemEntityId> {
|
||||
match self {
|
||||
InventoryItem::Individual(individual_inventory_item) => {
|
||||
vec![individual_inventory_item.entity_id]
|
||||
},
|
||||
InventoryItem::Stacked(stacked_inventory_item) => {
|
||||
stacked_inventory_item.entity_ids.clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn item_id(&self) -> ClientItemId {
|
||||
match self {
|
||||
InventoryItem::Individual(individual_inventory_item) => {
|
||||
@ -179,6 +207,13 @@ impl InventoryItem {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn individual(&mut self) -> Option<&mut IndividualInventoryItem> {
|
||||
match self {
|
||||
InventoryItem::Individual(ref mut individual_inventory_item) => Some(individual_inventory_item),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -365,6 +400,24 @@ impl CharacterInventory {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_equipped_mag_handle<'a>(&'a mut self) -> Option<InventoryItemHandle<'a>> {
|
||||
let (slot, _) = self.items.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, item)| {
|
||||
if let InventoryItem::Individual(individual_inventory_item) = item {
|
||||
if let ItemDetail::Mag(_) = &individual_inventory_item.item {
|
||||
return individual_inventory_item.equipped
|
||||
}
|
||||
}
|
||||
false
|
||||
})
|
||||
.nth(0)?;
|
||||
Some(InventoryItemHandle {
|
||||
inventory: self,
|
||||
slot: slot,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_item_by_id(&self, item_id: ClientItemId) -> Option<&InventoryItem> {
|
||||
self.items.iter()
|
||||
.filter(|item| {
|
||||
|
@ -5,7 +5,7 @@ use crate::entity::gateway::EntityGateway;
|
||||
use crate::entity::character::{CharacterEntity, CharacterEntityId};
|
||||
use crate::entity::item::{ItemDetail, ItemLocation, BankName};
|
||||
use crate::entity::item::{Meseta, NewItemEntity};
|
||||
use crate::entity::item::tool::Tool;
|
||||
use crate::entity::item::tool::{Tool, ToolType};
|
||||
use crate::ship::map::MapArea;
|
||||
use crate::ship::ship::ItemDropLocation;
|
||||
use crate::ship::drops::{ItemDrop, ItemDropType};
|
||||
@ -14,6 +14,7 @@ use crate::ship::location::{AreaClient, RoomId};
|
||||
use crate::ship::items::bank::*;
|
||||
use crate::ship::items::floor::*;
|
||||
use crate::ship::items::inventory::*;
|
||||
use crate::ship::items::use_tool;
|
||||
|
||||
|
||||
pub enum TriggerCreateItem {
|
||||
@ -36,6 +37,8 @@ pub enum ItemManagerError {
|
||||
NotEnoughTools(Tool, usize, usize), // have, expected
|
||||
InventoryItemConsumeError(#[from] InventoryItemConsumeError),
|
||||
BankFull,
|
||||
WrongItemType(ClientItemId),
|
||||
UseItemError(#[from] use_tool::UseItemError),
|
||||
}
|
||||
|
||||
pub struct ItemManager {
|
||||
@ -260,6 +263,9 @@ impl ItemManager {
|
||||
equipped: false,
|
||||
}
|
||||
).await;
|
||||
if let Some(_) = new_inventory_item.mag() {
|
||||
entity_gateway.change_mag_owner(&new_inventory_item.entity_id, character).await;
|
||||
}
|
||||
},
|
||||
None => {
|
||||
return Err(ItemManagerError::CouldNotAddToInventory(item_id));
|
||||
@ -508,7 +514,7 @@ impl ItemManager {
|
||||
character: &CharacterEntity,
|
||||
item_id: ClientItemId,
|
||||
amount: usize)
|
||||
-> Result<ItemDetail, ItemManagerError> {
|
||||
-> Result<ConsumedItem, ItemManagerError> {
|
||||
let inventory = self.character_inventory.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
|
||||
let used_item = inventory.get_item_handle_by_id(item_id).ok_or(ItemManagerError::NoSuchItemId(item_id))?;
|
||||
let consumed_item = used_item.consume(amount)?;
|
||||
@ -518,7 +524,7 @@ impl ItemManager {
|
||||
ItemLocation::Consumed).await;
|
||||
}
|
||||
|
||||
Ok(consumed_item.item())
|
||||
Ok(consumed_item)
|
||||
}
|
||||
|
||||
pub async fn player_deposits_item<EG: EntityGateway>(&mut self,
|
||||
@ -595,4 +601,155 @@ impl ItemManager {
|
||||
|
||||
Ok(inventory_item.0)
|
||||
}
|
||||
|
||||
pub async fn player_feeds_mag_item<EG: EntityGateway>(&mut self,
|
||||
entity_gateway: &mut EG,
|
||||
character: &CharacterEntity,
|
||||
mag_id: ClientItemId,
|
||||
tool_id: ClientItemId)
|
||||
-> Result<(), ItemManagerError> {
|
||||
let inventory = self.character_inventory.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
|
||||
let consumed_tool = {
|
||||
let item_to_feed = inventory.get_item_handle_by_id(tool_id).ok_or(ItemManagerError::NoSuchItemId(tool_id))?;
|
||||
item_to_feed.consume(1)?
|
||||
};
|
||||
let mut mag_handle = inventory.get_item_handle_by_id(mag_id).ok_or(ItemManagerError::NoSuchItemId(mag_id))?;
|
||||
|
||||
let individual_item = mag_handle.item_mut()
|
||||
.ok_or(ItemManagerError::NoSuchItemId(mag_id))?
|
||||
.individual()
|
||||
.ok_or(ItemManagerError::WrongItemType(mag_id))?;
|
||||
let mag = individual_item
|
||||
.mag_mut()
|
||||
.ok_or(ItemManagerError::WrongItemType(mag_id))?;
|
||||
|
||||
let consumed_tool_type = match &consumed_tool {
|
||||
ConsumedItem::Stacked(stacked_consumed_item) => stacked_consumed_item.tool.tool,
|
||||
_ => return Err(ItemManagerError::WrongItemType(tool_id))
|
||||
};
|
||||
mag.feed(consumed_tool_type);
|
||||
|
||||
for entity_id in consumed_tool.entity_ids() {
|
||||
entity_gateway.feed_mag(&individual_item.entity_id, &entity_id).await;
|
||||
entity_gateway.change_item_location(&entity_id, ItemLocation::FedToMag {
|
||||
mag: individual_item.entity_id,
|
||||
}).await;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
pub async fn use_item<EG: EntityGateway>(&mut self,
|
||||
used_item: ConsumedItem,
|
||||
entity_gateway: &mut EG,
|
||||
character: &mut CharacterEntity) -> Result<(), ItemManagerError> {
|
||||
let inventory = self.character_inventory.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
|
||||
match &used_item.item() {
|
||||
ItemDetail::Weapon(_w) => {
|
||||
// something like when items are used to combine/transform them?
|
||||
//_ => {}
|
||||
},
|
||||
ItemDetail::Tool(t) => {
|
||||
match t.tool {
|
||||
ToolType::PowerMaterial => {
|
||||
use_tool::power_material(entity_gateway, character).await;
|
||||
},
|
||||
ToolType::MindMaterial => {
|
||||
use_tool::mind_material(entity_gateway, character).await;
|
||||
},
|
||||
ToolType::EvadeMaterial => {
|
||||
use_tool::evade_material(entity_gateway, character).await;
|
||||
},
|
||||
ToolType::DefMaterial => {
|
||||
use_tool::def_material(entity_gateway, character).await;
|
||||
},
|
||||
ToolType::LuckMaterial => {
|
||||
use_tool::luck_material(entity_gateway, character).await;
|
||||
},
|
||||
ToolType::HpMaterial => {
|
||||
use_tool::hp_material(entity_gateway, character).await;
|
||||
},
|
||||
ToolType::TpMaterial => {
|
||||
use_tool::tp_material(entity_gateway, character).await;
|
||||
},
|
||||
ToolType::CellOfMag502 => {
|
||||
use_tool::cell_of_mag_502(entity_gateway, &used_item, inventory).await?;
|
||||
},
|
||||
ToolType::CellOfMag213 => {
|
||||
use_tool::cell_of_mag_213(entity_gateway, &used_item, inventory).await?;
|
||||
},
|
||||
ToolType::PartsOfRobochao => {
|
||||
use_tool::parts_of_robochao(entity_gateway, &used_item, inventory).await?;
|
||||
},
|
||||
ToolType::HeartOfOpaOpa => {
|
||||
use_tool::heart_of_opaopa(entity_gateway, &used_item, inventory).await?;
|
||||
},
|
||||
ToolType::HeartOfPian => {
|
||||
use_tool::heart_of_pian(entity_gateway, &used_item, inventory).await?;
|
||||
},
|
||||
ToolType::HeartOfChao=> {
|
||||
use_tool::heart_of_chao(entity_gateway, &used_item, inventory).await?;
|
||||
},
|
||||
ToolType::HeartOfAngel => {
|
||||
use_tool::heart_of_angel(entity_gateway, &used_item, inventory).await?;
|
||||
},
|
||||
ToolType::KitOfHamburger => {
|
||||
use_tool::kit_of_hamburger(entity_gateway, &used_item, inventory).await?;
|
||||
},
|
||||
ToolType::PanthersSpirit => {
|
||||
use_tool::panthers_spirit(entity_gateway, &used_item, inventory).await?;
|
||||
},
|
||||
ToolType::KitOfMark3 => {
|
||||
use_tool::kit_of_mark3(entity_gateway, &used_item, inventory).await?;
|
||||
},
|
||||
ToolType::KitOfMasterSystem=> {
|
||||
use_tool::kit_of_master_system(entity_gateway, &used_item, inventory).await?;
|
||||
},
|
||||
ToolType::KitOfGenesis => {
|
||||
use_tool::kit_of_genesis(entity_gateway, &used_item, inventory).await?;
|
||||
},
|
||||
ToolType::KitOfSegaSaturn => {
|
||||
use_tool::kit_of_sega_saturn(entity_gateway, &used_item, inventory).await?;
|
||||
},
|
||||
ToolType::KitOfDreamcast => {
|
||||
use_tool::kit_of_dreamcast(entity_gateway, &used_item, inventory).await?;
|
||||
},
|
||||
ToolType::Tablet => {
|
||||
use_tool::tablet(entity_gateway, &used_item, inventory).await?;
|
||||
},
|
||||
ToolType::DragonScale => {
|
||||
use_tool::dragon_scale(entity_gateway, &used_item, inventory).await?;
|
||||
},
|
||||
ToolType::HeavenStrikerCoat => {
|
||||
use_tool::heaven_striker_coat(entity_gateway, &used_item, inventory).await?;
|
||||
},
|
||||
ToolType::PioneerParts => {
|
||||
use_tool::pioneer_parts(entity_gateway, &used_item, inventory).await?;
|
||||
},
|
||||
ToolType::AmitiesMemo => {
|
||||
use_tool::amities_memo(entity_gateway, &used_item, inventory).await?;
|
||||
},
|
||||
ToolType::HeartOfMorolian => {
|
||||
use_tool::heart_of_morolian(entity_gateway, &used_item, inventory).await?;
|
||||
},
|
||||
ToolType::RappysBeak => {
|
||||
use_tool::rappys_beak(entity_gateway, &used_item, inventory).await?;
|
||||
},
|
||||
ToolType::YahoosEngine => {
|
||||
use_tool::yahoos_engine(entity_gateway, &used_item, inventory).await?;
|
||||
},
|
||||
ToolType::DPhotonCore => {
|
||||
use_tool::d_photon_core(entity_gateway, &used_item, inventory).await?;
|
||||
},
|
||||
ToolType::LibertaKit => {
|
||||
use_tool::liberta_kit(entity_gateway, &used_item, inventory).await?;
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ mod bank;
|
||||
mod floor;
|
||||
mod inventory;
|
||||
mod manager;
|
||||
pub mod use_tool;
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||
pub struct ClientItemId(pub u32);
|
||||
|
175
src/ship/items/use_tool.rs
Normal file
175
src/ship/items/use_tool.rs
Normal file
@ -0,0 +1,175 @@
|
||||
use thiserror::Error;
|
||||
use crate::entity::gateway::EntityGateway;
|
||||
use crate::entity::character::CharacterEntity;
|
||||
use crate::entity::item::{ItemEntityId, ItemDetail};
|
||||
use crate::entity::item::tool::ToolType;
|
||||
use crate::entity::item::mag::MagCell;
|
||||
use crate::ship::items::{ItemManager, ClientItemId, CharacterInventory, ConsumedItem};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[error("")]
|
||||
pub enum UseItemError {
|
||||
NoCharacter,
|
||||
ItemNotEquipped,
|
||||
InvalidItem,
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//pub fn use_tool()
|
||||
|
||||
pub async fn power_material<EG: EntityGateway>(entity_gateway: &mut EG, character: &mut CharacterEntity) {
|
||||
character.materials.power += 1;
|
||||
entity_gateway.save_character(character).await;
|
||||
}
|
||||
|
||||
pub async fn mind_material<EG: EntityGateway>(entity_gateway: &mut EG, character: &mut CharacterEntity) {
|
||||
character.materials.mind += 1;
|
||||
entity_gateway.save_character(character).await;
|
||||
}
|
||||
|
||||
pub async fn evade_material<EG: EntityGateway>(entity_gateway: &mut EG, character: &mut CharacterEntity) {
|
||||
character.materials.evade += 1;
|
||||
entity_gateway.save_character(character).await;
|
||||
}
|
||||
|
||||
pub async fn def_material<EG: EntityGateway>(entity_gateway: &mut EG, character: &mut CharacterEntity) {
|
||||
character.materials.def += 1;
|
||||
entity_gateway.save_character(character).await;
|
||||
}
|
||||
|
||||
pub async fn luck_material<EG: EntityGateway>(entity_gateway: &mut EG, character: &mut CharacterEntity) {
|
||||
character.materials.luck += 1;
|
||||
entity_gateway.save_character(character).await;
|
||||
}
|
||||
|
||||
pub async fn hp_material<EG: EntityGateway>(entity_gateway: &mut EG, character: &mut CharacterEntity) {
|
||||
character.materials.hp += 1;
|
||||
entity_gateway.save_character(character).await;
|
||||
}
|
||||
|
||||
pub async fn tp_material<EG: EntityGateway>(entity_gateway: &mut EG, character: &mut CharacterEntity) {
|
||||
character.materials.tp += 1;
|
||||
entity_gateway.save_character(character).await;
|
||||
}
|
||||
|
||||
async fn mag_cell<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory, mag_cell_type: MagCell) -> Result<(), UseItemError> {
|
||||
let mut mag_handle = inventory.get_equipped_mag_handle().ok_or(UseItemError::ItemNotEquipped)?;
|
||||
let mag_item = mag_handle.item_mut()
|
||||
.ok_or(UseItemError::InvalidItem)?;
|
||||
let actual_mag = mag_item
|
||||
.individual()
|
||||
.ok_or(UseItemError::InvalidItem)?
|
||||
.mag_mut()
|
||||
.ok_or(UseItemError::InvalidItem)?;
|
||||
actual_mag.apply_mag_cell(mag_cell_type);
|
||||
for mag_entity_id in mag_item.entity_ids() {
|
||||
for cell_entity_id in used_cell.entity_ids() {
|
||||
entity_gateway.use_mag_cell(&mag_entity_id, &cell_entity_id).await;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn cell_of_mag_502<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), UseItemError> {
|
||||
mag_cell(entity_gateway, used_cell, inventory, MagCell::CellOfMag502).await
|
||||
}
|
||||
|
||||
pub async fn cell_of_mag_213<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), UseItemError> {
|
||||
mag_cell(entity_gateway, used_cell, inventory, MagCell::CellOfMag213).await
|
||||
}
|
||||
|
||||
pub async fn parts_of_robochao<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), UseItemError> {
|
||||
mag_cell(entity_gateway, used_cell, inventory, MagCell::PartsOfRobochao).await
|
||||
}
|
||||
|
||||
pub async fn heart_of_opaopa<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), UseItemError> {
|
||||
mag_cell(entity_gateway, used_cell, inventory, MagCell::HeartOfOpaOpa).await
|
||||
}
|
||||
|
||||
pub async fn heart_of_pian<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), UseItemError> {
|
||||
mag_cell(entity_gateway, used_cell, inventory, MagCell::HeartOfPian).await
|
||||
}
|
||||
|
||||
pub async fn heart_of_chao<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), UseItemError> {
|
||||
mag_cell(entity_gateway, used_cell, inventory, MagCell::HeartOfChao).await
|
||||
}
|
||||
|
||||
pub async fn heart_of_angel<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), UseItemError> {
|
||||
mag_cell(entity_gateway, used_cell, inventory, MagCell::HeartOfAngel).await
|
||||
}
|
||||
|
||||
pub async fn kit_of_hamburger<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), UseItemError> {
|
||||
mag_cell(entity_gateway, used_cell, inventory, MagCell::KitOfHamburger).await
|
||||
}
|
||||
|
||||
pub async fn panthers_spirit<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), UseItemError> {
|
||||
mag_cell(entity_gateway, used_cell, inventory, MagCell::PanthersSpirit).await
|
||||
}
|
||||
|
||||
pub async fn kit_of_mark3<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), UseItemError> {
|
||||
mag_cell(entity_gateway, used_cell, inventory, MagCell::KitOfMark3).await
|
||||
}
|
||||
|
||||
pub async fn kit_of_master_system<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), UseItemError> {
|
||||
mag_cell(entity_gateway, used_cell, inventory, MagCell::KitOfMasterSystem).await
|
||||
}
|
||||
|
||||
pub async fn kit_of_genesis<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), UseItemError> {
|
||||
mag_cell(entity_gateway, used_cell, inventory, MagCell::KitOfGenesis).await
|
||||
}
|
||||
|
||||
pub async fn kit_of_sega_saturn<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), UseItemError> {
|
||||
mag_cell(entity_gateway, used_cell, inventory, MagCell::KitOfSegaSaturn).await
|
||||
}
|
||||
|
||||
pub async fn kit_of_dreamcast<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), UseItemError> {
|
||||
mag_cell(entity_gateway, used_cell, inventory, MagCell::KitOfDreamcast).await
|
||||
}
|
||||
|
||||
pub async fn tablet<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), UseItemError> {
|
||||
mag_cell(entity_gateway, used_cell, inventory, MagCell::Tablet).await
|
||||
}
|
||||
|
||||
pub async fn dragon_scale<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), UseItemError> {
|
||||
mag_cell(entity_gateway, used_cell, inventory, MagCell::DragonScale).await
|
||||
}
|
||||
|
||||
pub async fn heaven_striker_coat<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), UseItemError> {
|
||||
mag_cell(entity_gateway, used_cell, inventory, MagCell::HeavenStrikerCoat).await
|
||||
}
|
||||
|
||||
pub async fn pioneer_parts<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), UseItemError> {
|
||||
mag_cell(entity_gateway, used_cell, inventory, MagCell::PioneerParts).await
|
||||
}
|
||||
|
||||
pub async fn amities_memo<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), UseItemError> {
|
||||
mag_cell(entity_gateway, used_cell, inventory, MagCell::AmitiesMemo).await
|
||||
}
|
||||
|
||||
pub async fn heart_of_morolian<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), UseItemError> {
|
||||
mag_cell(entity_gateway, used_cell, inventory, MagCell::HeartOfMorolian).await
|
||||
}
|
||||
|
||||
pub async fn rappys_beak<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), UseItemError> {
|
||||
mag_cell(entity_gateway, used_cell, inventory, MagCell::RappysBeak).await
|
||||
}
|
||||
|
||||
pub async fn yahoos_engine<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), UseItemError> {
|
||||
mag_cell(entity_gateway, used_cell, inventory, MagCell::YahoosEngine).await
|
||||
}
|
||||
|
||||
pub async fn d_photon_core<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), UseItemError> {
|
||||
mag_cell(entity_gateway, used_cell, inventory, MagCell::DPhotonCore).await
|
||||
}
|
||||
|
||||
pub async fn liberta_kit<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory) -> Result<(), UseItemError> {
|
||||
mag_cell(entity_gateway, used_cell, inventory, MagCell::LibertaKit).await
|
||||
}
|
@ -263,50 +263,9 @@ where
|
||||
EG: EntityGateway
|
||||
{
|
||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||
|
||||
let item_used_type = item_manager.player_consumes_tool(entity_gateway, &client.character, ClientItemId(player_use_tool.item_id), 1).await?;
|
||||
|
||||
match item_used_type {
|
||||
ItemDetail::Weapon(_w) => {
|
||||
// something like when items are used to combine/transform them?
|
||||
//_ => {}
|
||||
},
|
||||
ItemDetail::Tool(t) => {
|
||||
match t.tool {
|
||||
ToolType::PowerMaterial => {
|
||||
client.character.materials.power += 1;
|
||||
entity_gateway.save_character(&client.character).await;
|
||||
},
|
||||
ToolType::MindMaterial => {
|
||||
client.character.materials.mind += 1;
|
||||
entity_gateway.save_character(&client.character).await;
|
||||
},
|
||||
ToolType::EvadeMaterial => {
|
||||
client.character.materials.evade += 1;
|
||||
entity_gateway.save_character(&client.character).await;
|
||||
},
|
||||
ToolType::DefMaterial => {
|
||||
client.character.materials.def += 1;
|
||||
entity_gateway.save_character(&client.character).await;
|
||||
},
|
||||
ToolType::LuckMaterial => {
|
||||
client.character.materials.luck += 1;
|
||||
entity_gateway.save_character(&client.character).await;
|
||||
},
|
||||
ToolType::HpMaterial => {
|
||||
client.character.materials.hp += 1;
|
||||
entity_gateway.save_character(&client.character).await;
|
||||
},
|
||||
ToolType::TpMaterial => {
|
||||
client.character.materials.tp += 1;
|
||||
entity_gateway.save_character(&client.character).await;
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
item_manager.use_item(item_used_type, entity_gateway, &mut client.character).await?;
|
||||
Ok(Box::new(None.into_iter()))
|
||||
}
|
||||
|
||||
@ -326,4 +285,25 @@ EG: EntityGateway
|
||||
} else {
|
||||
Err(ShipError::NotEnoughMeseta(id, client.character.meseta))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub async fn player_feed_mag<EG>(id: ClientId,
|
||||
mag_feed: &PlayerFeedMag,
|
||||
entity_gateway: &mut EG,
|
||||
client_location: &ClientLocation,
|
||||
clients: &Clients,
|
||||
item_manager: &mut ItemManager)
|
||||
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, ShipError>
|
||||
where
|
||||
EG: EntityGateway
|
||||
{
|
||||
let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||
item_manager.player_feeds_mag_item(entity_gateway, &client.character, ClientItemId(mag_feed.mag_id), ClientItemId(mag_feed.item_id)).await?;
|
||||
|
||||
let mag_feed = mag_feed.clone();
|
||||
Ok(Box::new(client_location.get_client_neighbors(id).unwrap().into_iter()
|
||||
.map(move |client| {
|
||||
(client.client, SendShipPacket::Message(Message::new(GameMessage::PlayerFeedMag(mag_feed.clone()))))
|
||||
})))
|
||||
}
|
||||
|
@ -348,6 +348,9 @@ impl<EG: EntityGateway> ShipServerState<EG> {
|
||||
GameMessage::PlayerUsedMedicalCenter(player_used_medical_center) => {
|
||||
handler::message::player_used_medical_center(id, &player_used_medical_center, &mut self.entity_gateway, &mut self.clients).await
|
||||
},
|
||||
GameMessage::PlayerFeedMag(player_feed_mag) => {
|
||||
handler::message::player_feed_mag(id, &player_feed_mag, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager).await
|
||||
},
|
||||
_ => {
|
||||
let cmsg = msg.clone();
|
||||
Ok(Box::new(self.client_location.get_client_neighbors(id).unwrap().into_iter()
|
||||
|
210
tests/test_mags.rs
Normal file
210
tests/test_mags.rs
Normal file
@ -0,0 +1,210 @@
|
||||
use elseware::common::serverstate::{ClientId, ServerState};
|
||||
use elseware::entity::gateway::{EntityGateway, InMemoryGateway};
|
||||
use elseware::entity::item;
|
||||
use elseware::ship::ship::{ShipServerState, RecvShipPacket, SendShipPacket};
|
||||
use elseware::entity::character::{CharacterClass, SectionID};
|
||||
|
||||
use libpso::packet::ship::*;
|
||||
use libpso::packet::messages::*;
|
||||
|
||||
#[path = "common.rs"]
|
||||
mod common;
|
||||
use common::*;
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_mag_feed() {
|
||||
let mut entity_gateway = InMemoryGateway::new();
|
||||
|
||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
|
||||
entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Mag(
|
||||
item::mag::Mag::baby_mag(0)
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 0,
|
||||
equipped: true,
|
||||
}
|
||||
}).await;
|
||||
for _ in 0..7 {
|
||||
entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool(
|
||||
item::tool::Tool {
|
||||
tool: item::tool::ToolType::Monomate,
|
||||
}
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 1,
|
||||
equipped: false,
|
||||
}
|
||||
}).await;
|
||||
}
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
create_room(&mut ship, ClientId(1), "room", "").await;
|
||||
|
||||
for _ in 0..7 {
|
||||
ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerFeedMag(PlayerFeedMag {
|
||||
client: 0,
|
||||
target: 0,
|
||||
mag_id: 0x10000,
|
||||
item_id: 0x10001,
|
||||
})))).await.unwrap().for_each(drop);
|
||||
}
|
||||
|
||||
let p1_items = entity_gateway.get_items_by_character(&char1).await;
|
||||
let mag = p1_items.get(0).unwrap();
|
||||
match &mag.item {
|
||||
item::ItemDetail::Mag(mag) => {
|
||||
assert!(mag.level() == 7);
|
||||
assert!(mag.def() == 5);
|
||||
assert!(mag.pow() == 2);
|
||||
assert!(mag.dex() == 0);
|
||||
assert!(mag.mind() == 0);
|
||||
}
|
||||
_ => panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_mag_change_owner() {
|
||||
let mut entity_gateway = InMemoryGateway::new();
|
||||
|
||||
let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
let (_user2, mut char2) = new_user_character(&mut entity_gateway, "a2", "a").await;
|
||||
char1.char_class = CharacterClass::RAmarl;
|
||||
char1.section_id = SectionID::Redria;
|
||||
entity_gateway.save_character(&char1).await;
|
||||
char2.char_class = CharacterClass::FOmarl;
|
||||
char2.section_id = SectionID::Whitill;
|
||||
entity_gateway.save_character(&char2).await;
|
||||
|
||||
entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Mag(
|
||||
item::mag::Mag::baby_mag(0)
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 0,
|
||||
equipped: true,
|
||||
}
|
||||
}).await;
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
log_in_char(&mut ship, ClientId(2), "a2", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
join_lobby(&mut ship, ClientId(2)).await;
|
||||
create_room(&mut ship, ClientId(1), "room", "").await;
|
||||
join_room(&mut ship, ClientId(2), 0).await;
|
||||
|
||||
ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerDropItem(PlayerDropItem {
|
||||
client: 0,
|
||||
target: 0,
|
||||
unknown1: 0,
|
||||
map_area: 0,
|
||||
item_id: 0x10000,
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
z: 0.0,
|
||||
})))).await.unwrap().for_each(drop);
|
||||
|
||||
ship.handle(ClientId(2), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem {
|
||||
client: 0,
|
||||
target: 0,
|
||||
item_id: 0x10000,
|
||||
map_area: 0,
|
||||
unknown: [0; 3]
|
||||
})))).await.unwrap().for_each(drop);
|
||||
|
||||
let p2_items = entity_gateway.get_items_by_character(&char2).await;
|
||||
let mag = p2_items.get(0).unwrap();
|
||||
match &mag.item {
|
||||
item::ItemDetail::Mag(mag) => {
|
||||
assert!(mag.class == CharacterClass::FOmarl);
|
||||
assert!(mag.id == SectionID::Whitill);
|
||||
},
|
||||
_ => panic!()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_mag_cell() {
|
||||
let mut entity_gateway = InMemoryGateway::new();
|
||||
|
||||
let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await;
|
||||
|
||||
let mag = entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Mag(
|
||||
item::mag::Mag::baby_mag(0)
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 0,
|
||||
equipped: true,
|
||||
}
|
||||
}).await.unwrap();
|
||||
|
||||
for _ in 0..1000 {
|
||||
let fed_tool = entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool (
|
||||
item::tool::Tool {
|
||||
tool: item::tool::ToolType::Monomate,
|
||||
}
|
||||
),
|
||||
location: item::ItemLocation::FedToMag {
|
||||
mag: mag.id,
|
||||
}
|
||||
}).await.unwrap();
|
||||
entity_gateway.feed_mag(&mag.id, &fed_tool.id).await;
|
||||
}
|
||||
entity_gateway.create_item(
|
||||
item::NewItemEntity {
|
||||
item: item::ItemDetail::Tool(
|
||||
item::tool::Tool {
|
||||
tool: item::tool::ToolType::CellOfMag502,
|
||||
}
|
||||
),
|
||||
location: item::ItemLocation::Inventory {
|
||||
character_id: char1.id,
|
||||
slot: 1,
|
||||
equipped: false,
|
||||
}
|
||||
}).await;
|
||||
|
||||
let mut ship = ShipServerState::builder()
|
||||
.gateway(entity_gateway.clone())
|
||||
.build();
|
||||
log_in_char(&mut ship, ClientId(1), "a1", "a").await;
|
||||
join_lobby(&mut ship, ClientId(1)).await;
|
||||
create_room(&mut ship, ClientId(1), "room", "").await;
|
||||
|
||||
ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerUseItem(PlayerUseItem {
|
||||
client: 0,
|
||||
target: 0,
|
||||
item_id: 0x10001,
|
||||
})))).await.unwrap().for_each(drop);
|
||||
|
||||
let p1_items = entity_gateway.get_items_by_character(&char1).await;
|
||||
let mag = p1_items.get(0).unwrap();
|
||||
match &mag.item {
|
||||
item::ItemDetail::Mag(mag) => {
|
||||
assert!(mag.mag == item::mag::MagType::Soniti);
|
||||
}
|
||||
_ => panic!()
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user