load rare monster config file each time a room is created
This commit is contained in:
parent
080e939e56
commit
39660f0cb8
@ -1,15 +1,9 @@
|
|||||||
|
# 1/10 = 0.1
|
||||||
# 1/100 = 0.01
|
# 1/100 = 0.01
|
||||||
# 1/256 = 0.00390625
|
# 1/256 = 0.00390625
|
||||||
# 1/512 = 0.001953125
|
# 1/512 = 0.001953125
|
||||||
|
|
||||||
[[Hildebear]]
|
Hildebear = 1.0
|
||||||
appear_rate = 0.01
|
RagRappy = 0.1
|
||||||
|
PoisonLily = 0.1
|
||||||
[[RagRappy]]
|
PofuillySlime = 0.1
|
||||||
appear_rate = 0.01
|
|
||||||
|
|
||||||
[[PoisonLily]]
|
|
||||||
appear_rate = 0.01
|
|
||||||
|
|
||||||
[[PofuillySlime]]
|
|
||||||
appear_rate = 0.01
|
|
@ -1,13 +1,9 @@
|
|||||||
|
# 1/10 = 0.1
|
||||||
# 1/100 = 0.01
|
# 1/100 = 0.01
|
||||||
# 1/256 = 0.00390625
|
# 1/256 = 0.00390625
|
||||||
# 1/512 = 0.001953125
|
# 1/512 = 0.001953125
|
||||||
|
|
||||||
[[Hildebear]]
|
Hildebear = 0.01
|
||||||
appear_rate = 0.01
|
RagRappy = 0.01
|
||||||
|
PoisonLily = 0.01
|
||||||
[[RagRappy]]
|
|
||||||
appear_rate = 0.01
|
|
||||||
|
|
||||||
[[PoisonLily]]
|
|
||||||
appear_rate = 0.01
|
|
||||||
|
|
||||||
|
@ -1,27 +1,13 @@
|
|||||||
|
# 1/10 = 0.1
|
||||||
# 1/100 = 0.01
|
# 1/100 = 0.01
|
||||||
# 1/256 = 0.00390625
|
# 1/256 = 0.00390625
|
||||||
# 1/512 = 0.001953125
|
# 1/512 = 0.001953125
|
||||||
|
|
||||||
[[SandRappyCrater]]
|
SandRappyCrater = 0.01
|
||||||
appear_rate = 0.01
|
ZuCrater = 0.01
|
||||||
|
Dorphon = 0.01
|
||||||
[[ZuCrater]]
|
SandRappyDesert = 0.01
|
||||||
appear_rate = 0.01
|
ZuDesert = 0.01
|
||||||
|
MerissaA = 0.01
|
||||||
[[Dorphon]]
|
Shambertin = 0.1
|
||||||
appear_rate = 0.01
|
SaintMillion = 0.1
|
||||||
|
|
||||||
[[SandRappyDesert]]
|
|
||||||
appear_rate = 0.01
|
|
||||||
|
|
||||||
[[ZuDesert]]
|
|
||||||
appear_rate = 0.01
|
|
||||||
|
|
||||||
[[MerissaA]]
|
|
||||||
appear_rate = 0.01
|
|
||||||
|
|
||||||
[[Shambertin]]
|
|
||||||
appear_rate = 0.1
|
|
||||||
|
|
||||||
[[SaintMillion]]
|
|
||||||
appear_rate = 0.1
|
|
@ -58,8 +58,8 @@ pub fn load_data_file<T: serde::de::DeserializeOwned>(episode: Episode, difficul
|
|||||||
// this is just copypaste
|
// this is just copypaste
|
||||||
pub fn load_rare_monster_file<T: serde::de::DeserializeOwned>(episode: Episode) -> T {
|
pub fn load_rare_monster_file<T: serde::de::DeserializeOwned>(episode: Episode) -> T {
|
||||||
let mut path = PathBuf::from("data/battle_param/");
|
let mut path = PathBuf::from("data/battle_param/");
|
||||||
path.push(episode.to_string().to_lowercase());
|
path.push(episode.to_string().to_lowercase() + "_rare_monster.toml");
|
||||||
path.push("_rare_monster.toml");
|
println!("rare monster file path: {:?}", path);
|
||||||
|
|
||||||
let mut f = File::open(path).unwrap();
|
let mut f = File::open(path).unwrap();
|
||||||
let mut s = String::new();
|
let mut s = String::new();
|
||||||
|
@ -208,6 +208,54 @@ impl MapArea {
|
|||||||
// MapArea::TestMapEp4 => 10,
|
// MapArea::TestMapEp4 => 10,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn to_episode(self) -> Episode {
|
||||||
|
match self {
|
||||||
|
Pioneer2Ep1 => Episode::One,
|
||||||
|
Forest1 => Episode::One,
|
||||||
|
Forest2 => Episode::One,
|
||||||
|
Caves1 => Episode::One,
|
||||||
|
Caves2 => Episode::One,
|
||||||
|
Caves3 => Episode::One,
|
||||||
|
Mines1 => Episode::One,
|
||||||
|
Mines2 => Episode::One,
|
||||||
|
Ruins1 => Episode::One,
|
||||||
|
Ruins2 => Episode::One,
|
||||||
|
Ruins3 => Episode::One,
|
||||||
|
Dragon => Episode::One,
|
||||||
|
DeRolLe => Episode::One,
|
||||||
|
VolOpt => Episode::One,
|
||||||
|
DarkFalz => Episode::One,
|
||||||
|
Pioneer2Ep2 => Episode::Two,
|
||||||
|
VrTempleAlpha => Episode::Two,
|
||||||
|
VrTempleBeta => Episode::Two,
|
||||||
|
VrSpaceshipAlpha => Episode::Two,
|
||||||
|
VrSpaceshipBeta => Episode::Two,
|
||||||
|
Cca => Episode::Two,
|
||||||
|
JungleAreaNorth => Episode::Two,
|
||||||
|
JungleAreaEast => Episode::Two,
|
||||||
|
Mountain => Episode::Two,
|
||||||
|
Seaside => Episode::Two,
|
||||||
|
SeabedUpper => Episode::Two,
|
||||||
|
SeabedLower => Episode::Two,
|
||||||
|
GalGryphon => Episode::Two,
|
||||||
|
OlgaFlow => Episode::Two,
|
||||||
|
BarbaRay => Episode::Two,
|
||||||
|
GolDragon => Episode::Two,
|
||||||
|
SeasideNight => Episode::Two,
|
||||||
|
Tower => Episode::Two,
|
||||||
|
Pioneer2Ep4 => Episode::Four,
|
||||||
|
CraterEast => Episode::Four,
|
||||||
|
CraterWest => Episode::Four,
|
||||||
|
CraterSouth => Episode::Four,
|
||||||
|
CraterNorth => Episode::Four,
|
||||||
|
CraterInterior => Episode::Four,
|
||||||
|
SubDesert1 => Episode::Four,
|
||||||
|
SubDesert2 => Episode::Four,
|
||||||
|
SubDesert3 => Episode::Four,
|
||||||
|
SaintMillion => Episode::Four,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -75,25 +75,27 @@ pub enum MapEnemyError {
|
|||||||
MapAreaError(#[from] MapAreaError),
|
MapAreaError(#[from] MapAreaError),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
// TODO: is this even needed/used?
|
||||||
pub struct RareMonsterAppearRate(pub f32);
|
// #[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
// pub type RareMonsterAppearRate: HashMap<MonsterType, f32>,
|
||||||
|
|
||||||
// making this `pub type` doesn't allow `impl`s to be defined?
|
// making this `pub type` doesn't allow `impl`s to be defined?
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct RareMonsterAppearTable {
|
pub struct RareMonsterAppearTable {
|
||||||
appear_rate: HashMap<MonsterType, RareMonsterAppearRate>,
|
appear_rate: HashMap<MonsterType, f32>,
|
||||||
seed: u32,
|
seed: u32
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RareMonsterAppearTable {
|
impl RareMonsterAppearTable {
|
||||||
pub fn new(episode: Episode, room_seed: u32) -> RareMonsterAppearTable {
|
pub fn new(episode: Episode, room_seed: u32) -> RareMonsterAppearTable {
|
||||||
let cfg: HashMap<String, f32> = load_rare_monster_file(episode);
|
let cfg: HashMap<String, f32> = load_rare_monster_file(episode);
|
||||||
|
println!("got cfg: {:?}", cfg);
|
||||||
|
|
||||||
let appear_rates: HashMap<MonsterType, RareMonsterAppearRate> = cfg
|
let appear_rates: HashMap<MonsterType, f32> = cfg
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(monster, appear_rate)| {
|
.map(|(monster, rate)| {
|
||||||
let monster: MonsterType = monster.parse().unwrap();
|
let monster: MonsterType = monster.parse().unwrap(); // TODO: don't unwrap!
|
||||||
let appear_rate = RareMonsterAppearRate(appear_rate);
|
let appear_rate = rate;
|
||||||
(monster, appear_rate)
|
(monster, appear_rate)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
@ -105,11 +107,14 @@ impl RareMonsterAppearTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn roll_appearance(&self, monster: &MonsterType) -> bool {
|
pub fn roll_appearance(&self, monster: &MonsterType) -> bool {
|
||||||
let mut rng = rand_chacha::ChaChaRng::seed_from_u64(self.seed as u64);
|
let mut rng = rand_chacha::ChaChaRng::seed_from_u64(self.seed as u64); // TODO: figure out how to seed with a u32
|
||||||
if rng.gen::<f32>() < self.appear_rate.get(monster).unwrap_or(&RareMonsterAppearRate(0.0f32)).0 {
|
println!("rolling for {:?} appearance", monster);
|
||||||
|
if rng.gen::<f32>() < *self.appear_rate.get(monster).unwrap_or(&0.0f32) {
|
||||||
|
println!("its a rare!");
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
println!("lol sucker");
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -331,5 +336,59 @@ impl MapEnemy {
|
|||||||
..self
|
..self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: does this actually do anything useful?
|
||||||
|
pub fn has_rare_appearance(self) -> bool {
|
||||||
|
match self.monster {
|
||||||
|
MonsterType::RagRappy | MonsterType::Hildebear |
|
||||||
|
MonsterType::PoisonLily | MonsterType::PofuillySlime |
|
||||||
|
MonsterType::SandRappyCrater | MonsterType::ZuCrater | MonsterType::Dorphon |
|
||||||
|
MonsterType::SandRappyDesert | MonsterType::ZuDesert | MonsterType::MerissaA |
|
||||||
|
MonsterType::SaintMillion | MonsterType::Shambertin => true,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: does `shiny` need to be set here?
|
||||||
|
// TODO: distinguish between a `random` rare monster and a `set/guaranteed` rare monster? (does any acceptable quest even have this?)
|
||||||
|
pub fn set_rare_appearance(self) -> MapEnemy {
|
||||||
|
match self.monster {
|
||||||
|
MonsterType::RagRappy | MonsterType::Hildebear |
|
||||||
|
MonsterType::PoisonLily | MonsterType::PofuillySlime |
|
||||||
|
MonsterType::SandRappyCrater | MonsterType::ZuCrater | MonsterType::Dorphon |
|
||||||
|
MonsterType::SandRappyDesert | MonsterType::ZuDesert | MonsterType::MerissaA |
|
||||||
|
MonsterType::SaintMillion | MonsterType::Shambertin => self.set_shiny(),
|
||||||
|
_ => self,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// // TODO: does `shiny` need to be set here?
|
||||||
|
// // TODO: distinguish between a `random` rare monster and a `set/guaranteed` rare monster? (does any acceptable quest even have this?)
|
||||||
|
// pub fn set_rare_appearance(self) -> MapEnemy {
|
||||||
|
// match (self.monster, self.map_area.to_episode()) {
|
||||||
|
// (MonsterType::RagRappy, Episode::One) => {MapEnemy {monster: MonsterType::AlRappy, ..self}},
|
||||||
|
// (MonsterType::RagRappy, Episode::Two) => {MapEnemy {monster: MonsterType::EventRappy, ..self}},
|
||||||
|
// (MonsterType::Hildebear, _) => {MapEnemy {monster: MonsterType::Hildeblue, ..self}},
|
||||||
|
// (MonsterType::PoisonLily, _) => {MapEnemy {monster: MonsterType::NarLily, ..self}},
|
||||||
|
// (MonsterType::PofuillySlime, _) => {MapEnemy {monster: MonsterType::PouillySlime, ..self}},
|
||||||
|
// (MonsterType::SandRappyCrater, _) => {MapEnemy {monster: MonsterType::DelRappyCrater, ..self}},
|
||||||
|
// (MonsterType::ZuCrater, _) => {MapEnemy {monster: MonsterType::PazuzuCrater, ..self}},
|
||||||
|
// (MonsterType::Dorphon, _) => {MapEnemy {monster: MonsterType::DorphonEclair, ..self}},
|
||||||
|
// (MonsterType::SandRappyDesert, _) => {MapEnemy {monster: MonsterType::DelRappyDesert, ..self}},
|
||||||
|
// (MonsterType::ZuDesert, _) => {MapEnemy {monster: MonsterType::PazuzuDesert, ..self}},
|
||||||
|
// (MonsterType::MerissaA, _) => {MapEnemy {monster: MonsterType::MerissaAA, ..self}},
|
||||||
|
// (MonsterType::SaintMillion, _) => {MapEnemy {monster: MonsterType::Kondrieu, ..self}},
|
||||||
|
// (MonsterType::Shambertin, _) => {MapEnemy {monster: MonsterType::Kondrieu, ..self}},
|
||||||
|
// _ => {self},
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// in theory this should only be called on monsters we know can have rare types
|
||||||
|
pub fn roll_appearance_for_quest(self, rare_monster_table: &RareMonsterAppearTable) -> MapEnemy {
|
||||||
|
if rare_monster_table.roll_appearance(&self.monster) {
|
||||||
|
return self.set_rare_appearance()
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ use crate::ship::room::{Episode, RoomMode};
|
|||||||
// TODO: don't use *
|
// TODO: don't use *
|
||||||
use crate::ship::map::*;
|
use crate::ship::map::*;
|
||||||
|
|
||||||
use rand::{Rng};
|
// use rand::{Rng};
|
||||||
|
|
||||||
|
|
||||||
pub fn objects_from_stream(cursor: &mut impl Read, episode: &Episode, map_area: &MapArea) -> Vec<Option<MapObject>> {
|
pub fn objects_from_stream(cursor: &mut impl Read, episode: &Episode, map_area: &MapArea) -> Vec<Option<MapObject>> {
|
||||||
@ -31,10 +31,10 @@ fn objects_from_map_data(path: PathBuf, episode: &Episode, map_area: &MapArea) -
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_enemy(episode: &Episode, map_area: &MapArea, raw_enemy: RawMapEnemy) -> Vec<Option<MapEnemy>> {
|
fn parse_enemy(episode: &Episode, map_area: &MapArea, raw_enemy: RawMapEnemy) -> Vec<Option<MapEnemy>> {
|
||||||
|
// fn parse_enemy(episode: &Episode, map_area: &MapArea, raw_enemy: RawMapEnemy, rare_monster_table: RareMonsterAppearTable) -> Vec<Option<MapEnemy>> {
|
||||||
let enemy = MapEnemy::from_raw(raw_enemy, episode, map_area);
|
let enemy = MapEnemy::from_raw(raw_enemy, episode, map_area);
|
||||||
/*
|
|
||||||
TODO: load rare monster rates config
|
// TODO: load rare monster rates config
|
||||||
*/
|
|
||||||
enemy
|
enemy
|
||||||
.map_or(vec![None], |monster| {
|
.map_or(vec![None], |monster| {
|
||||||
let mut monsters = Vec::new();
|
let mut monsters = Vec::new();
|
||||||
@ -43,7 +43,8 @@ fn parse_enemy(episode: &Episode, map_area: &MapArea, raw_enemy: RawMapEnemy) ->
|
|||||||
match monster.monster {
|
match monster.monster {
|
||||||
// TODO: make real spawn rates
|
// TODO: make real spawn rates
|
||||||
// TODO: specific ep 2 event rappies
|
// TODO: specific ep 2 event rappies
|
||||||
MonsterType::RagRappy => {if rand::thread_rng().gen_range(0, 100) < 11 {
|
// MonsterType::RagRappy => {if rand::thread_rng().gen_range(0, 100) < 11 {
|
||||||
|
/* MonsterType::RagRappy => {if rare_monster_table.roll_appearance(&monster.monster) {
|
||||||
monsters.pop();
|
monsters.pop();
|
||||||
match episode {
|
match episode {
|
||||||
Episode::One => {monsters.push(Some(MapEnemy::new(MonsterType::AlRappy, monster.map_area).set_shiny()))},
|
Episode::One => {monsters.push(Some(MapEnemy::new(MonsterType::AlRappy, monster.map_area).set_shiny()))},
|
||||||
@ -52,11 +53,13 @@ fn parse_enemy(episode: &Episode, map_area: &MapArea, raw_enemy: RawMapEnemy) ->
|
|||||||
}
|
}
|
||||||
|
|
||||||
}},
|
}},
|
||||||
MonsterType::Hildebear => {if rand::thread_rng().gen_range(0, 100) < 11 {
|
// MonsterType::Hildebear => {if rand::thread_rng().gen_range(0, 100) < 11 {
|
||||||
|
MonsterType::Hildebear => {if rare_monster_table.roll_appearance(&monster.monster) {
|
||||||
monsters.pop();
|
monsters.pop();
|
||||||
monsters.push(Some(MapEnemy::new(MonsterType::Hildeblue, monster.map_area).set_shiny()))
|
monsters.push(Some(MapEnemy::new(MonsterType::Hildeblue, monster.map_area).set_shiny()))
|
||||||
}},
|
}},
|
||||||
MonsterType::PoisonLily => {if rand::thread_rng().gen_range(0, 100) < 11 {
|
// MonsterType::PoisonLily => {if rand::thread_rng().gen_range(0, 100) < 11 {
|
||||||
|
MonsterType::PoisonLily => {if rare_monster_table.roll_appearance(&monster.monster) {
|
||||||
monsters.pop();
|
monsters.pop();
|
||||||
monsters.push(Some(MapEnemy::new(MonsterType::NarLily, monster.map_area).set_shiny()))
|
monsters.push(Some(MapEnemy::new(MonsterType::NarLily, monster.map_area).set_shiny()))
|
||||||
}},
|
}},
|
||||||
@ -64,7 +67,8 @@ fn parse_enemy(episode: &Episode, map_area: &MapArea, raw_enemy: RawMapEnemy) ->
|
|||||||
MonsterType::PofuillySlime => {
|
MonsterType::PofuillySlime => {
|
||||||
monsters.pop();
|
monsters.pop();
|
||||||
for _ in 0..5 {
|
for _ in 0..5 {
|
||||||
if rand::thread_rng().gen_range(0, 100) < 11 {
|
// if rand::thread_rng().gen_range(0, 100) < 11 {
|
||||||
|
if rare_monster_table.roll_appearance(&monster.monster) {
|
||||||
monsters.push(Some(MapEnemy::new(MonsterType::PouillySlime, monster.map_area).set_shiny()))
|
monsters.push(Some(MapEnemy::new(MonsterType::PouillySlime, monster.map_area).set_shiny()))
|
||||||
} else {
|
} else {
|
||||||
monsters.push(Some(MapEnemy::new(MonsterType::PofuillySlime, monster.map_area)))
|
monsters.push(Some(MapEnemy::new(MonsterType::PofuillySlime, monster.map_area)))
|
||||||
@ -75,42 +79,50 @@ fn parse_enemy(episode: &Episode, map_area: &MapArea, raw_enemy: RawMapEnemy) ->
|
|||||||
// guaranteed rare slime already pushed
|
// guaranteed rare slime already pushed
|
||||||
// roll for the other 3 (4?) copies
|
// roll for the other 3 (4?) copies
|
||||||
for _ in 0..4 {
|
for _ in 0..4 {
|
||||||
if rand::thread_rng().gen_range(0, 100) < 11 {
|
// if rand::thread_rng().gen_range(0, 100) < 11 {
|
||||||
|
if rare_monster_table.roll_appearance(&monster.monster) {
|
||||||
monsters.push(Some(MapEnemy::new(MonsterType::PouillySlime, monster.map_area).set_shiny()))
|
monsters.push(Some(MapEnemy::new(MonsterType::PouillySlime, monster.map_area).set_shiny()))
|
||||||
} else {
|
} else {
|
||||||
monsters.push(Some(MapEnemy::new(MonsterType::PofuillySlime, monster.map_area)))
|
monsters.push(Some(MapEnemy::new(MonsterType::PofuillySlime, monster.map_area)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
MonsterType::SandRappyCrater => {if rand::thread_rng().gen_range(0, 100) < 11 {
|
// MonsterType::SandRappyCrater => {if rand::thread_rng().gen_range(0, 100) < 11 {
|
||||||
|
MonsterType::SandRappyCrater => {if rare_monster_table.roll_appearance(&monster.monster) {
|
||||||
monsters.pop();
|
monsters.pop();
|
||||||
monsters.push(Some(MapEnemy::new(MonsterType::DelRappyCrater, monster.map_area).set_shiny()))
|
monsters.push(Some(MapEnemy::new(MonsterType::DelRappyCrater, monster.map_area).set_shiny()))
|
||||||
}},
|
}},
|
||||||
MonsterType::ZuCrater => {if rand::thread_rng().gen_range(0, 100) < 11 {
|
// MonsterType::ZuCrater => {if rand::thread_rng().gen_range(0, 100) < 11 {
|
||||||
|
MonsterType::ZuCrater => {if rare_monster_table.roll_appearance(&monster.monster) {
|
||||||
monsters.pop();
|
monsters.pop();
|
||||||
monsters.push(Some(MapEnemy::new(MonsterType::PazuzuCrater, monster.map_area).set_shiny()))
|
monsters.push(Some(MapEnemy::new(MonsterType::PazuzuCrater, monster.map_area).set_shiny()))
|
||||||
}},
|
}},
|
||||||
MonsterType::Dorphon => {if rand::thread_rng().gen_range(0, 100) < 11 {
|
// MonsterType::Dorphon => {if rand::thread_rng().gen_range(0, 100) < 11 {
|
||||||
|
MonsterType::Dorphon => {if rare_monster_table.roll_appearance(&monster.monster) {
|
||||||
monsters.pop();
|
monsters.pop();
|
||||||
monsters.push(Some(MapEnemy::new(MonsterType::DorphonEclair, monster.map_area).set_shiny()))
|
monsters.push(Some(MapEnemy::new(MonsterType::DorphonEclair, monster.map_area).set_shiny()))
|
||||||
}},
|
}},
|
||||||
MonsterType::SandRappyDesert => {if rand::thread_rng().gen_range(0, 100) < 11 {
|
// MonsterType::SandRappyDesert => {if rand::thread_rng().gen_range(0, 100) < 11 {
|
||||||
|
MonsterType::SandRappyDesert => {if rare_monster_table.roll_appearance(&monster.monster) {
|
||||||
monsters.pop();
|
monsters.pop();
|
||||||
monsters.push(Some(MapEnemy::new(MonsterType::DelRappyDesert, monster.map_area).set_shiny()))
|
monsters.push(Some(MapEnemy::new(MonsterType::DelRappyDesert, monster.map_area).set_shiny()))
|
||||||
}},
|
}},
|
||||||
MonsterType::ZuDesert => {if rand::thread_rng().gen_range(0, 100) < 11 {
|
// MonsterType::ZuDesert => {if rand::thread_rng().gen_range(0, 100) < 11 {
|
||||||
|
MonsterType::ZuDesert => {if rare_monster_table.roll_appearance(&monster.monster) {
|
||||||
monsters.pop();
|
monsters.pop();
|
||||||
monsters.push(Some(MapEnemy::new(MonsterType::PazuzuDesert, monster.map_area).set_shiny()))
|
monsters.push(Some(MapEnemy::new(MonsterType::PazuzuDesert, monster.map_area).set_shiny()))
|
||||||
}},
|
}},
|
||||||
MonsterType::MerissaA => {if rand::thread_rng().gen_range(0, 100) < 11 {
|
// MonsterType::MerissaA => {if rand::thread_rng().gen_range(0, 100) < 11 {
|
||||||
|
MonsterType::MerissaA => {if rare_monster_table.roll_appearance(&monster.monster) {
|
||||||
monsters.pop();
|
monsters.pop();
|
||||||
monsters.push(Some(MapEnemy::new(MonsterType::MerissaAA, monster.map_area).set_shiny()))
|
monsters.push(Some(MapEnemy::new(MonsterType::MerissaAA, monster.map_area).set_shiny()))
|
||||||
}},
|
}},
|
||||||
MonsterType::SaintMillion | MonsterType::Shambertin => {if rand::thread_rng().gen_range(0, 100) < 11 {
|
// MonsterType::SaintMillion | MonsterType::Shambertin => { if rand::thread_rng().gen_range(0, 100) < 11 {
|
||||||
|
MonsterType::SaintMillion | MonsterType::Shambertin => { if rare_monster_table.roll_appearance(&monster.monster) {
|
||||||
monsters.pop();
|
monsters.pop();
|
||||||
monsters.push(Some(MapEnemy::new(MonsterType::Kondrieu, monster.map_area).set_shiny()))
|
monsters.push(Some(MapEnemy::new(MonsterType::Kondrieu, monster.map_area).set_shiny()))
|
||||||
}},
|
}},
|
||||||
|
*/
|
||||||
|
|
||||||
MonsterType::Monest => {
|
MonsterType::Monest => {
|
||||||
for _ in 0..30 {
|
for _ in 0..30 {
|
||||||
@ -223,17 +235,21 @@ fn parse_enemy(episode: &Episode, map_area: &MapArea, raw_enemy: RawMapEnemy) ->
|
|||||||
|
|
||||||
|
|
||||||
pub fn enemy_data_from_stream(cursor: &mut impl Read, map_area: &MapArea, episode: &Episode) -> Vec<Option<MapEnemy>> {
|
pub fn enemy_data_from_stream(cursor: &mut impl Read, map_area: &MapArea, episode: &Episode) -> Vec<Option<MapEnemy>> {
|
||||||
|
// pub fn enemy_data_from_stream(cursor: &mut impl Read, map_area: &MapArea, episode: &Episode, rare_monster_table: enemy::RareMonsterAppearTable) -> Vec<Option<MapEnemy>> {
|
||||||
let mut enemy_data = Vec::new();
|
let mut enemy_data = Vec::new();
|
||||||
while let Ok(enemy) = RawMapEnemy::from_byte_stream(cursor) {
|
while let Ok(enemy) = RawMapEnemy::from_byte_stream(cursor) {
|
||||||
enemy_data.append(&mut parse_enemy(episode, map_area, enemy));
|
enemy_data.append(&mut parse_enemy(episode, map_area, enemy));
|
||||||
|
// enemy_data.append(&mut parse_enemy(episode, map_area, enemy, rare_monster_table));
|
||||||
}
|
}
|
||||||
enemy_data
|
enemy_data
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enemy_data_from_map_data(map_variant: &MapVariant, episode: &Episode) -> Vec<Option<MapEnemy>> {
|
fn enemy_data_from_map_data(map_variant: &MapVariant, episode: &Episode) -> Vec<Option<MapEnemy>> {
|
||||||
|
// fn enemy_data_from_map_data(map_variant: &MapVariant, episode: &Episode, rare_monster_table: enemy::RareMonsterAppearTable) -> Vec<Option<MapEnemy>> {
|
||||||
let path = map_variant.dat_file();
|
let path = map_variant.dat_file();
|
||||||
let mut cursor = File::open(path).unwrap();
|
let mut cursor = File::open(path).unwrap();
|
||||||
enemy_data_from_stream(&mut cursor, &map_variant.map, episode)
|
enemy_data_from_stream(&mut cursor, &map_variant.map, episode)
|
||||||
|
// enemy_data_from_stream(&mut cursor, &map_variant.map, episode, rare_monster_table)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -252,7 +268,8 @@ pub struct Maps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Maps {
|
impl Maps {
|
||||||
pub fn new(room_mode: RoomMode) -> Maps {
|
// pub fn new(room_mode: RoomMode) -> Maps {
|
||||||
|
pub fn new(room_mode: RoomMode, rare_monster_table: &enemy::RareMonsterAppearTable) -> Maps {
|
||||||
let map_variants = match (room_mode.episode(), room_mode.single_player()) {
|
let map_variants = match (room_mode.episode(), room_mode.single_player()) {
|
||||||
(Episode::One, 0) => {
|
(Episode::One, 0) => {
|
||||||
vec![MapVariant::new(MapArea::Pioneer2Ep1, MapVariantMode::Online),
|
vec![MapVariant::new(MapArea::Pioneer2Ep1, MapVariantMode::Online),
|
||||||
@ -344,16 +361,20 @@ impl Maps {
|
|||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
};
|
};
|
||||||
|
|
||||||
let maps = Maps {
|
let mut maps = Maps {
|
||||||
enemy_data: map_variants.iter().fold(Vec::new(), |mut enemy_data, map_variant| {
|
enemy_data: map_variants.iter()
|
||||||
enemy_data.append(&mut enemy_data_from_map_data(map_variant, &room_mode.episode()));
|
.fold(Vec::new(), |mut enemy_data, map_variant| {
|
||||||
enemy_data
|
enemy_data.append(&mut enemy_data_from_map_data(map_variant, &room_mode.episode()));
|
||||||
}),
|
// enemy_data.append(&mut enemy_data_from_map_data(map_variant, &room_mode.episode(), rare_monster_table));
|
||||||
object_data: map_variants.iter().map(|map_variant| {
|
enemy_data
|
||||||
objects_from_map_data(map_variant.obj_file().into(), &room_mode.episode(), &map_variant.map)
|
}),
|
||||||
}).flatten().collect(),
|
object_data: map_variants.iter()
|
||||||
map_variants,
|
.map(|map_variant| {
|
||||||
|
objects_from_map_data(map_variant.obj_file().into(), &room_mode.episode(), &map_variant.map)
|
||||||
|
}).flatten().collect(),
|
||||||
|
map_variants,
|
||||||
};
|
};
|
||||||
|
maps.roll_monster_appearance(rare_monster_table);
|
||||||
maps
|
maps
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -378,7 +399,18 @@ impl Maps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_quest_data(&mut self, enemies: Vec<Option<MapEnemy>>, objects: Vec<Option<MapObject>>) {
|
pub fn set_quest_data(&mut self, enemies: Vec<Option<MapEnemy>>, objects: Vec<Option<MapObject>>) {
|
||||||
|
// pub fn set_quest_data(&mut self, enemies: Vec<Option<MapEnemy>>, objects: Vec<Option<MapObject>>, rare_monster_table: RareMonsterAppearTable) {
|
||||||
self.enemy_data = enemies;
|
self.enemy_data = enemies;
|
||||||
|
|
||||||
|
// self.enemy_data = enemies
|
||||||
|
// .iter()
|
||||||
|
// .map(|&x| if x.is_some() {
|
||||||
|
// Some(x.unwrap().roll_appearance_for_quest(rare_monster_table))
|
||||||
|
// } else {
|
||||||
|
// x
|
||||||
|
// })
|
||||||
|
// .collect();
|
||||||
|
|
||||||
self.object_data = objects;
|
self.object_data = objects;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,4 +435,15 @@ impl Maps {
|
|||||||
}
|
}
|
||||||
rare_monsters
|
rare_monsters
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn roll_monster_appearance(&mut self, rare_monster_table: &RareMonsterAppearTable) {
|
||||||
|
self.enemy_data = self.enemy_data
|
||||||
|
.iter()
|
||||||
|
.map(|&x| if x.is_some() {
|
||||||
|
Some(x.unwrap().roll_appearance_for_quest(&rare_monster_table))
|
||||||
|
} else {
|
||||||
|
x
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
pub mod area;
|
pub mod area;
|
||||||
mod enemy;
|
pub mod enemy;
|
||||||
mod object;
|
mod object;
|
||||||
mod variant;
|
mod variant;
|
||||||
mod maps;
|
mod maps;
|
||||||
|
@ -130,9 +130,10 @@ pub fn done_bursting(id: ClientId,
|
|||||||
.flatten()
|
.flatten()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// TODO: check how often `done_bursting` is called. ie: make sure it's only used when joining a room and not each time a player warps in a pipe
|
||||||
if rare_monster_list.is_some() {
|
if rare_monster_list.is_some() {
|
||||||
let rare_monster_packet = SendShipPacket::RareMonsterList(builder::room::build_rare_monster_list(rare_monster_list.unwrap()).unwrap()); // TODO: don't double unwrap
|
let rare_monster_packet = SendShipPacket::RareMonsterList(builder::room::build_rare_monster_list(rare_monster_list.unwrap()).unwrap()); // TODO: don't double unwrap
|
||||||
result = Box::new(result.chain(vec![(id, rare_monster_packet)]));
|
result = Box::new(result.chain(vec![(id, rare_monster_packet)])); // TODO: make sure we arent clobbering `result` here
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
|
@ -7,6 +7,7 @@ use crate::ship::drops::DropTable;
|
|||||||
use crate::entity::character::SectionID;
|
use crate::entity::character::SectionID;
|
||||||
use crate::ship::monster::{load_monster_stats_table, MonsterType, MonsterStats};
|
use crate::ship::monster::{load_monster_stats_table, MonsterType, MonsterStats};
|
||||||
use crate::ship::map::area::MapAreaLookup;
|
use crate::ship::map::area::MapAreaLookup;
|
||||||
|
use crate::ship::map::enemy::RareMonsterAppearTable;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum RoomCreationError {
|
pub enum RoomCreationError {
|
||||||
@ -167,6 +168,7 @@ pub struct RoomState {
|
|||||||
pub bursting: bool,
|
pub bursting: bool,
|
||||||
pub monster_stats: Box<HashMap<MonsterType, MonsterStats>>,
|
pub monster_stats: Box<HashMap<MonsterType, MonsterStats>>,
|
||||||
pub map_areas: MapAreaLookup,
|
pub map_areas: MapAreaLookup,
|
||||||
|
pub rare_monster_table: Box<RareMonsterAppearTable>,
|
||||||
// items on ground
|
// items on ground
|
||||||
// enemy info
|
// enemy info
|
||||||
}
|
}
|
||||||
@ -231,13 +233,19 @@ impl RoomState {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let random_seed = rand::thread_rng().gen();
|
||||||
|
let rare_monster_table = RareMonsterAppearTable::new(room_mode.episode(), random_seed);
|
||||||
|
|
||||||
Ok(RoomState {
|
Ok(RoomState {
|
||||||
monster_stats: Box::new(load_monster_stats_table(&room_mode).map_err(|_| RoomCreationError::CouldNotLoadMonsterStats(room_mode))?),
|
monster_stats: Box::new(load_monster_stats_table(&room_mode).map_err(|_| RoomCreationError::CouldNotLoadMonsterStats(room_mode))?),
|
||||||
mode: room_mode,
|
mode: room_mode,
|
||||||
random_seed: rand::thread_rng().gen(),
|
// random_seed: rand::thread_rng().gen(),
|
||||||
|
random_seed: random_seed,
|
||||||
|
rare_monster_table: Box::new(rare_monster_table.clone()),
|
||||||
name: String::from_utf16_lossy(&create_room.name).trim_matches(char::from(0)).into(),
|
name: String::from_utf16_lossy(&create_room.name).trim_matches(char::from(0)).into(),
|
||||||
password: create_room.password,
|
password: create_room.password,
|
||||||
maps: Maps::new(room_mode),
|
// maps: Maps::new(room_mode),
|
||||||
|
maps: Maps::new(room_mode, &rare_monster_table),
|
||||||
section_id,
|
section_id,
|
||||||
drop_table: Box::new(DropTable::new(room_mode.episode(), room_mode.difficulty(), section_id)),
|
drop_table: Box::new(DropTable::new(room_mode.episode(), room_mode.difficulty(), section_id)),
|
||||||
bursting: false,
|
bursting: false,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user