diff --git a/src/camera.rs b/src/camera.rs index e304254..ab9a670 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -63,7 +63,7 @@ pub fn render_camera(ecs: &World, ctx: &mut Rltk) { if pos.x < max_x && pos.y < max_y && pos.x >= min_x && pos.y >= min_y { let mut draw = false; let mut fg = render.fg; - let bg = if render.bg == (RGB { r: 0.0, g: 0.0, b: 0.0 }) { + let mut bg = if render.bg == (RGB { r: 0.0, g: 0.0, b: 0.0 }) { crate::map::themes::get_tile_renderables_for_id(idx, &*map).2 } else { render.bg @@ -76,10 +76,15 @@ pub fn render_camera(ecs: &World, ctx: &mut Rltk) { // We don't darken BG, because get_tile_renderables_for_id handles this. } // Draw entities with minds within telepath range - if map.telepath_tiles[idx] { - let has_mind = minds.get(*ent); - if let Some(_) = has_mind { - draw = true; + if !draw { + if map.telepath_tiles[idx] { + let has_mind = minds.get(*ent); + if let Some(_) = has_mind { + draw = true; + if !map.revealed_tiles[idx] { + bg = RGB::named(BLACK); + } + } } } // Draw all props diff --git a/src/components.rs b/src/components.rs index 750a16b..6149cf0 100644 --- a/src/components.rs +++ b/src/components.rs @@ -361,6 +361,9 @@ pub struct Confusion { pub turns: i32, } +#[derive(Component, Serialize, Deserialize, Clone)] +pub struct Blind {} + #[derive(Component, Serialize, Deserialize, Clone)] pub struct MagicMapper {} diff --git a/src/main.rs b/src/main.rs index 9c07018..346652a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -619,6 +619,7 @@ fn main() -> rltk::BError { gs.ecs.register::(); gs.ecs.register::(); gs.ecs.register::(); + gs.ecs.register::(); gs.ecs.register::(); gs.ecs.register::(); gs.ecs.register::(); diff --git a/src/melee_combat_system.rs b/src/melee_combat_system.rs index 530680a..0d19607 100644 --- a/src/melee_combat_system.rs +++ b/src/melee_combat_system.rs @@ -2,8 +2,8 @@ use super::{ effects::{add_effect, EffectType, Targets}, gamelog, gamesystem, gui::renderable_colour, - ArmourClassBonus, Attributes, EquipmentSlot, Equipped, HungerClock, HungerState, MeleeWeapon, MultiAttack, Name, - NaturalAttacks, ParticleBuilder, Pools, Position, Renderable, Skill, Skills, ToHitBonus, WantsToMelee, + ArmourClassBonus, Attributes, Blind, EquipmentSlot, Equipped, HungerClock, HungerState, MeleeWeapon, MultiAttack, + Name, NaturalAttacks, ParticleBuilder, Pools, Position, Renderable, Skill, Skills, ToHitBonus, WantsToMelee, WeaponAttribute, }; use rltk::prelude::*; @@ -30,6 +30,7 @@ impl<'a> System<'a> for MeleeCombatSystem { ReadStorage<'a, ToHitBonus>, ReadStorage<'a, HungerClock>, ReadStorage<'a, MultiAttack>, + ReadStorage<'a, Blind>, WriteExpect<'a, rltk::RandomNumberGenerator>, ); @@ -52,6 +53,7 @@ impl<'a> System<'a> for MeleeCombatSystem { to_hit, hunger_clock, multi_attackers, + blind_entities, mut rng, ) = data; @@ -119,10 +121,8 @@ impl<'a> System<'a> for MeleeCombatSystem { if target_pools.hit_points.current <= 0 { break; } - let weapon_info = attack.0; let attack_verb = attack.1; - // Get all offensive bonuses let d20 = rng.roll_dice(1, 20); let attribute_hit_bonus = attacker_attributes.dexterity.bonus; @@ -134,6 +134,9 @@ impl<'a> System<'a> for MeleeCombatSystem { } } let mut status_hit_bonus = 0; + if let Some(_) = blind_entities.get(entity) { + status_hit_bonus -= 4; + }; let hc = hunger_clock.get(entity); if let Some(hc) = hc { match hc.state { diff --git a/src/visibility_system.rs b/src/visibility_system.rs index c662a43..29bee19 100644 --- a/src/visibility_system.rs +++ b/src/visibility_system.rs @@ -1,9 +1,11 @@ -use super::{gamelog, BlocksVisibility, Hidden, Map, Name, Player, Position, Telepath, Viewshed}; +use super::{gamelog, Blind, BlocksVisibility, Hidden, Map, Name, Player, Position, Telepath, Viewshed}; use rltk::{FieldOfViewAlg::SymmetricShadowcasting, Point}; use specs::prelude::*; pub struct VisibilitySystem {} +const BLIND_TELEPATHY_RANGE_MULTIPLIER: i32 = 3; + impl<'a> System<'a> for VisibilitySystem { type SystemData = ( WriteExpect<'a, Map>, @@ -15,12 +17,24 @@ impl<'a> System<'a> for VisibilitySystem { ReadStorage<'a, Player>, WriteStorage<'a, Hidden>, ReadStorage<'a, Name>, + ReadStorage<'a, Blind>, ReadStorage<'a, BlocksVisibility>, ); fn run(&mut self, data: Self::SystemData) { - let (mut map, mut rng, entities, mut viewshed, mut telepath, pos, player, mut hidden, names, blocks_visibility) = - data; + let ( + mut map, + mut rng, + entities, + mut viewshed, + mut telepath, + pos, + player, + mut hidden, + names, + blind_entities, + blocks_visibility, + ) = data; map.view_blocked.clear(); for (block_pos, _block) in (&pos, &blocks_visibility).join() { @@ -31,8 +45,9 @@ impl<'a> System<'a> for VisibilitySystem { for (ent, viewshed, pos) in (&entities, &mut viewshed, &pos).join() { if viewshed.dirty { viewshed.dirty = false; + let mut range = if let Some(is_blind) = blind_entities.get(ent) { 1 } else { viewshed.range }; let origin = Point::new(pos.x, pos.y); - viewshed.visible_tiles = SymmetricShadowcasting.field_of_view(origin, viewshed.range, &*map); + viewshed.visible_tiles = SymmetricShadowcasting.field_of_view(origin, range, &*map); viewshed.visible_tiles.retain(|p| { p.x >= 0 && p.x < map.width @@ -78,8 +93,11 @@ impl<'a> System<'a> for VisibilitySystem { for (ent, telepath, pos) in (&entities, &mut telepath, &pos).join() { if telepath.dirty { telepath.dirty = false; - - telepath.telepath_tiles = fast_fov(pos.x, pos.y, telepath.range); + let mut range = telepath.range; + if let Some(is_blind) = blind_entities.get(ent) { + range *= BLIND_TELEPATHY_RANGE_MULTIPLIER; + } + telepath.telepath_tiles = fast_fov(pos.x, pos.y, range); telepath.telepath_tiles.retain(|p| p.x >= 0 && p.x < map.width && p.y >= 0 && p.y < map.height); // If this is the player, reveal what they can see