use super::*;
use crate::{site2::gen::PrimitiveTransform, Land};
use common::terrain::Structure as PrefabStructure;
use rand::prelude::*;
use vek::*;
const TILE_SIZE: i32 = 13;
pub struct DwarvenMine {
name: String,
bounds: Aabr<i32>,
pub(crate) alt: i32,
origin: Vec2<i32>,
}
impl DwarvenMine {
pub fn generate(
land: &Land,
rng: &mut impl Rng,
site: &Site,
wpos: Vec2<i32>,
tile_aabr: Aabr<i32>,
) -> Self {
let bounds = Aabr {
min: site.tile_wpos(tile_aabr.min),
max: site.tile_wpos(tile_aabr.max),
};
let name = format!("{} Mine", NameGen::location(rng).generate_mine());
Self {
name,
bounds,
origin: wpos - TILE_SIZE / 2,
alt: land.get_alt_approx(site.tile_center_wpos(wpos)) as i32,
}
}
pub fn name(&self) -> &str { &self.name }
pub fn spawn_rules(&self, wpos: Vec2<i32>) -> SpawnRules {
let near_entrance = wpos.distance_squared(self.origin) < 64i32.pow(2);
SpawnRules {
trees: !near_entrance,
max_warp: (!near_entrance) as i32 as f32,
..SpawnRules::default()
}
}
}
impl Structure for DwarvenMine {
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"render_mine\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "render_mine")]
fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) {
let center = self.bounds.center();
let entrance_path = "site_structures.dwarves.entrance";
let entrance_pos: Vec3<i32> = (center.x, center.y, self.alt - 37).into(); render_prefab(entrance_path, entrance_pos, painter);
let hallway0_path = "site_structures.dwarves.hallway";
let hallway0_pos: Vec3<i32> = entrance_pos + Vec3::new(-67, 8, -37);
render_prefab(hallway0_path, hallway0_pos + Vec3::new(0, 0, 0), painter);
let hallway1_path = "site_structures.dwarves.hallway1";
let hallway1_pos: Vec3<i32> = hallway0_pos + Vec3::new(-55, -7, -33);
render_prefab(hallway1_path, hallway1_pos, painter);
let mining_site_path = "site_structures.dwarves.mining_site";
let mining_site_pos: Vec3<i32> = hallway1_pos + Vec3::new(-5, 28, 21);
render_prefab(mining_site_path, mining_site_pos, painter);
let after_mining_path = "site_structures.dwarves.after_forgemaster";
let after_mining_pos: Vec3<i32> = mining_site_pos + Vec3::new(-12, -9, -3);
render_prefab(
after_mining_path,
after_mining_pos + Vec3::new(0, -2, 0),
painter,
);
let hallway2_path = "site_structures.dwarves.hallway2";
let hallway2_pos: Vec3<i32> = after_mining_pos + Vec3::new(-3, 35, -18);
render_prefab(hallway2_path, hallway2_pos, painter);
let excavation_site_path = "site_structures.dwarves.excavation_site";
let excavation_site_pos: Vec3<i32> = hallway2_pos + Vec3::new(-35, 83, -10);
render_prefab(excavation_site_path, excavation_site_pos, painter);
let forgemaster_boss_path = "site_structures.dwarves.forgemaster_boss";
let forgemaster_boss_pos: Vec3<i32> = excavation_site_pos + Vec3::new(115, 0, -17);
render_prefab(forgemaster_boss_path, forgemaster_boss_pos, painter);
let cleansing_room_path = "site_structures.dwarves.cleansing_room";
let cleansing_room_pos: Vec3<i32> = excavation_site_pos + Vec3::new(-47, -125, 6);
render_prefab(cleansing_room_path, cleansing_room_pos, painter);
let smelting_room_path = "site_structures.dwarves.smelting_room";
let smelting_room_pos: Vec3<i32> = cleansing_room_pos + Vec3::new(49, -6, 0);
render_prefab(smelting_room_path, smelting_room_pos, painter);
let forgemaster_path = "site_structures.dwarves.forgemaster_room";
let forgemaster_pos: Vec3<i32> = smelting_room_pos + Vec3::new(8, 36, 10);
render_prefab(forgemaster_path, forgemaster_pos, painter);
let random_entities: Vec<(Vec3<i32>, u8)> = vec![
(forgemaster_pos + Vec3::new(11, 20, 1), 0),
(forgemaster_pos + Vec3::new(0, 20, 1), 0),
(forgemaster_pos + Vec3::new(-11, 20, 1), 0),
];
for (pos, rot) in random_entities {
spawn_random_entity(pos, painter, rot);
}
let miner = "common.entity.dungeon.dwarven_quarry.miner";
let iron_dwarf = "common.entity.dungeon.dwarven_quarry.iron_dwarf";
let turret = "common.entity.dungeon.dwarven_quarry.turret";
let lavathrower = "common.entity.dungeon.dwarven_quarry.lavathrower";
let mine_guard = "common.entity.dungeon.dwarven_quarry.mine_guard";
let flamekeeper = "common.entity.dungeon.dwarven_quarry.flamekeeper";
let forgemaster = "common.entity.dungeon.dwarven_quarry.forgemaster";
let irongolem = "common.entity.dungeon.dwarven_quarry.irongolem";
let irongolem_key = "common.entity.dungeon.dwarven_quarry.irongolem_key";
let snaretongue_forge_key = "common.entity.dungeon.dwarven_quarry.snaretongue_forge_key";
let snaretongue_miner_key = "common.entity.dungeon.dwarven_quarry.snaretongue_miner_key";
let entrance_offset: Vec3<f32> = (20.0, -20.0, 45.0).into();
let miner_pos: Vec<(Vec3<f32>, &str)> = vec![
(
(entrance_pos + Vec3::new(-6, 0, 0)).map(|x| x as f32) + entrance_offset,
miner,
),
(
(entrance_pos + Vec3::new(-2, 0, 0)).map(|x| x as f32) + entrance_offset,
miner,
),
(
hallway0_pos.map(|x| x as f32) + Vec3::new(10.0, -4.0, 16.0),
miner,
),
(
hallway0_pos.map(|x| x as f32) + Vec3::new(-10.0, -4.0, 10.0),
miner,
),
(
hallway0_pos.map(|x| x as f32) + Vec3::new(-10.0, -6.0, 10.0),
miner,
),
(
hallway0_pos.map(|x| x as f32) + Vec3::new(-30.0, -4.0, 0.0),
miner,
),
(
hallway0_pos.map(|x| x as f32) + Vec3::new(-46.0, -4.0, -5.0),
miner,
),
(
mining_site_pos.map(|x| x as f32) + Vec3::new(14.0, 17.0, 10.0),
flamekeeper,
),
(
mining_site_pos.map(|x| x as f32) + Vec3::new(14.0, 27.0, 8.0),
mine_guard,
),
(
mining_site_pos.map(|x| x as f32) + Vec3::new(-4.0, 32.0, 8.0),
turret,
),
(
mining_site_pos.map(|x| x as f32) + Vec3::new(32.0, 32.0, 10.0),
turret,
),
(
mining_site_pos.map(|x| x as f32) + Vec3::new(14.0, 32.0, 10.0),
mine_guard,
),
(
mining_site_pos.map(|x| x as f32) + Vec3::new(-8.0, 0.0, 10.0),
miner,
),
(
mining_site_pos.map(|x| x as f32) + Vec3::new(36.0, 0.0, 10.0),
miner,
),
(
mining_site_pos.map(|x| x as f32) + Vec3::new(-8.0, 15.0, 0.0),
iron_dwarf,
),
(
mining_site_pos.map(|x| x as f32) + Vec3::new(36.0, 15.0, 0.0),
iron_dwarf,
),
(
hallway2_pos.map(|x| x as f32) + Vec3::new(-4.0, -22.0, 20.0),
miner,
),
(
hallway2_pos.map(|x| x as f32) + Vec3::new(-4.0, 7.0, 10.0),
miner,
),
(
hallway2_pos.map(|x| x as f32) + Vec3::new(-5.0, 30.0, 0.0),
mine_guard,
),
(
hallway2_pos.map(|x| x as f32) + Vec3::new(0.0, 44.0, 0.0),
iron_dwarf,
),
(
hallway2_pos.map(|x| x as f32) + Vec3::new(2.0, 44.0, 0.0),
lavathrower,
),
(
forgemaster_boss_pos.map(|x| x as f32) + Vec3::new(23.0, 1.0, 20.0),
forgemaster,
),
(
excavation_site_pos.map(|x| x as f32) + Vec3::new(0.0, -25.0, 18.0),
lavathrower,
),
(
excavation_site_pos.map(|x| x as f32) + Vec3::new(50.0, 42.0, 25.0),
mine_guard,
),
(
excavation_site_pos.map(|x| x as f32) + Vec3::new(48.0, 40.0, 12.0),
turret,
),
(
excavation_site_pos.map(|x| x as f32) + Vec3::new(44.0, 50.0, 15.0),
lavathrower,
),
(
excavation_site_pos.map(|x| x as f32) + Vec3::new(50.0, 18.0, 18.0),
turret,
),
(
excavation_site_pos.map(|x| x as f32) + Vec3::new(50.0, 10.0, 18.0),
lavathrower,
),
(
excavation_site_pos.map(|x| x as f32) + Vec3::new(-1.0, 44.0, 20.0),
lavathrower,
),
(
excavation_site_pos.map(|x| x as f32) + Vec3::new(-1.0, 42.0, 20.0),
mine_guard,
),
(
excavation_site_pos.map(|x| x as f32) + Vec3::new(-30.0, -12.0, 8.0),
irongolem_key,
),
(
cleansing_room_pos.map(|x| x as f32) + Vec3::new(-10.0, -5.0, 10.0),
snaretongue_forge_key,
),
(
cleansing_room_pos.map(|x| x as f32) + Vec3::new(-14.0, 60.0, -10.0),
snaretongue_miner_key,
),
(
smelting_room_pos.map(|x| x as f32) + Vec3::new(-8.0, -2.0, 5.0),
lavathrower,
),
(
smelting_room_pos.map(|x| x as f32) + Vec3::new(20.0, -10.0, 5.0),
lavathrower,
),
(
forgemaster_pos.map(|x| x as f32) + Vec3::new(0.0, 4.0, 3.0),
irongolem,
),
];
let entity_group_positions = vec![
(
smelting_room_pos.map(|x| x as f32) + Vec3::new(26.0, -10.0, 5.0),
vec![iron_dwarf],
2,
5.0,
4.0,
),
(
smelting_room_pos.map(|x| x as f32) + Vec3::new(6.0, 2.0, 12.0),
vec![iron_dwarf],
2,
5.0,
4.0,
),
(
smelting_room_pos.map(|x| x as f32) + Vec3::new(8.0, -10.0, 18.0),
vec![miner, iron_dwarf, mine_guard],
4,
5.0,
4.0,
),
(
hallway1_pos.map(|x| x as f32) + Vec3::new(-5.0, 2.0, 0.0),
vec![miner, iron_dwarf, mine_guard],
2,
5.0,
4.0,
),
(
hallway1_pos.map(|x| x as f32) + Vec3::new(-20.0, 10.0, 0.0),
vec![miner, iron_dwarf, mine_guard],
2,
5.0,
4.0,
),
(
hallway1_pos.map(|x| x as f32) + Vec3::new(4.0, 15.0, 0.0),
vec![miner, iron_dwarf, mine_guard],
2,
5.0,
4.0,
),
(
hallway1_pos.map(|x| x as f32) + Vec3::new(-5.0, -8.0, 18.0),
vec![miner, iron_dwarf, mine_guard],
3,
5.0,
4.0,
),
(
hallway1_pos.map(|x| x as f32) + Vec3::new(-5.0, -8.0, 30.0),
vec![miner, iron_dwarf, mine_guard],
3,
5.0,
4.0,
),
(
hallway1_pos.map(|x| x as f32) + Vec3::new(-20.0, 18.0, 10.0),
vec![miner, iron_dwarf, mine_guard],
3,
5.0,
4.0,
),
(
hallway1_pos.map(|x| x as f32) + Vec3::new(4.0, 15.0, 12.0),
vec![miner, iron_dwarf, mine_guard],
3,
5.0,
4.0,
),
];
for (position, entity_paths, num_entities, max_distance, entity_distance) in
entity_group_positions
{
spawn_entities(
position,
painter,
&entity_paths,
num_entities,
max_distance,
entity_distance,
);
}
for (pos, entity) in miner_pos {
spawn_entity(pos, painter, entity);
}
}
}
fn spawn_entity(pos: Vec3<f32>, painter: &Painter, entity_path: &str) {
let mut rng = thread_rng();
painter.spawn(
EntityInfo::at(pos)
.with_asset_expect(entity_path, &mut rng, None)
.with_no_flee(),
);
}
fn spawn_entities(
pos: Vec3<f32>,
painter: &Painter,
entity_paths: &[&str],
num_entities: u32,
max_distance: f32,
entity_distance: f32,
) {
let mut rng = thread_rng();
let num_paths = entity_paths.len();
let side_length = (num_entities as f32).sqrt().ceil() as u32;
let spacing = entity_distance;
for i in 0..num_entities {
let path_index = rng.gen_range(0..num_paths);
let entity_path = entity_paths[path_index];
let row = i / side_length;
let col = i % side_length;
let x_offset = col as f32 * spacing - max_distance;
let y_offset = row as f32 * spacing - max_distance;
let spawn_pos = pos + Vec3::new(x_offset, y_offset, 0.0);
painter.spawn(EntityInfo::at(spawn_pos).with_asset_expect(entity_path, &mut rng, None));
}
}
fn render_prefab(file_path: &str, position: Vec3<i32>, painter: &Painter) {
let asset_handle = PrefabStructure::load_group(file_path);
let prefab_structure = asset_handle.read()[0].clone();
painter
.prim(Primitive::Prefab(Box::new(prefab_structure.clone())))
.translate(position)
.fill(Fill::Prefab(Box::new(prefab_structure), position, 0));
}
fn spawn_random_entity(pos: Vec3<i32>, painter: &Painter, rot: u8) {
let mut rng = thread_rng();
let entities = [
"common.entity.dungeon.dwarven_quarry.miner",
"common.entity.dungeon.dwarven_quarry.turret",
"common.entity.dungeon.dwarven_quarry.iron_dwarf",
];
let sprites = [
SpriteKind::Anvil,
SpriteKind::Forge,
SpriteKind::RepairBench,
SpriteKind::DungeonChest5,
];
let random_number = rng.gen_range(0..=10);
if random_number <= 3 {
let pos_f32 = pos.map(|coord| coord as f32);
let random_entity_index = rng.gen_range(0..entities.len());
let random_entity = entities[random_entity_index];
spawn_entity(pos_f32, painter, random_entity);
} else if random_number <= 9 {
let random_sprite_index = rng.gen_range(0..sprites.len());
let random_sprite = sprites[random_sprite_index];
painter.rotated_sprite(pos, random_sprite, rot);
} else {
return;
}
}