|
@ -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 {
|
|
|
|
|
|
enemy_data: map_variants.iter().fold(Vec::new(), |mut enemy_data, map_variant| {
|
|
|
|
|
|
enemy_data.append(&mut enemy_data_from_map_data(map_variant, &room_mode.episode()));
|
|
|
|
|
|
enemy_data
|
|
|
|
|
|
}),
|
|
|
|
|
|
object_data: map_variants.iter().map(|map_variant| {
|
|
|
|
|
|
objects_from_map_data(map_variant.obj_file().into(), &room_mode.episode(), &map_variant.map)
|
|
|
|
|
|
}).flatten().collect(),
|
|
|
|
|
|
map_variants,
|
|
|
|
|
|
|
|
|
let mut maps = Maps {
|
|
|
|
|
|
enemy_data: map_variants.iter()
|
|
|
|
|
|
.fold(Vec::new(), |mut enemy_data, map_variant| {
|
|
|
|
|
|
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));
|
|
|
|
|
|
enemy_data
|
|
|
|
|
|
}),
|
|
|
|
|
|
object_data: map_variants.iter()
|
|
|
|
|
|
.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();
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|