|
@ -2,7 +2,6 @@ use std::collections::HashMap; |
|
|
use rand::{Rng, SeedableRng};
|
|
|
use rand::{Rng, SeedableRng};
|
|
|
use rand::distributions::{WeightedIndex, Distribution};
|
|
|
use rand::distributions::{WeightedIndex, Distribution};
|
|
|
use serde::{Serialize, Deserialize};
|
|
|
use serde::{Serialize, Deserialize};
|
|
|
use crate::entity::item::ItemDetail;
|
|
|
|
|
|
use crate::entity::item::weapon::{Weapon, WeaponType};
|
|
|
use crate::entity::item::weapon::{Weapon, WeaponType};
|
|
|
use crate::entity::item::armor::{Armor, ArmorType};
|
|
|
use crate::entity::item::armor::{Armor, ArmorType};
|
|
|
use crate::entity::item::shield::{Shield, ShieldType};
|
|
|
use crate::entity::item::shield::{Shield, ShieldType};
|
|
@ -12,7 +11,7 @@ use crate::entity::character::SectionID; |
|
|
use crate::ship::monster::MonsterType;
|
|
|
use crate::ship::monster::MonsterType;
|
|
|
use crate::ship::room::{Difficulty, Episode};
|
|
|
use crate::ship::room::{Difficulty, Episode};
|
|
|
use crate::ship::map::MapVariantType;
|
|
|
use crate::ship::map::MapVariantType;
|
|
|
use crate::ship::drops::load_data_file;
|
|
|
|
|
|
|
|
|
use crate::ship::drops::{ItemDropType, load_data_file};
|
|
|
use crate::ship::map::{MapObject, MapObjectType, FixedBoxDropType};
|
|
|
use crate::ship::map::{MapObject, MapObjectType, FixedBoxDropType};
|
|
|
use crate::ship::drops::rare_drop_table::{RareDropTable, RareDropItem};
|
|
|
use crate::ship::drops::rare_drop_table::{RareDropTable, RareDropItem};
|
|
|
use crate::ship::drops::generic_weapon::GenericWeaponTable;
|
|
|
use crate::ship::drops::generic_weapon::GenericWeaponTable;
|
|
@ -172,7 +171,7 @@ impl BoxDropTable { |
|
|
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
fn rare_drop<R: Rng>(&self, map_area: &MapVariantType, rng: &mut R) -> Option<ItemDetail> {
|
|
|
|
|
|
|
|
|
fn rare_drop<R: Rng>(&self, map_area: &MapVariantType, rng: &mut R) -> Option<ItemDropType> {
|
|
|
self.rare_rates.rates_by_area(map_area).iter()
|
|
|
self.rare_rates.rates_by_area(map_area).iter()
|
|
|
.filter_map(|rate| {
|
|
|
.filter_map(|rate| {
|
|
|
let rand: f32 = rng.gen();
|
|
|
let rand: f32 = rng.gen();
|
|
@ -185,7 +184,7 @@ impl BoxDropTable { |
|
|
}).nth(0)
|
|
|
}).nth(0)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
fn random_box_drop<R: Rng>(&self, map_area: &MapVariantType, rng: &mut R) -> Option<ItemDetail> {
|
|
|
|
|
|
|
|
|
fn random_box_drop<R: Rng>(&self, map_area: &MapVariantType, rng: &mut R) -> Option<ItemDropType> {
|
|
|
self.rare_drop(map_area, rng).or_else(|| {
|
|
|
self.rare_drop(map_area, rng).or_else(|| {
|
|
|
let rate = self.box_rates.rates_by_area(map_area);
|
|
|
let rate = self.box_rates.rates_by_area(map_area);
|
|
|
let type_weights = WeightedIndex::new(&[rate.weapon_rate, rate.armor_rate, rate.shield_rate, rate.unit_rate,
|
|
|
let type_weights = WeightedIndex::new(&[rate.weapon_rate, rate.armor_rate, rate.shield_rate, rate.unit_rate,
|
|
@ -197,24 +196,27 @@ impl BoxDropTable { |
|
|
2 => self.shield_table.get_drop(map_area, rng),
|
|
|
2 => self.shield_table.get_drop(map_area, rng),
|
|
|
3 => self.unit_table.get_drop(map_area, rng),
|
|
|
3 => self.unit_table.get_drop(map_area, rng),
|
|
|
4 => self.tool_table.get_drop(map_area, rng),
|
|
|
4 => self.tool_table.get_drop(map_area, rng),
|
|
|
//5 => meseta drop
|
|
|
|
|
|
|
|
|
5 => Some(ItemDropType::Meseta(rng.gen_range(rate.min_meseta, rate.max_meseta))),
|
|
|
_ => None,
|
|
|
_ => None,
|
|
|
}
|
|
|
}
|
|
|
})
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
fn fixed_box_drop<R: Rng>(&self, fixed_drop: FixedBoxDropType, map_area: &MapVariantType, rng: &mut R) -> Option<ItemDetail> {
|
|
|
|
|
|
|
|
|
fn fixed_box_drop<R: Rng>(&self, fixed_drop: FixedBoxDropType, map_area: &MapVariantType, rng: &mut R) -> Option<ItemDropType> {
|
|
|
match fixed_drop {
|
|
|
match fixed_drop {
|
|
|
FixedBoxDropType::Weapon => self.weapon_table.get_drop(map_area, rng),
|
|
|
FixedBoxDropType::Weapon => self.weapon_table.get_drop(map_area, rng),
|
|
|
FixedBoxDropType::Armor => self.armor_table.get_drop(map_area, rng), // TODO: should this drop shield?
|
|
|
FixedBoxDropType::Armor => self.armor_table.get_drop(map_area, rng), // TODO: should this drop shield?
|
|
|
FixedBoxDropType::Tool => self.tool_table.get_drop(map_area, rng),
|
|
|
FixedBoxDropType::Tool => self.tool_table.get_drop(map_area, rng),
|
|
|
FixedBoxDropType::Meseta => panic!(),
|
|
|
|
|
|
|
|
|
FixedBoxDropType::Meseta => {
|
|
|
|
|
|
let rate = self.box_rates.rates_by_area(map_area);
|
|
|
|
|
|
Some(ItemDropType::Meseta(rng.gen_range(rate.min_meseta, rate.max_meseta)))
|
|
|
|
|
|
},
|
|
|
FixedBoxDropType::Random => self.random_box_drop(map_area, rng),
|
|
|
FixedBoxDropType::Random => self.random_box_drop(map_area, rng),
|
|
|
FixedBoxDropType::Specific(value) => panic!(),
|
|
|
FixedBoxDropType::Specific(value) => panic!(),
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
pub fn get_drop<R: Rng>(&self, map_area: &MapVariantType, object: &MapObject, rng: &mut R) -> Option<ItemDetail> {
|
|
|
|
|
|
|
|
|
pub fn get_drop<R: Rng>(&self, map_area: &MapVariantType, object: &MapObject, rng: &mut R) -> Option<ItemDropType> {
|
|
|
match object.object {
|
|
|
match object.object {
|
|
|
MapObjectType::Box | MapObjectType::EnemyBox | MapObjectType::RuinsBox| MapObjectType::RuinsEnemyBox
|
|
|
MapObjectType::Box | MapObjectType::EnemyBox | MapObjectType::RuinsBox| MapObjectType::RuinsEnemyBox
|
|
|
| MapObjectType::CcaBox => {
|
|
|
| MapObjectType::CcaBox => {
|
|
|